summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
blob: d6b9c5edf8c97cee9ae69535dbf67707061b466a (plain)
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
/*
 * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_H_

#include <memory>

#include "base/macros.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

class ExecutionContext;
class KURL;
class LocalFrame;
class ResourceRequest;
class SecurityOrigin;
class ThreadableLoaderClient;

// Useful for doing loader operations from any thread (not threadsafe, just able
// to run on threads other than the main thread).
//
// Can perform requests either synchronously or asynchronously. Requests are
// asynchronous by default, and this behavior can be controlled by passing
// a ResourceLoaderOptions with synchronous_policy == kRequestSynchronously to
// the constructor.
// In either case, Start() must be called to actaully begin the request.
class CORE_EXPORT ThreadableLoader final
    : public GarbageCollected<ThreadableLoader>,
      private RawResourceClient {
  USING_GARBAGE_COLLECTED_MIXIN(ThreadableLoader);

 public:
  // ThreadableLoaderClient methods are never called before Start() call.
  //
  // Loading is separated into the constructor and the Start() method in order
  // to:
  // - reduce work done in a constructor
  // - not to ask the users to handle failures in the constructor and other
  //   async failures separately
  //
  // Loading completes when one of the following methods are called:
  // - DidFinishLoading()
  // - DidFail()
  // - DidFailAccessControlCheck()
  // - DidFailRedirectCheck()
  // After any of these methods is called, the loader won't call any of the
  // ThreadableLoaderClient methods.
  //
  // When ThreadableLoader::Cancel() is called,
  // ThreadableLoaderClient::DidFail() is called with a ResourceError
  // with IsCancellation() returning true, if any of DidFinishLoading()
  // or DidFail.*() methods have not been called yet. (DidFail() may be
  // called with a ResourceError with IsCancellation() returning true
  // also for cancellation happened inside the loader.)
  //
  // ThreadableLoaderClient methods may call Cancel().
  //
  // The specified ResourceFetcher if non-null, or otherwise
  // ExecutionContext::Fetcher() is used.
  ThreadableLoader(ExecutionContext&,
                   ThreadableLoaderClient*,
                   const ResourceLoaderOptions&,
                   ResourceFetcher* = nullptr);
  ~ThreadableLoader() override;

  // Exposed for testing. Code outside this class should not call this function.
  static std::unique_ptr<ResourceRequest>
  CreateAccessControlPreflightRequestForTesting(const ResourceRequest&);

  // Must be called to actually begin the request.
  void Start(ResourceRequest);

  // A ThreadableLoader may have a timeout specified. It is possible, in some
  // cases, for the timeout to be overridden after the request is sent (for
  // example, XMLHttpRequests may override their timeout setting after sending).
  //
  // If the request has already started, the new timeout will be relative to the
  // time the request started.
  //
  // Passing a timeout of zero means there should be no timeout.
  void SetTimeout(const base::TimeDelta& timeout);

  void Cancel();

  // Detach the loader from the request. This ffunction is for "keepalive"
  // requests. No notification will be sent to the client, but the request
  // will be processed.
  void Detach();

  void SetDefersLoading(bool);

  void Trace(Visitor* visitor) override;

 private:
  class AssignOnScopeExit;
  class DetachedClient;

  static std::unique_ptr<ResourceRequest> CreateAccessControlPreflightRequest(
      const ResourceRequest&,
      const SecurityOrigin*);

  void Clear();

  // ResourceClient
  void NotifyFinished(Resource*) override;

  String DebugName() const override { return "ThreadableLoader"; }

  // RawResourceClient
  void DataSent(Resource*,
                uint64_t bytes_sent,
                uint64_t total_bytes_to_be_sent) override;
  void ResponseReceived(Resource*, const ResourceResponse&) override;
  void ResponseBodyReceived(Resource*, BytesConsumer& body) override;
  void SetSerializedCachedMetadata(Resource*, const uint8_t*, size_t) override;
  void DataReceived(Resource*, const char* data, size_t data_length) override;
  bool RedirectReceived(Resource*,
                        const ResourceRequest&,
                        const ResourceResponse&) override;
  void RedirectBlocked() override;
  void DataDownloaded(Resource*, uint64_t) override;
  void DidDownloadToBlob(Resource*, scoped_refptr<BlobDataHandle>) override;

  // Notify Inspector and log to console about resource response. Use this
  // method if response is not going to be finished normally.
  void ReportResponseReceived(uint64_t identifier, const ResourceResponse&);

  void DidTimeout(TimerBase*);
  // Calls the appropriate loading method according to policy and data about
  // origin. Only for handling the initial load (including fallback after
  // consulting ServiceWorker).
  void DispatchInitialRequest(ResourceRequest&);
  void MakeCrossOriginAccessRequest(const ResourceRequest&);

  // Loads m_fallbackRequestForServiceWorker.
  void LoadFallbackRequestForServiceWorker();
  // Issues a CORS preflight.
  void LoadPreflightRequest(const ResourceRequest&,
                            const ResourceLoaderOptions&);
  // Loads actual_request_.
  void LoadActualRequest();
  // Clears actual_request_ and reports access control check failure to
  // m_client.
  void HandlePreflightFailure(const KURL&, const network::CorsErrorStatus&);
  // Investigates the response for the preflight request. If successful,
  // the actual request will be made later in NotifyFinished().
  void HandlePreflightResponse(const ResourceResponse&);

  void DispatchDidFail(const ResourceError&);

  void PrepareCrossOriginRequest(ResourceRequest&) const;

  // This method modifies the ResourceRequest by calling
  // SetAllowStoredCredentials() on it based on same-origin-ness and the
  // credentials mode.
  //
  // This method configures the ResourceLoaderOptions so that the underlying
  // ResourceFetcher doesn't perform some part of the CORS logic since this
  // class performs it by itself.
  void LoadRequest(ResourceRequest&, ResourceLoaderOptions);

  const SecurityOrigin* GetSecurityOrigin() const;

  // Returns null if the loader is not associated with a frame.
  // TODO(kinuko): Remove dependency to frame.
  LocalFrame* GetFrame() const;

  Member<ThreadableLoaderClient> client_;
  Member<ExecutionContext> execution_context_;
  Member<ResourceFetcher> resource_fetcher_;

  base::TimeDelta timeout_;
  // Some items may be overridden by m_forceDoNotAllowStoredCredentials and
  // m_securityOrigin. In such a case, build a ResourceLoaderOptions with
  // up-to-date values from them and this variable, and use it.
  const ResourceLoaderOptions resource_loader_options_;

  // True when feature OutOfBlinkCors is enabled (https://crbug.com/736308).
  const bool out_of_blink_cors_;

  // Corresponds to the CORS flag in the Fetch spec.
  bool cors_flag_ = false;
  scoped_refptr<const SecurityOrigin> security_origin_;
  scoped_refptr<const SecurityOrigin> original_security_origin_;

  const bool async_;

  // Holds the original request context (used for sanity checks).
  mojom::RequestContextType request_context_;

  // Saved so that we can use the original value for the modes in
  // ResponseReceived() where |resource| might be a reused one (e.g. preloaded
  // resource) which can have different modes.
  network::mojom::RequestMode request_mode_;
  network::mojom::CredentialsMode credentials_mode_;

  // Holds the original request for fallback in case the Service Worker
  // does not respond.
  ResourceRequest fallback_request_for_service_worker_;

  // Holds the original request and options for it during preflight request
  // handling phase.
  ResourceRequest actual_request_;
  ResourceLoaderOptions actual_options_;
  network::mojom::FetchResponseType response_tainting_ =
      network::mojom::FetchResponseType::kBasic;

  KURL initial_request_url_;
  KURL last_request_url_;

  // stores request headers in case of a cross-origin redirect.
  HTTPHeaderMap request_headers_;

  TaskRunnerTimer<ThreadableLoader> timeout_timer_;
  base::TimeTicks
      request_started_;  // Time an asynchronous fetch request is started

  // Max number of times that this ThreadableLoader can follow.
  int redirect_limit_;

  network::mojom::RedirectMode redirect_mode_;

  // Holds the referrer after a redirect response was received. This referrer is
  // used to populate the HTTP Referer header when following the redirect.
  bool override_referrer_;
  bool report_upload_progress_ = false;
  Referrer referrer_after_redirect_;

  bool detached_ = false;

  RawResourceClientStateChecker checker_;

  DISALLOW_COPY_AND_ASSIGN(ThreadableLoader);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_THREADABLE_LOADER_H_