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

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

Issue 2816403002: test all
Patch Set: fix sharedworker Created 3 years, 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "core/loader/WorkerFetchContext.h"
6
7 #include "core/loader/MixedContentChecker.h"
8 #include "core/probe/CoreProbes.h"
9 #include "core/timing/WorkerGlobalScopePerformance.h"
10 #include "core/workers/WorkerClients.h"
11 #include "core/workers/WorkerGlobalScope.h"
12 #include "platform/RuntimeEnabledFeatures.h"
13 #include "platform/Supplementable.h"
14 #include "platform/WebTaskRunner.h"
15 #include "platform/exported/WrappedResourceRequest.h"
16 #include "platform/loader/fetch/ResourceFetcher.h"
17 #include "platform/weborigin/SecurityPolicy.h"
18 #include "public/platform/Platform.h"
19 #include "public/platform/WebMixedContent.h"
20 #include "public/platform/WebMixedContentContextType.h"
21 #include "public/platform/WebScheduler.h"
22 #include "public/platform/WebThread.h"
23 #include "public/platform/WebWorkerFetchContext.h"
24
25 namespace blink {
26
27 namespace {
28
29 // WorkerFetchContextInfo is used to pass the WebWorkerFetchContext from the
30 // main thread to the worker thread by attaching to the WorkerClients as a
31 // Supplement.
32 class WorkerFetchContextInfo final
33 : public GarbageCollectedFinalized<WorkerFetchContextInfo>,
34 public Supplement<WorkerClients> {
35 USING_GARBAGE_COLLECTED_MIXIN(WorkerFetchContextInfo);
36
37 public:
38 static WorkerFetchContextInfo* From(WorkerClients& clients) {
39 return static_cast<WorkerFetchContextInfo*>(
40 Supplement<WorkerClients>::From(clients, SupplementName()));
41 }
42 static const char* SupplementName() { return "WorkerFetchContextInfo"; }
43
44 explicit WorkerFetchContextInfo(
45 std::unique_ptr<WebWorkerFetchContext> web_context)
46 : web_context_(std::move(web_context)) {}
47 virtual ~WorkerFetchContextInfo() {}
48
49 std::unique_ptr<WebWorkerFetchContext> TakeContext() {
50 return std::move(web_context_);
51 }
52
53 DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<WorkerClients>::Trace(visitor); }
54
55 private:
56 std::unique_ptr<WebWorkerFetchContext> web_context_;
57 };
58
59 } // namespace
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
115 WorkerFetchContext::~WorkerFetchContext() {}
116
117 WorkerFetchContext* WorkerFetchContext::Create(
118 WorkerGlobalScope& worker_global_scope) {
119 WorkerClients* worker_clients = worker_global_scope.Clients();
120 if (!worker_clients)
121 return nullptr;
122 WorkerFetchContextInfo* context_info =
123 static_cast<WorkerFetchContextInfo*>(Supplement<WorkerClients>::From(
124 *worker_clients, WorkerFetchContextInfo::SupplementName()));
125 if (!context_info)
126 return nullptr;
127 std::unique_ptr<WebWorkerFetchContext> web_context =
128 context_info->TakeContext();
129 DCHECK(web_context);
130 return new WorkerFetchContext(worker_global_scope, std::move(web_context));
131 }
132
133 WorkerFetchContext::WorkerFetchContext(
134 WorkerGlobalScope& worker_global_scope,
135 std::unique_ptr<WebWorkerFetchContext> web_context)
136 : worker_global_scope_(worker_global_scope),
137 web_context_(std::move(web_context)),
138 loading_task_runner_(Platform::Current()
139 ->CurrentThread()
140 ->Scheduler()
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_;
155 }
156
157 WebURLLoader* WorkerFetchContext::CreateURLLoader() {
158 return web_context_->CreateURLLoader();
159 }
160
161 bool WorkerFetchContext::IsControlledByServiceWorker() const {
162 return web_context_->IsControlledByServiceWorker();
163 }
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 void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
189 FetchResourceType type) {
190 bool isMainResource = type == kFetchMainResource;
191 if (!isMainResource) {
192 if (!request.DidSetHTTPReferrer()) {
193 request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
194 worker_global_scope_->GetReferrerPolicy(), request.Url(),
195 worker_global_scope_->OutgoingReferrer()));
196 request.AddHTTPOriginIfNeeded(worker_global_scope_->GetSecurityOrigin());
197 } else {
198 DCHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(),
199 request.Url(),
200 request.HttpReferrer())
201 .referrer,
202 request.HttpReferrer());
203 request.AddHTTPOriginIfNeeded(request.HttpReferrer());
204 }
205 }
206 }
207
208 void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
209 RedirectType) {
210 String user_agent = worker_global_scope_->UserAgent();
211 probe::applyUserAgentOverride(worker_global_scope_, &user_agent);
212 DCHECK(!user_agent.IsNull());
213 request.SetHTTPUserAgent(AtomicString(user_agent));
214
215 request.SetIsMojoIPCForced(true);
216 if (request.RequestorOrigin()->IsUnique() &&
217 !worker_global_scope_->GetSecurityOrigin()->IsUnique()) {
218 request.SetRequestorOrigin(worker_global_scope_->GetSecurityOrigin());
219 }
220 WrappedResourceRequest webreq(request);
221 web_context_->WillSendRequest(webreq);
222 }
223
224 void WorkerFetchContext::DispatchWillSendRequest(
225 unsigned long identifier,
226 ResourceRequest& request,
227 const ResourceResponse& redirect_response,
228 const FetchInitiatorInfo& initiator_info) {
229 probe::willSendRequest(worker_global_scope_, identifier, nullptr, request,
230 redirect_response, initiator_info);
231 }
232
233 void WorkerFetchContext::DispatchDidReceiveResponse(
234 unsigned long identifier,
235 const ResourceResponse& response,
236 WebURLRequest::FrameType frame_type,
237 WebURLRequest::RequestContext request_context,
238 Resource* resource,
239 ResourceResponseType) {
240 if (response.HasMajorCertificateErrors()) {
241 WebMixedContentContextType context_type =
242 WebMixedContent::ContextTypeFromRequestContext(
243 request_context, false /* strictMixedContentCheckingForPlugin */);
244 if (context_type == WebMixedContentContextType::kBlockable) {
245 web_context_->DidRunContentWithCertificateErrors(response.Url());
246 } else {
247 web_context_->DidDisplayContentWithCertificateErrors(response.Url());
248 }
249 }
250 probe::didReceiveResourceResponse(worker_global_scope_, identifier, nullptr,
251 response, resource);
252 }
253
254 void WorkerFetchContext::DispatchDidReceiveData(unsigned long identifier,
255 const char* data,
256 int data_length) {
257 probe::didReceiveData(worker_global_scope_, identifier, nullptr, data,
258 data_length);
259 }
260
261 void WorkerFetchContext::DispatchDidReceiveEncodedData(
262 unsigned long identifier,
263 int encoded_data_length) {
264 probe::didReceiveEncodedDataLength(worker_global_scope_, identifier,
265 encoded_data_length);
266 }
267
268 void WorkerFetchContext::DispatchDidFinishLoading(unsigned long identifier,
269 double finish_time,
270 int64_t encoded_data_length,
271 int64_t decoded_body_length) {
272 probe::didFinishLoading(worker_global_scope_, identifier, nullptr,
273 finish_time, encoded_data_length,
274 decoded_body_length);
275 }
276
277 void WorkerFetchContext::DispatchDidFail(unsigned long identifier,
278 const ResourceError& error,
279 int64_t encoded_data_length,
280 bool is_internal_request) {
281 probe::didFailLoading(worker_global_scope_, identifier, error);
282 }
283
284 ResourceRequestBlockedReason WorkerFetchContext::AllowResponse(
285 Resource::Type type,
286 const ResourceRequest& resource_request,
287 const KURL& url,
288 const ResourceLoaderOptions& options) const {
289 ResourceRequestBlockedReason blocked_reason =
290 CanRequestInternal(type, resource_request, url, options,
291 SecurityViolationReportingPolicy::kReport,
292 FetchParameters::kUseDefaultOriginRestrictionForType,
293 RedirectStatus::kFollowedRedirect);
294 if (blocked_reason != ResourceRequestBlockedReason::kNone) {
295 probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
296 options.initiator_info, blocked_reason);
297 }
298 return blocked_reason;
299 }
300
301 void WorkerFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
302 WorkerGlobalScopePerformance::performance(*worker_global_scope_)
303 ->AddResourceTiming(info);
304 }
305
306 ResourceRequestBlockedReason WorkerFetchContext::CanRequestInternal(
307 Resource::Type type,
308 const ResourceRequest& resource_request,
309 const KURL& url,
310 const ResourceLoaderOptions& options,
311 SecurityViolationReportingPolicy reporting_policy,
312 FetchParameters::OriginRestriction origin_restriction,
313 ResourceRequest::RedirectStatus redirect_status) const {
314 bool should_block_request = false;
315 probe::shouldBlockRequest(worker_global_scope_, resource_request,
316 &should_block_request);
317 if (should_block_request)
318 return ResourceRequestBlockedReason::kInspector;
319
320 SecurityOrigin* security_origin = options.security_origin.Get();
321 if (!security_origin)
322 security_origin = worker_global_scope_->GetSecurityOrigin();
323 if (!security_origin->CanDisplay(url)) {
324 if (origin_restriction == FetchParameters::kRestrictToSameOrigin) {
325 return ResourceRequestBlockedReason::kOrigin;
326 }
327 }
328
329 if (!url.User().IsEmpty() || !url.Pass().IsEmpty()) {
330 // See https://crbug.com/504300
331 if (RuntimeEnabledFeatures::blockCredentialedSubresourcesEnabled())
332 return ResourceRequestBlockedReason::kOrigin;
333 }
334
335 // TODO(horo): Check GetStrictMixedContentChecking()
336 // TODO(horo): Implement reporting.
337 if (MixedContentChecker::IsMixedContent(security_origin, url))
338 return ResourceRequestBlockedReason::kMixedContent;
339
340 // TODO(horo): Implement subresource filter.
341
342 if (!worker_global_scope_->GetContentSecurityPolicy()->AllowRequest(
343 resource_request.GetRequestContext(), url,
344 options.content_security_policy_nonce, options.integrity_metadata,
345 options.parser_disposition, redirect_status, reporting_policy)) {
346 return ResourceRequestBlockedReason::CSP;
347 }
348
349 return ResourceRequestBlockedReason::kNone;
350 }
351
352 RefPtr<WebTaskRunner> WorkerFetchContext::TimerTaskRunner() const {
353 return timer_task_runner_;
354 }
355
356 RefPtr<WebTaskRunner> WorkerFetchContext::LoadingTaskRunner() const {
357 return loading_task_runner_;
358 }
359
360 Resource::ResourceCallback* WorkerFetchContext::GetResourceCallback() {
361 return resource_callback_;
362 }
363
364 DEFINE_TRACE(WorkerFetchContext) {
365 visitor->Trace(worker_global_scope_);
366 visitor->Trace(resource_fetcher_);
367 visitor->Trace(resource_callback_);
368 FetchContext::Trace(visitor);
369 }
370
371 void ProvideWorkerFetchContextToWorker(
372 WorkerClients* clients,
373 std::unique_ptr<WebWorkerFetchContext> web_context) {
374 DCHECK(clients);
375 WorkerFetchContextInfo::ProvideTo(
376 *clients, WorkerFetchContextInfo::SupplementName(),
377 new WorkerFetchContextInfo(std::move(web_context)));
378 }
379
380 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698