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/check.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( 131 const std::vector<std::string>& removed_headers, 132 const net::HttpRequestHeaders& modified_headers, 133 const net::HttpRequestHeaders& modified_cors_exempt_headers, 134 const base::Optional<GURL>& new_url) override; 135 void SetPriority(net::RequestPriority priority, 136 int32_t intra_priority_value) override; 137 void PauseReadingBodyFromNet() override; 138 void ResumeReadingBodyFromNet() override; 139 140 void DeleteIfNeeded(); 141 142 private: is_range_request()143 bool is_range_request() const { return range_requested_.IsValid(); } 144 145 void InitializeRangeRequestInfo(const net::HttpRequestHeaders& headers); 146 void SetupRangeResponse(); 147 148 // Invokes the loader callback which is expected to setup the mojo binding. 149 void CallLoaderCallback(base::OnceClosure continuation); 150 151 // AppCacheStorage::Delegate: 152 void OnResponseInfoLoaded(AppCacheResponseInfo* response_info, 153 int64_t response_id) override; 154 155 void ContinueOnResponseInfoLoaded( 156 scoped_refptr<AppCacheResponseInfo> response_info); 157 158 // AppCacheResponseReader completion callback. 159 void OnReadComplete(int result); 160 161 // Callback invoked when the data pipe can be written to. 162 void OnResponseBodyStreamReady(MojoResult result); 163 164 // Schedules a task to delete self with some clean-ups. This is also used as 165 // a mojo binding error handler. 166 void DeleteSoon(); 167 168 void SendResponseInfo(); 169 void ReadMore(); 170 void NotifyCompleted(int error_code); 171 172 // True if the AppCache entry is not found. 173 bool cache_entry_not_found_ = false; 174 175 // The loader's delivery status. 176 DeliveryType delivery_type_ = DeliveryType::kAwaitingDeliverCall; 177 178 // Byte range request if any. 179 net::HttpByteRange range_requested_; 180 181 std::unique_ptr<net::HttpResponseInfo> range_response_info_; 182 183 // The response details. 184 scoped_refptr<AppCacheResponseInfo> info_; 185 186 // Used to read the cache. 187 std::unique_ptr<AppCacheResponseReader> reader_; 188 189 base::WeakPtr<AppCacheStorage> storage_; 190 191 // Time when the request started. 192 base::TimeTicks start_time_tick_; 193 194 // Timing information for the most recent request. Its start times are 195 // populated in DeliverAppCachedResponse(). 196 net::LoadTimingInfo load_timing_info_; 197 198 GURL manifest_url_; 199 int64_t cache_id_ = blink::mojom::kAppCacheNoCacheId; 200 AppCacheEntry entry_; 201 bool is_fallback_ = false; 202 203 // Receiver of the URLLoaderClient with us. 204 mojo::Receiver<network::mojom::URLLoader> receiver_{this}; 205 206 // The URLLoaderClient remote. We call this interface with notifications 207 // about the URL load 208 mojo::Remote<network::mojom::URLLoaderClient> client_; 209 210 // The data pipe used to transfer AppCache data to the client. 211 mojo::ScopedDataPipeConsumerHandle consumer_handle_; 212 mojo::ScopedDataPipeProducerHandle response_body_stream_; 213 scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; 214 mojo::SimpleWatcher writable_handle_watcher_; 215 216 // The Callback to be invoked in the network service land to indicate if 217 // the resource request can be serviced via the AppCache. 218 AppCacheRequestHandler::AppCacheLoaderCallback loader_callback_; 219 220 // The AppCacheRequest instance, used to inform the loader job about range 221 // request headers. Not owned by this class. 222 const base::WeakPtr<AppCacheRequest> appcache_request_; 223 224 bool is_deleting_soon_ = false; 225 226 SEQUENCE_CHECKER(sequence_checker_); 227 228 base::WeakPtrFactory<AppCacheURLLoader> weak_factory_{this}; 229 DISALLOW_COPY_AND_ASSIGN(AppCacheURLLoader); 230 }; 231 232 } // namespace content 233 234 #endif // CONTENT_BROWSER_APPCACHE_APPCACHE_URL_LOADER_H_ 235