1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_URL_REQUEST_JOB_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_URL_REQUEST_JOB_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/request_context_frame_type.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "net/http/http_byte_range.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_status.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
#include "url/gurl.h"
namespace net {
class IOBuffer;
} // namespace net
namespace storage {
class BlobDataHandle;
class BlobStorageContext;
} // namespace storage
namespace content {
class ResourceContext;
class ResourceRequestBodyImpl;
class ServiceWorkerBlobReader;
class ServiceWorkerStreamReader;
class ServiceWorkerFetchDispatcher;
class ServiceWorkerVersion;
class Stream;
class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
public:
class CONTENT_EXPORT Delegate {
public:
virtual ~Delegate() {}
// Will be invoked before the request is restarted. The caller
// can use this opportunity to grab state from the
// ServiceWorkerURLRequestJob to determine how it should behave when the
// request is restarted.
virtual void OnPrepareToRestart() = 0;
// Returns the ServiceWorkerVersion fetch events for this request job should
// be dispatched to. If no appropriate worker can be determined, returns
// nullptr and sets |*result| to an appropriate error.
virtual ServiceWorkerVersion* GetServiceWorkerVersion(
ServiceWorkerMetrics::URLRequestJobResult* result) = 0;
// Called after dispatching the fetch event to determine if processing of
// the request should still continue, or if processing should be aborted.
// When false is returned, this sets |*result| to an appropriate error.
virtual bool RequestStillValid(
ServiceWorkerMetrics::URLRequestJobResult* result);
// Called to signal that loading failed, and that the resource being loaded
// was a main resource.
virtual void MainResourceLoadFailed() {}
};
ServiceWorkerURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const std::string& client_id,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const ResourceContext* resource_context,
FetchRequestMode request_mode,
FetchCredentialsMode credentials_mode,
FetchRedirectMode redirect_mode,
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
scoped_refptr<ResourceRequestBodyImpl> body,
ServiceWorkerFetchType fetch_type,
const base::Optional<base::TimeDelta>& timeout,
Delegate* delegate);
~ServiceWorkerURLRequestJob() override;
const ResourceContext* resource_context() const { return resource_context_; }
bool did_navigation_preload() const { return did_navigation_preload_; }
// Sets the response type.
// When an in-flight request possibly needs CORS check, use
// FallbackToNetworkOrRenderer. This method will decide whether the request
// can directly go to the network or should fallback to a renderer to send
// CORS preflight. You can use FallbackToNetwork only when, like main resource
// or foreign fetch cases, it's apparent that the request should go to the
// network directly.
// TODO(shimazu): Update the comment when what should we do at foreign fetch
// fallback is determined: crbug.com/604084
void FallbackToNetwork();
void FallbackToNetworkOrRenderer();
void ForwardToServiceWorker();
// Tells the job to abort with a start error. Currently this is only called
// because the controller was lost. This function could be made more generic
// if needed later.
void FailDueToLostController();
bool ShouldFallbackToNetwork() const {
return response_type_ == FALLBACK_TO_NETWORK;
}
bool ShouldForwardToServiceWorker() const {
return response_type_ == FORWARD_TO_SERVICE_WORKER;
}
// net::URLRequestJob overrides:
void Start() override;
void Kill() override;
net::LoadState GetLoadState() const override;
bool GetCharset(std::string* charset) override;
bool GetMimeType(std::string* mime_type) const override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override;
int GetResponseCode() const override;
void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
int ReadRawData(net::IOBuffer* buf, int buf_size) override;
//----------------------------------------------------------------------------
// The following are intended for use by ServiceWorker(Blob|Stream)Reader.
void OnResponseStarted();
void OnReadRawDataComplete(int bytes_read);
void RecordResult(ServiceWorkerMetrics::URLRequestJobResult result);
//----------------------------------------------------------------------------
base::WeakPtr<ServiceWorkerURLRequestJob> GetWeakPtr();
private:
class FileSizeResolver;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
LostActiveVersion);
enum ResponseType {
NOT_DETERMINED,
FAIL_DUE_TO_LOST_CONTROLLER,
FALLBACK_TO_NETWORK,
FALLBACK_TO_RENDERER, // Use this when falling back with CORS check
FORWARD_TO_SERVICE_WORKER
};
enum ResponseBodyType {
UNKNOWN,
BLOB,
STREAM,
};
// We start processing the request if Start() is called AND response_type_
// is determined.
void MaybeStartRequest();
void StartRequest();
// Creates ServiceWorkerFetchRequest from |request_| and |body_|.
std::unique_ptr<ServiceWorkerFetchRequest> CreateFetchRequest();
// Creates BlobDataHandle of the request body from |body_|. This handle
// |request_body_blob_data_handle_| will be deleted when
// ServiceWorkerURLRequestJob is deleted.
// This must not be called until all files in |body_| with unknown size have
// their sizes populated.
void CreateRequestBodyBlob(std::string* blob_uuid, uint64_t* blob_size);
// For FORWARD_TO_SERVICE_WORKER case.
void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version);
void DidDispatchFetchEvent(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
const scoped_refptr<ServiceWorkerVersion>& version);
void SetResponse(const ServiceWorkerResponse& response);
// Populates |http_response_headers_|.
void CreateResponseHeader(int status_code,
const std::string& status_text,
const ServiceWorkerHeaderMap& headers);
// Creates |http_response_info_| using |http_response_headers_| and calls
// NotifyHeadersComplete.
void CommitResponseHeader();
// Creates and commits a response header indicating error.
void DeliverErrorResponse();
// Restarts this job to fallback to network.
// This can be called after StartRequest.
void FinalizeFallbackToNetwork();
// Sends back a response with fall_back_required set as true to trigger
// subsequent network requests with CORS checking.
// This can be called after StartRequest.
void FinalizeFallbackToRenderer();
// True if need to send back a response with fall_back_required set as true to
// trigger subsequent network requests with CORS checking.
bool IsFallbackToRendererNeeded() const;
// For UMA.
void SetResponseBodyType(ResponseBodyType type);
bool ShouldRecordResult();
void RecordStatusZeroResponseError(
blink::WebServiceWorkerResponseError error);
const net::HttpResponseInfo* http_info() const;
// Invoke callbacks before invoking corresponding URLRequestJob methods.
void NotifyHeadersComplete();
void NotifyStartError(net::URLRequestStatus status);
void NotifyRestartRequired();
// Wrapper that gathers parameters to |on_start_completed_callback_| and then
// calls it.
void OnStartCompleted() const;
bool IsMainResourceLoad() const;
// For waiting for files sizes of request body files with unknown sizes.
bool HasRequestBody();
void RequestBodyFileSizesResolved(bool success);
// Called back from
// ServiceWorkerFetchEventDispatcher::MaybeStartNavigationPreload when the
// navigation preload response starts.
void OnNavigationPreloadResponse();
void MaybeReportNavigationPreloadMetrics();
// Not owned.
Delegate* delegate_;
// Timing info to show on the popup in Devtools' Network tab.
net::LoadTimingInfo load_timing_info_;
// When the worker was asked to prepare for the fetch event. Preparation may
// include activation and startup.
base::TimeTicks worker_start_time_;
// When the worker confirmed it's ready for the fetch event. If it was already
// activated and running when asked to prepare, this should be nearly the same
// as |worker_start_time_|).
base::TimeTicks worker_ready_time_;
// When the response started.
base::Time response_time_;
// When the navigation preload response started.
base::TimeTicks navigation_preload_response_time_;
// True if the worker was already in ACTIVATED status when asked to prepare
// for the fetch event.
bool worker_already_activated_ = false;
// The status the worker was in when asked to prepare for the fetch event.
EmbeddedWorkerStatus initial_worker_status_ = EmbeddedWorkerStatus::STOPPED;
// If worker startup occurred during preparation, the situation that startup
// occurred in.
ServiceWorkerMetrics::StartSituation worker_start_situation_ =
ServiceWorkerMetrics::StartSituation::UNKNOWN;
// True if navigation preload was enabled.
bool did_navigation_preload_ = false;
// True if navigation preload metrics were reported.
bool reported_navigation_preload_metrics_ = false;
ResponseType response_type_;
// True if URLRequestJob::Start() has been called.
bool is_started_;
net::HttpByteRange byte_range_;
std::unique_ptr<net::HttpResponseInfo> range_response_info_;
std::unique_ptr<net::HttpResponseInfo> http_response_info_;
// Headers that have not yet been committed to |http_response_info_|.
scoped_refptr<net::HttpResponseHeaders> http_response_headers_;
std::vector<GURL> response_url_list_;
blink::WebServiceWorkerResponseType service_worker_response_type_;
// Used when response type is FORWARD_TO_SERVICE_WORKER.
std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
std::string client_id_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
const ResourceContext* resource_context_;
// Only one of |blob_reader_| and |stream_reader_| can be non-null.
std::unique_ptr<ServiceWorkerBlobReader> blob_reader_;
std::unique_ptr<ServiceWorkerStreamReader> stream_reader_;
FetchRequestMode request_mode_;
FetchCredentialsMode credentials_mode_;
FetchRedirectMode redirect_mode_;
const ResourceType resource_type_;
RequestContextType request_context_type_;
RequestContextFrameType frame_type_;
bool fall_back_required_;
// ResourceRequestBody has a collection of BlobDataHandles attached to it
// using the userdata mechanism. So we have to keep it not to free the blobs.
scoped_refptr<ResourceRequestBodyImpl> body_;
std::unique_ptr<storage::BlobDataHandle> request_body_blob_data_handle_;
ServiceWorkerFetchType fetch_type_;
base::Optional<base::TimeDelta> timeout_;
ResponseBodyType response_body_type_ = UNKNOWN;
bool did_record_result_ = false;
bool response_is_in_cache_storage_ = false;
std::string response_cache_storage_cache_name_;
ServiceWorkerHeaderList cors_exposed_header_names_;
std::unique_ptr<FileSizeResolver> file_size_resolver_;
base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJob);
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_URL_REQUEST_JOB_H_
|