1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_URL_LOADER_H_ 6 #define CONTENT_BROWSER_APPCACHE_APPCACHE_URL_LOADER_H_ 7 8 #include <memory> 9 10 #include "base/logging.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/sequence_checker.h" 14 #include "base/time/time.h" 15 #include "content/browser/appcache/appcache_entry.h" 16 #include "content/browser/appcache/appcache_request_handler.h" 17 #include "content/browser/appcache/appcache_storage.h" 18 #include "content/common/content_export.h" 19 #include "mojo/public/cpp/bindings/pending_receiver.h" 20 #include "mojo/public/cpp/bindings/pending_remote.h" 21 #include "mojo/public/cpp/bindings/receiver.h" 22 #include "mojo/public/cpp/bindings/remote.h" 23 #include "mojo/public/cpp/system/data_pipe.h" 24 #include "net/http/http_byte_range.h" 25 #include "services/network/public/mojom/url_loader.mojom-forward.h" 26 #include "third_party/blink/public/mojom/appcache/appcache_info.mojom-forward.h" 27 #include "url/gurl.h" 28 29 namespace net { 30 class HttpRequestHeaders; 31 class HttpResponseInfo; 32 } // namespace net 33 34 namespace network { 35 class NetToMojoPendingBuffer; 36 } 37 38 namespace content { 39 40 class AppCacheRequest; 41 class AppCacheResponseInfo; 42 class AppCacheResponseReader; 43 44 // network::mojom::URLLoader that retrieves responses stored in an AppCache. 45 class CONTENT_EXPORT AppCacheURLLoader : public AppCacheStorage::Delegate, 46 public network::mojom::URLLoader { 47 public: 48 enum class DeliveryType { 49 kAwaitingDeliverCall, 50 kAppCached, 51 kNetwork, 52 kError, 53 }; 54 55 // Use AppCacheRequestHandler::CreateJob() instead of calling the constructor 56 // directly. 57 // 58 // The constructor is exposed for std::make_unique. 59 AppCacheURLLoader( 60 AppCacheRequest* appcache_request, 61 AppCacheStorage* storage, 62 AppCacheRequestHandler::AppCacheLoaderCallback loader_callback); 63 64 ~AppCacheURLLoader() override; 65 66 // Sets up the bindings. 67 void Start(base::OnceClosure continuation, 68 const network::ResourceRequest& resource_request, 69 mojo::PendingReceiver<network::mojom::URLLoader> receiver, 70 mojo::PendingRemote<network::mojom::URLLoaderClient> client); 71 72 // True if the loader was started. 73 bool IsStarted() const; 74 75 // True if the loader is waiting for instructions. IsWaiting()76 bool IsWaiting() const { 77 return delivery_type_ == DeliveryType::kAwaitingDeliverCall; 78 } 79 80 // True if the loader is delivering a response from the cache. IsDeliveringAppCacheResponse()81 bool IsDeliveringAppCacheResponse() const { 82 return delivery_type_ == DeliveryType::kAppCached; 83 } 84 85 // True if the loader is delivering a response from the network. IsDeliveringNetworkResponse()86 bool IsDeliveringNetworkResponse() const { 87 return delivery_type_ == DeliveryType::kNetwork; 88 } 89 90 // True if the loader is delivering an error response. IsDeliveringErrorResponse()91 bool IsDeliveringErrorResponse() const { 92 return delivery_type_ == DeliveryType::kError; 93 } 94 set_delivery_type(DeliveryType delivery_type)95 void set_delivery_type(DeliveryType delivery_type) { 96 delivery_type_ = delivery_type; 97 } 98 99 // True if the cache entry was not found in the cache. IsCacheEntryNotFound()100 bool IsCacheEntryNotFound() const { return cache_entry_not_found_; } 101 102 // Informs the loader of what response it should deliver. 103 // 104 // Each loader should receive exactly one call to a Deliver*() method. Loaders 105 // will sit idle and wait indefinitely until one of the Deliver*() methods is 106 // called. 107 void DeliverAppCachedResponse(const GURL& manifest_url, 108 int64_t cache_id, 109 const AppCacheEntry& entry, 110 bool is_fallback); 111 112 // Informs the loader that it should deliver the response from the network. 113 // This is generally controlled by the entries in the manifest file. 114 // 115 // Each loader should receive exactly one call to a Deliver*() method. Loaders 116 // will sit idle and wait indefinitely until one of the Deliver*() methods is 117 // called. 118 void DeliverNetworkResponse(); 119 120 // Informs the loader that it should deliver an error response. 121 // 122 // Each loader should receive exactly one call to a Deliver*() method. Loaders 123 // will sit idle and wait indefinitely until one of the Deliver*() methods is 124 // called. 125 void DeliverErrorResponse(); 126 127 base::WeakPtr<AppCacheURLLoader> GetWeakPtr(); 128 129 // network::mojom::URLLoader: 130 void FollowRedirect(const std::vector<std::string>& removed_headers, 131 const net::HttpRequestHeaders& modified_headers, 132 const base::Optional<GURL>& new_url) override; 133 void SetPriority(net::RequestPriority priority, 134 int32_t intra_priority_value) override; 135 void PauseReadingBodyFromNet() override; 136 void ResumeReadingBodyFromNet() override; 137 138 void DeleteIfNeeded(); 139 140 private: is_range_request()141 bool is_range_request() const { return range_requested_.IsValid(); } 142 143 void InitializeRangeRequestInfo(const net::HttpRequestHeaders& headers); 144 void SetupRangeResponse(); 145 146 // Invokes the loader callback which is expected to setup the mojo binding. 147 void CallLoaderCallback(base::OnceClosure continuation); 148 149 // AppCacheStorage::Delegate: 150 void OnResponseInfoLoaded(AppCacheResponseInfo* response_info, 151 int64_t response_id) override; 152 153 void ContinueOnResponseInfoLoaded( 154 scoped_refptr<AppCacheResponseInfo> response_info); 155 156 // AppCacheResponseReader completion callback. 157 void OnReadComplete(int result); 158 159 // Callback invoked when the data pipe can be written to. 160 void OnResponseBodyStreamReady(MojoResult result); 161 162 // Schedules a task to delete self with some clean-ups. This is also used as 163 // a mojo binding error handler. 164 void DeleteSoon(); 165 166 void SendResponseInfo(); 167 void ReadMore(); 168 void NotifyCompleted(int error_code); 169 170 // True if the AppCache entry is not found. 171 bool cache_entry_not_found_ = false; 172 173 // The loader's delivery status. 174 DeliveryType delivery_type_ = DeliveryType::kAwaitingDeliverCall; 175 176 // Byte range request if any. 177 net::HttpByteRange range_requested_; 178 179 std::unique_ptr<net::HttpResponseInfo> range_response_info_; 180 181 // The response details. 182 scoped_refptr<AppCacheResponseInfo> info_; 183 184 // Used to read the cache. 185 std::unique_ptr<AppCacheResponseReader> reader_; 186 187 base::WeakPtr<AppCacheStorage> storage_; 188 189 // Time when the request started. 190 base::TimeTicks start_time_tick_; 191 192 // Timing information for the most recent request. Its start times are 193 // populated in DeliverAppCachedResponse(). 194 net::LoadTimingInfo load_timing_info_; 195 196 GURL manifest_url_; 197 int64_t cache_id_ = blink::mojom::kAppCacheNoCacheId; 198 AppCacheEntry entry_; 199 bool is_fallback_ = false; 200 201 // Receiver of the URLLoaderClient with us. 202 mojo::Receiver<network::mojom::URLLoader> receiver_{this}; 203 204 // The URLLoaderClient remote. We call this interface with notifications 205 // about the URL load 206 mojo::Remote<network::mojom::URLLoaderClient> client_; 207 208 // The data pipe used to transfer AppCache data to the client. 209 mojo::ScopedDataPipeConsumerHandle consumer_handle_; 210 mojo::ScopedDataPipeProducerHandle response_body_stream_; 211 scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; 212 mojo::SimpleWatcher writable_handle_watcher_; 213 214 // The Callback to be invoked in the network service land to indicate if 215 // the resource request can be serviced via the AppCache. 216 AppCacheRequestHandler::AppCacheLoaderCallback loader_callback_; 217 218 // The AppCacheRequest instance, used to inform the loader job about range 219 // request headers. Not owned by this class. 220 const base::WeakPtr<AppCacheRequest> appcache_request_; 221 222 bool is_deleting_soon_ = false; 223 const bool is_main_resource_load_; 224 225 SEQUENCE_CHECKER(sequence_checker_); 226 227 base::WeakPtrFactory<AppCacheURLLoader> weak_factory_{this}; 228 DISALLOW_COPY_AND_ASSIGN(AppCacheURLLoader); 229 }; 230 231 } // namespace content 232 233 #endif // CONTENT_BROWSER_APPCACHE_APPCACHE_URL_LOADER_H_ 234