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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..436a61b4edc7fbdf6ed98a5bc3b19054ba9fdffe
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -0,0 +1,380 @@
+// Copyright 2017 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.
+
+#include "core/loader/WorkerFetchContext.h"
+
+#include "core/loader/MixedContentChecker.h"
+#include "core/probe/CoreProbes.h"
+#include "core/timing/WorkerGlobalScopePerformance.h"
+#include "core/workers/WorkerClients.h"
+#include "core/workers/WorkerGlobalScope.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/Supplementable.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/exported/WrappedResourceRequest.h"
+#include "platform/loader/fetch/ResourceFetcher.h"
+#include "platform/weborigin/SecurityPolicy.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebMixedContent.h"
+#include "public/platform/WebMixedContentContextType.h"
+#include "public/platform/WebScheduler.h"
+#include "public/platform/WebThread.h"
+#include "public/platform/WebWorkerFetchContext.h"
+
+namespace blink {
+
+namespace {
+
+// WorkerFetchContextInfo is used to pass the WebWorkerFetchContext from the
+// main thread to the worker thread by attaching to the WorkerClients as a
+// Supplement.
+class WorkerFetchContextInfo final
+ : public GarbageCollectedFinalized<WorkerFetchContextInfo>,
+ public Supplement<WorkerClients> {
+ USING_GARBAGE_COLLECTED_MIXIN(WorkerFetchContextInfo);
+
+ public:
+ static WorkerFetchContextInfo* From(WorkerClients& clients) {
+ return static_cast<WorkerFetchContextInfo*>(
+ Supplement<WorkerClients>::From(clients, SupplementName()));
+ }
+ static const char* SupplementName() { return "WorkerFetchContextInfo"; }
+
+ explicit WorkerFetchContextInfo(
+ std::unique_ptr<WebWorkerFetchContext> web_context)
+ : web_context_(std::move(web_context)) {}
+ virtual ~WorkerFetchContextInfo() {}
+
+ std::unique_ptr<WebWorkerFetchContext> TakeContext() {
+ return std::move(web_context_);
+ }
+
+ DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<WorkerClients>::Trace(visitor); }
+
+ private:
+ std::unique_ptr<WebWorkerFetchContext> web_context_;
+};
+
+} // namespace
+
+class WorkerFetchContext::WorkerResourceCallback final
+ : public GarbageCollectedFinalized<WorkerResourceCallback>,
+ public Resource::ResourceCallback {
+ public:
+ WorkerResourceCallback(WebTaskRunner* loading_task_runner)
+ : loading_task_runner_(loading_task_runner) {}
+ ~WorkerResourceCallback() {}
+ void Schedule(Resource*) override;
+ void Cancel(Resource*) override;
+ bool IsScheduled(Resource*) const override;
+ DECLARE_TRACE();
+
+ private:
+ void RunTask();
+
+ RefPtr<WebTaskRunner> loading_task_runner_;
+ TaskHandle task_handle_;
+ HeapHashSet<Member<Resource>> resources_with_pending_clients_;
+};
+
+DEFINE_TRACE(WorkerFetchContext::WorkerResourceCallback) {
+ visitor->Trace(resources_with_pending_clients_);
+}
+
+void WorkerFetchContext::WorkerResourceCallback::Schedule(Resource* resource) {
+ if (!task_handle_.IsActive()) {
+ task_handle_ = loading_task_runner_->PostCancellableTask(
+ BLINK_FROM_HERE,
+ WTF::Bind(&WorkerResourceCallback::RunTask, WrapWeakPersistent(this)));
+ }
+ resources_with_pending_clients_.insert(resource);
+}
+
+void WorkerFetchContext::WorkerResourceCallback::Cancel(Resource* resource) {
+ resources_with_pending_clients_.erase(resource);
+ if (task_handle_.IsActive() && resources_with_pending_clients_.IsEmpty())
+ task_handle_.Cancel();
+}
+
+bool WorkerFetchContext::WorkerResourceCallback::IsScheduled(
+ Resource* resource) const {
+ return resources_with_pending_clients_.Contains(resource);
+}
+
+void WorkerFetchContext::WorkerResourceCallback::RunTask() {
+ HeapVector<Member<Resource>> resources;
+ for (const Member<Resource>& resource : resources_with_pending_clients_)
+ resources.push_back(resource);
+ resources_with_pending_clients_.Clear();
+
+ for (const auto& resource : resources)
+ resource->FinishPendingClients();
+}
+
+WorkerFetchContext::~WorkerFetchContext() {}
+
+WorkerFetchContext* WorkerFetchContext::Create(
+ WorkerGlobalScope& worker_global_scope) {
+ WorkerClients* worker_clients = worker_global_scope.Clients();
+ if (!worker_clients)
+ return nullptr;
+ WorkerFetchContextInfo* context_info =
+ static_cast<WorkerFetchContextInfo*>(Supplement<WorkerClients>::From(
+ *worker_clients, WorkerFetchContextInfo::SupplementName()));
+ if (!context_info)
+ return nullptr;
+ std::unique_ptr<WebWorkerFetchContext> web_context =
+ context_info->TakeContext();
+ DCHECK(web_context);
+ return new WorkerFetchContext(worker_global_scope, std::move(web_context));
+}
+
+WorkerFetchContext::WorkerFetchContext(
+ WorkerGlobalScope& worker_global_scope,
+ std::unique_ptr<WebWorkerFetchContext> web_context)
+ : worker_global_scope_(worker_global_scope),
+ web_context_(std::move(web_context)),
+ loading_task_runner_(Platform::Current()
+ ->CurrentThread()
+ ->Scheduler()
+ ->LoadingTaskRunner()),
+ timer_task_runner_(
+ Platform::Current()->CurrentThread()->Scheduler()->TimerTaskRunner()),
+ resource_callback_(
+ new WorkerResourceCallback(loading_task_runner_.Get())) {
+ web_context_->InitializeOnWorkerThread(
+ loading_task_runner_->ToSingleThreadTaskRunner());
+}
+
+ResourceFetcher* WorkerFetchContext::GetResourceFetcher() {
+ if (resource_fetcher_)
+ return resource_fetcher_;
+ resource_fetcher_ = ResourceFetcher::Create(this);
+ return resource_fetcher_;
+}
+
+WebURLLoader* WorkerFetchContext::CreateURLLoader() {
+ return web_context_->CreateURLLoader();
+}
+
+bool WorkerFetchContext::IsControlledByServiceWorker() const {
+ return web_context_->IsControlledByServiceWorker();
+}
+
+int64_t WorkerFetchContext::ServiceWorkerID() const {
+ // TODO(horo): ServiceWorkerID() is used only for memory cache which is
+ // disabled in worker thread. So we should remove this method.
+ return web_context_->ServiceWorkerID();
+}
+
+ResourceRequestBlockedReason WorkerFetchContext::CanRequest(
+ Resource::Type type,
+ const ResourceRequest& resource_request,
+ const KURL& url,
+ const ResourceLoaderOptions& options,
+ SecurityViolationReportingPolicy reporting_policy,
+ FetchParameters::OriginRestriction origin_restriction) const {
+ ResourceRequestBlockedReason blocked_reason = CanRequestInternal(
+ type, resource_request, url, options, reporting_policy,
+ origin_restriction, resource_request.GetRedirectStatus());
+ if (blocked_reason != ResourceRequestBlockedReason::kNone) {
+ probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
+ options.initiator_info, blocked_reason);
+ }
+ return blocked_reason;
+}
+
+void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
+ FetchResourceType type) {
+ bool isMainResource = type == kFetchMainResource;
+ if (!isMainResource) {
+ if (!request.DidSetHTTPReferrer()) {
+ request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+ worker_global_scope_->GetReferrerPolicy(), request.Url(),
+ worker_global_scope_->OutgoingReferrer()));
+ request.AddHTTPOriginIfNeeded(worker_global_scope_->GetSecurityOrigin());
+ } else {
+ DCHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(),
+ request.Url(),
+ request.HttpReferrer())
+ .referrer,
+ request.HttpReferrer());
+ request.AddHTTPOriginIfNeeded(request.HttpReferrer());
+ }
+ }
+}
+
+void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
+ RedirectType) {
+ String user_agent = worker_global_scope_->UserAgent();
+ probe::applyUserAgentOverride(worker_global_scope_, &user_agent);
+ DCHECK(!user_agent.IsNull());
+ request.SetHTTPUserAgent(AtomicString(user_agent));
+
+ request.SetIsMojoIPCForced(true);
+ if (request.RequestorOrigin()->IsUnique() &&
+ !worker_global_scope_->GetSecurityOrigin()->IsUnique()) {
+ request.SetRequestorOrigin(worker_global_scope_->GetSecurityOrigin());
+ }
+ WrappedResourceRequest webreq(request);
+ web_context_->WillSendRequest(webreq);
+}
+
+void WorkerFetchContext::DispatchWillSendRequest(
+ unsigned long identifier,
+ ResourceRequest& request,
+ const ResourceResponse& redirect_response,
+ const FetchInitiatorInfo& initiator_info) {
+ probe::willSendRequest(worker_global_scope_, identifier, nullptr, request,
+ redirect_response, initiator_info);
+}
+
+void WorkerFetchContext::DispatchDidReceiveResponse(
+ unsigned long identifier,
+ const ResourceResponse& response,
+ WebURLRequest::FrameType frame_type,
+ WebURLRequest::RequestContext request_context,
+ Resource* resource,
+ ResourceResponseType) {
+ if (response.HasMajorCertificateErrors()) {
+ WebMixedContentContextType context_type =
+ WebMixedContent::ContextTypeFromRequestContext(
+ request_context, false /* strictMixedContentCheckingForPlugin */);
+ if (context_type == WebMixedContentContextType::kBlockable) {
+ web_context_->DidRunContentWithCertificateErrors(response.Url());
+ } else {
+ web_context_->DidDisplayContentWithCertificateErrors(response.Url());
+ }
+ }
+ probe::didReceiveResourceResponse(worker_global_scope_, identifier, nullptr,
+ response, resource);
+}
+
+void WorkerFetchContext::DispatchDidReceiveData(unsigned long identifier,
+ const char* data,
+ int data_length) {
+ probe::didReceiveData(worker_global_scope_, identifier, nullptr, data,
+ data_length);
+}
+
+void WorkerFetchContext::DispatchDidReceiveEncodedData(
+ unsigned long identifier,
+ int encoded_data_length) {
+ probe::didReceiveEncodedDataLength(worker_global_scope_, identifier,
+ encoded_data_length);
+}
+
+void WorkerFetchContext::DispatchDidFinishLoading(unsigned long identifier,
+ double finish_time,
+ int64_t encoded_data_length,
+ int64_t decoded_body_length) {
+ probe::didFinishLoading(worker_global_scope_, identifier, nullptr,
+ finish_time, encoded_data_length,
+ decoded_body_length);
+}
+
+void WorkerFetchContext::DispatchDidFail(unsigned long identifier,
+ const ResourceError& error,
+ int64_t encoded_data_length,
+ bool is_internal_request) {
+ probe::didFailLoading(worker_global_scope_, identifier, error);
+}
+
+ResourceRequestBlockedReason WorkerFetchContext::AllowResponse(
+ Resource::Type type,
+ const ResourceRequest& resource_request,
+ const KURL& url,
+ const ResourceLoaderOptions& options) const {
+ ResourceRequestBlockedReason blocked_reason =
+ CanRequestInternal(type, resource_request, url, options,
+ SecurityViolationReportingPolicy::kReport,
+ FetchParameters::kUseDefaultOriginRestrictionForType,
+ RedirectStatus::kFollowedRedirect);
+ if (blocked_reason != ResourceRequestBlockedReason::kNone) {
+ probe::didBlockRequest(worker_global_scope_, resource_request, nullptr,
+ options.initiator_info, blocked_reason);
+ }
+ return blocked_reason;
+}
+
+void WorkerFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
+ WorkerGlobalScopePerformance::performance(*worker_global_scope_)
+ ->AddResourceTiming(info);
+}
+
+ResourceRequestBlockedReason WorkerFetchContext::CanRequestInternal(
+ Resource::Type type,
+ const ResourceRequest& resource_request,
+ const KURL& url,
+ const ResourceLoaderOptions& options,
+ SecurityViolationReportingPolicy reporting_policy,
+ FetchParameters::OriginRestriction origin_restriction,
+ ResourceRequest::RedirectStatus redirect_status) const {
+ bool should_block_request = false;
+ probe::shouldBlockRequest(worker_global_scope_, resource_request,
+ &should_block_request);
+ if (should_block_request)
+ return ResourceRequestBlockedReason::kInspector;
+
+ SecurityOrigin* security_origin = options.security_origin.Get();
+ if (!security_origin)
+ security_origin = worker_global_scope_->GetSecurityOrigin();
+ if (!security_origin->CanDisplay(url)) {
+ if (origin_restriction == FetchParameters::kRestrictToSameOrigin) {
+ return ResourceRequestBlockedReason::kOrigin;
+ }
+ }
+
+ if (!url.User().IsEmpty() || !url.Pass().IsEmpty()) {
+ // See https://crbug.com/504300
+ if (RuntimeEnabledFeatures::blockCredentialedSubresourcesEnabled())
+ return ResourceRequestBlockedReason::kOrigin;
+ }
+
+ // TODO(horo): Check GetStrictMixedContentChecking()
+ // TODO(horo): Implement reporting.
+ if (MixedContentChecker::IsMixedContent(security_origin, url))
+ return ResourceRequestBlockedReason::kMixedContent;
+
+ // TODO(horo): Implement subresource filter.
+
+ if (!worker_global_scope_->GetContentSecurityPolicy()->AllowRequest(
+ resource_request.GetRequestContext(), url,
+ options.content_security_policy_nonce, options.integrity_metadata,
+ options.parser_disposition, redirect_status, reporting_policy)) {
+ return ResourceRequestBlockedReason::CSP;
+ }
+
+ return ResourceRequestBlockedReason::kNone;
+}
+
+RefPtr<WebTaskRunner> WorkerFetchContext::TimerTaskRunner() const {
+ return timer_task_runner_;
+}
+
+RefPtr<WebTaskRunner> WorkerFetchContext::LoadingTaskRunner() const {
+ return loading_task_runner_;
+}
+
+Resource::ResourceCallback* WorkerFetchContext::GetResourceCallback() {
+ return resource_callback_;
+}
+
+DEFINE_TRACE(WorkerFetchContext) {
+ visitor->Trace(worker_global_scope_);
+ visitor->Trace(resource_fetcher_);
+ visitor->Trace(resource_callback_);
+ FetchContext::Trace(visitor);
+}
+
+void ProvideWorkerFetchContextToWorker(
+ WorkerClients* clients,
+ std::unique_ptr<WebWorkerFetchContext> web_context) {
+ DCHECK(clients);
+ WorkerFetchContextInfo::ProvideTo(
+ *clients, WorkerFetchContextInfo::SupplementName(),
+ new WorkerFetchContextInfo(std::move(web_context)));
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698