File: service_worker_url_request_job.h

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (341 lines) | stat: -rw-r--r-- 12,910 bytes parent folder | download
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_