Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp

Issue 2807533003: [WIP2] off-main-thread loading
Patch Set: call set_is_secure_context in EmbeddedSharedWorkerStub::CreateWorkerFetchContext() Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/loader/WorkerFetchContext.h" 5 #include "core/loader/WorkerFetchContext.h"
6 6
7 #include "core/loader/MixedContentChecker.h"
8 #include "core/probe/CoreProbes.h"
9 #include "core/timing/WorkerGlobalScopePerformance.h"
7 #include "core/workers/WorkerClients.h" 10 #include "core/workers/WorkerClients.h"
8 #include "core/workers/WorkerGlobalScope.h" 11 #include "core/workers/WorkerGlobalScope.h"
12 #include "platform/RuntimeEnabledFeatures.h"
9 #include "platform/Supplementable.h" 13 #include "platform/Supplementable.h"
10 #include "platform/WebTaskRunner.h" 14 #include "platform/WebTaskRunner.h"
11 #include "platform/exported/WrappedResourceRequest.h" 15 #include "platform/exported/WrappedResourceRequest.h"
16 #include "platform/loader/fetch/ResourceFetcher.h"
12 #include "platform/scheduler/child/web_scheduler.h" 17 #include "platform/scheduler/child/web_scheduler.h"
18 #include "platform/weborigin/SecurityPolicy.h"
13 #include "public/platform/Platform.h" 19 #include "public/platform/Platform.h"
20 #include "public/platform/WebMixedContent.h"
21 #include "public/platform/WebMixedContentContextType.h"
14 #include "public/platform/WebThread.h" 22 #include "public/platform/WebThread.h"
15 #include "public/platform/WebWorkerFetchContext.h" 23 #include "public/platform/WebWorkerFetchContext.h"
16 24
17 namespace blink { 25 namespace blink {
18 26
19 namespace { 27 namespace {
20 28
21 // WorkerFetchContextHolder is used to pass the WebWorkerFetchContext from the 29 // WorkerFetchContextHolder is used to pass the WebWorkerFetchContext from the
22 // main thread to the worker thread by attaching to the WorkerClients as a 30 // main thread to the worker thread by attaching to the WorkerClients as a
23 // Supplement. 31 // Supplement.
(...skipping 19 matching lines...) Expand all
43 } 51 }
44 52
45 DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<WorkerClients>::Trace(visitor); } 53 DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<WorkerClients>::Trace(visitor); }
46 54
47 private: 55 private:
48 std::unique_ptr<WebWorkerFetchContext> web_context_; 56 std::unique_ptr<WebWorkerFetchContext> web_context_;
49 }; 57 };
50 58
51 } // namespace 59 } // namespace
52 60
61 class WorkerFetchContext::WorkerResourceCallback final
62 : public GarbageCollectedFinalized<WorkerResourceCallback>,
63 public Resource::ResourceCallback {
64 public:
65 WorkerResourceCallback(WebTaskRunner* loading_task_runner)
66 : loading_task_runner_(loading_task_runner) {}
67 ~WorkerResourceCallback() {}
68 void Schedule(Resource*) override;
69 void Cancel(Resource*) override;
70 bool IsScheduled(Resource*) const override;
71 DECLARE_TRACE();
72
73 private:
74 void RunTask();
75
76 RefPtr<WebTaskRunner> loading_task_runner_;
77 TaskHandle task_handle_;
78 HeapHashSet<Member<Resource>> resources_with_pending_clients_;
79 };
80
81 DEFINE_TRACE(WorkerFetchContext::WorkerResourceCallback) {
82 visitor->Trace(resources_with_pending_clients_);
83 }
84
85 void WorkerFetchContext::WorkerResourceCallback::Schedule(Resource* resource) {
86 if (!task_handle_.IsActive()) {
87 task_handle_ = loading_task_runner_->PostCancellableTask(
88 BLINK_FROM_HERE,
89 WTF::Bind(&WorkerResourceCallback::RunTask, WrapWeakPersistent(this)));
90 }
91 resources_with_pending_clients_.insert(resource);
92 }
93
94 void WorkerFetchContext::WorkerResourceCallback::Cancel(Resource* resource) {
95 resources_with_pending_clients_.erase(resource);
96 if (task_handle_.IsActive() && resources_with_pending_clients_.IsEmpty())
97 task_handle_.Cancel();
98 }
99
100 bool WorkerFetchContext::WorkerResourceCallback::IsScheduled(
101 Resource* resource) const {
102 return resources_with_pending_clients_.Contains(resource);
103 }
104
105 void WorkerFetchContext::WorkerResourceCallback::RunTask() {
106 HeapVector<Member<Resource>> resources;
107 for (const Member<Resource>& resource : resources_with_pending_clients_)
108 resources.push_back(resource);
109 resources_with_pending_clients_.clear();
110
111 for (const auto& resource : resources)
112 resource->FinishPendingClients();
113 }
114
53 WorkerFetchContext::~WorkerFetchContext() {} 115 WorkerFetchContext::~WorkerFetchContext() {}
54 116
55 WorkerFetchContext* WorkerFetchContext::Create( 117 WorkerFetchContext* WorkerFetchContext::Create(
56 WorkerGlobalScope& worker_global_scope) { 118 WorkerGlobalScope& worker_global_scope) {
57 DCHECK(worker_global_scope.IsContextThread()); 119 DCHECK(worker_global_scope.IsContextThread());
58 WorkerClients* worker_clients = worker_global_scope.Clients(); 120 WorkerClients* worker_clients = worker_global_scope.Clients();
59 DCHECK(worker_clients); 121 if (!worker_clients)
122 return nullptr;
60 WorkerFetchContextHolder* holder = 123 WorkerFetchContextHolder* holder =
61 static_cast<WorkerFetchContextHolder*>(Supplement<WorkerClients>::From( 124 static_cast<WorkerFetchContextHolder*>(Supplement<WorkerClients>::From(
62 *worker_clients, WorkerFetchContextHolder::SupplementName())); 125 *worker_clients, WorkerFetchContextHolder::SupplementName()));
63 if (!holder) 126 if (!holder)
64 return nullptr; 127 return nullptr;
65 std::unique_ptr<WebWorkerFetchContext> web_context = holder->TakeContext(); 128 std::unique_ptr<WebWorkerFetchContext> web_context = holder->TakeContext();
66 DCHECK(web_context); 129 DCHECK(web_context);
67 return new WorkerFetchContext(std::move(web_context)); 130 return new WorkerFetchContext(worker_global_scope, std::move(web_context));
68 } 131 }
69 132
70 WorkerFetchContext::WorkerFetchContext( 133 WorkerFetchContext::WorkerFetchContext(
134 WorkerGlobalScope& worker_global_scope,
71 std::unique_ptr<WebWorkerFetchContext> web_context) 135 std::unique_ptr<WebWorkerFetchContext> web_context)
72 : web_context_(std::move(web_context)) { 136 : worker_global_scope_(worker_global_scope),
73 web_context_->InitializeOnWorkerThread(Platform::Current() 137 web_context_(std::move(web_context)),
74 ->CurrentThread() 138 loading_task_runner_(Platform::Current()
75 ->Scheduler() 139 ->CurrentThread()
76 ->LoadingTaskRunner() 140 ->Scheduler()
77 ->ToSingleThreadTaskRunner()); 141 ->LoadingTaskRunner()),
142 timer_task_runner_(
143 Platform::Current()->CurrentThread()->Scheduler()->TimerTaskRunner()),
144 resource_callback_(
145 new WorkerResourceCallback(loading_task_runner_.Get())) {
146 web_context_->InitializeOnWorkerThread(
147 loading_task_runner_->ToSingleThreadTaskRunner());
148 }
149
150 ResourceFetcher* WorkerFetchContext::GetResourceFetcher() {
151 if (resource_fetcher_)
152 return resource_fetcher_;
153 resource_fetcher_ = ResourceFetcher::Create(this);
154 return resource_fetcher_;
78 } 155 }
79 156
80 std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader() { 157 std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader() {
81 return web_context_->CreateURLLoader(); 158 return web_context_->CreateURLLoader();
82 } 159 }
83 160
84 bool WorkerFetchContext::IsControlledByServiceWorker() const { 161 bool WorkerFetchContext::IsControlledByServiceWorker() const {
85 return web_context_->IsControlledByServiceWorker(); 162 return web_context_->IsControlledByServiceWorker();
86 } 163 }
87 164
165 int64_t WorkerFetchContext::ServiceWorkerID() const {
166 // TODO(horo): ServiceWorkerID() is used only for memory cache which is
167 // disabled in worker thread. So we should remove this method.
168 return web_context_->ServiceWorkerID();
169 }
170
171 ResourceRequestBlockedReason WorkerFetchContext::CanRequest(
172 Resource::Type type,
173 const ResourceRequest& resource_request,
174 const KURL& url,
175 const ResourceLoaderOptions& options,
176 SecurityViolationReportingPolicy reporting_policy,
177 FetchParameters::OriginRestriction origin_restriction) const {
178 ResourceRequestBlockedReason blocked_reason = CanRequestInternal(
179 type, resource_request, url, options, reporting_policy,
180 origin_restriction, resource_request.GetRedirectStatus());
181 if (blocked_reason != ResourceRequestBlockedReason::kNone) {
182 probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
183 options.initiator_info, blocked_reason);
184 }
185 return blocked_reason;
186 }
187
188 ResourceRequestBlockedReason WorkerFetchContext::CanFollowRedirect(
189 Resource::Type type,
190 const ResourceRequest& resource_request,
191 const KURL& url,
192 const ResourceLoaderOptions& options,
193 SecurityViolationReportingPolicy reporting_policy,
194 FetchParameters::OriginRestriction origin_restriction) const {
195 ResourceRequestBlockedReason blocked_reason = CanRequestInternal(
196 type, resource_request, url, options, reporting_policy,
197 origin_restriction, resource_request.GetRedirectStatus());
198 if (blocked_reason != ResourceRequestBlockedReason::kNone) {
199 probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
200 options.initiator_info, blocked_reason);
201 }
202 return blocked_reason;
203 }
204
205 void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
206 FetchResourceType type) {
207 bool isMainResource = type == kFetchMainResource;
208 if (!isMainResource) {
209 if (!request.DidSetHTTPReferrer()) {
210 request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
211 worker_global_scope_->GetReferrerPolicy(), request.Url(),
212 worker_global_scope_->OutgoingReferrer()));
213 request.AddHTTPOriginIfNeeded(worker_global_scope_->GetSecurityOrigin());
214 } else {
215 DCHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(),
216 request.Url(),
217 request.HttpReferrer())
218 .referrer,
219 request.HttpReferrer());
220 request.AddHTTPOriginIfNeeded(request.HttpReferrer());
221 }
222 }
223 }
224
88 void WorkerFetchContext::PrepareRequest(ResourceRequest& request, 225 void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
89 RedirectType) { 226 RedirectType) {
227 String user_agent = worker_global_scope_->UserAgent();
228 probe::applyUserAgentOverride(worker_global_scope_, &user_agent);
229 DCHECK(!user_agent.IsNull());
230 request.SetHTTPUserAgent(AtomicString(user_agent));
231
232 request.SetIsMojoIPCForced(true);
233 if (request.RequestorOrigin()->IsUnique() &&
234 !worker_global_scope_->GetSecurityOrigin()->IsUnique()) {
235 request.SetRequestorOrigin(worker_global_scope_->GetSecurityOrigin());
236 }
90 WrappedResourceRequest webreq(request); 237 WrappedResourceRequest webreq(request);
91 web_context_->WillSendRequest(webreq); 238 web_context_->WillSendRequest(webreq);
92 } 239 }
93 240
241 void WorkerFetchContext::DispatchWillSendRequest(
242 unsigned long identifier,
243 ResourceRequest& request,
244 const ResourceResponse& redirect_response,
245 const FetchInitiatorInfo& initiator_info) {
246 probe::willSendRequest(worker_global_scope_, identifier, nullptr, request,
247 redirect_response, initiator_info);
248 }
249
250 void WorkerFetchContext::DispatchDidReceiveResponse(
251 unsigned long identifier,
252 const ResourceResponse& response,
253 WebURLRequest::FrameType frame_type,
254 WebURLRequest::RequestContext request_context,
255 Resource* resource,
256 ResourceResponseType) {
257 if (response.HasMajorCertificateErrors()) {
258 WebMixedContentContextType context_type =
259 WebMixedContent::ContextTypeFromRequestContext(
260 request_context, false /* strictMixedContentCheckingForPlugin */);
261 if (context_type == WebMixedContentContextType::kBlockable) {
262 web_context_->DidRunContentWithCertificateErrors(response.Url());
263 } else {
264 web_context_->DidDisplayContentWithCertificateErrors(response.Url());
265 }
266 }
267 probe::didReceiveResourceResponse(worker_global_scope_, identifier, nullptr,
268 response, resource);
269 }
270
271 void WorkerFetchContext::DispatchDidReceiveData(unsigned long identifier,
272 const char* data,
273 int data_length) {
274 probe::didReceiveData(worker_global_scope_, identifier, nullptr, data,
275 data_length);
276 }
277
278 void WorkerFetchContext::DispatchDidReceiveEncodedData(
279 unsigned long identifier,
280 int encoded_data_length) {
281 probe::didReceiveEncodedDataLength(worker_global_scope_, identifier,
282 encoded_data_length);
283 }
284
285 void WorkerFetchContext::DispatchDidFinishLoading(unsigned long identifier,
286 double finish_time,
287 int64_t encoded_data_length,
288 int64_t decoded_body_length) {
289 probe::didFinishLoading(worker_global_scope_, identifier, nullptr,
290 finish_time, encoded_data_length,
291 decoded_body_length);
292 }
293
294 void WorkerFetchContext::DispatchDidFail(unsigned long identifier,
295 const ResourceError& error,
296 int64_t encoded_data_length,
297 bool is_internal_request) {
298 probe::didFailLoading(worker_global_scope_, identifier, error);
299 }
300
301 ResourceRequestBlockedReason WorkerFetchContext::AllowResponse(
302 Resource::Type type,
303 const ResourceRequest& resource_request,
304 const KURL& url,
305 const ResourceLoaderOptions& options) const {
306 ResourceRequestBlockedReason blocked_reason =
307 CanRequestInternal(type, resource_request, url, options,
308 SecurityViolationReportingPolicy::kReport,
309 FetchParameters::kUseDefaultOriginRestrictionForType,
310 RedirectStatus::kFollowedRedirect);
311 if (blocked_reason != ResourceRequestBlockedReason::kNone) {
312 probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
313 options.initiator_info, blocked_reason);
314 }
315 return blocked_reason;
316 }
317
318 void WorkerFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
319 WorkerGlobalScopePerformance::performance(*worker_global_scope_)
320 ->AddResourceTiming(info);
321 }
322
323 ResourceRequestBlockedReason WorkerFetchContext::CanRequestInternal(
324 Resource::Type type,
325 const ResourceRequest& resource_request,
326 const KURL& url,
327 const ResourceLoaderOptions& options,
328 SecurityViolationReportingPolicy reporting_policy,
329 FetchParameters::OriginRestriction origin_restriction,
330 ResourceRequest::RedirectStatus redirect_status) const {
331 bool should_block_request = false;
332 probe::shouldBlockRequest(worker_global_scope_, resource_request,
333 &should_block_request);
334 if (should_block_request)
335 return ResourceRequestBlockedReason::kInspector;
336
337 SecurityOrigin* security_origin = options.security_origin.Get();
338 if (!security_origin)
339 security_origin = worker_global_scope_->GetSecurityOrigin();
340 if (!security_origin->CanDisplay(url)) {
341 if (origin_restriction == FetchParameters::kRestrictToSameOrigin) {
342 return ResourceRequestBlockedReason::kOrigin;
343 }
344 }
345
346 if (!url.User().IsEmpty() || !url.Pass().IsEmpty()) {
347 // See https://crbug.com/504300
348 if (RuntimeEnabledFeatures::blockCredentialedSubresourcesEnabled())
349 return ResourceRequestBlockedReason::kOrigin;
350 }
351
352 // TODO(horo): Check GetStrictMixedContentChecking()
353 // TODO(horo): Implement reporting.
354 if (MixedContentChecker::IsMixedContent(security_origin, url))
355 return ResourceRequestBlockedReason::kMixedContent;
356
357 // TODO(horo): Implement subresource filter.
358
359 if (!worker_global_scope_->GetContentSecurityPolicy()->AllowRequest(
360 resource_request.GetRequestContext(), url,
361 options.content_security_policy_nonce, options.integrity_metadata,
362 options.parser_disposition, redirect_status, reporting_policy)) {
363 return ResourceRequestBlockedReason::CSP;
364 }
365
366 return ResourceRequestBlockedReason::kNone;
367 }
368
369 RefPtr<WebTaskRunner> WorkerFetchContext::TimerTaskRunner() const {
370 return timer_task_runner_;
371 }
372
373 RefPtr<WebTaskRunner> WorkerFetchContext::LoadingTaskRunner() const {
374 return loading_task_runner_;
375 }
376
377 Resource::ResourceCallback* WorkerFetchContext::GetResourceCallback() {
378 return resource_callback_;
379 }
380
381 DEFINE_TRACE(WorkerFetchContext) {
382 visitor->Trace(worker_global_scope_);
383 visitor->Trace(resource_fetcher_);
384 visitor->Trace(resource_callback_);
385 FetchContext::Trace(visitor);
386 }
387
94 void ProvideWorkerFetchContextToWorker( 388 void ProvideWorkerFetchContextToWorker(
95 WorkerClients* clients, 389 WorkerClients* clients,
96 std::unique_ptr<WebWorkerFetchContext> web_context) { 390 std::unique_ptr<WebWorkerFetchContext> web_context) {
97 DCHECK(clients); 391 DCHECK(clients);
98 WorkerFetchContextHolder::ProvideTo( 392 WorkerFetchContextHolder::ProvideTo(
99 *clients, WorkerFetchContextHolder::SupplementName(), 393 *clients, WorkerFetchContextHolder::SupplementName(),
100 new WorkerFetchContextHolder(std::move(web_context))); 394 new WorkerFetchContextHolder(std::move(web_context)));
101 } 395 }
102 396
103 } // namespace blink 397 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698