diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-24 11:40:17 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-24 12:42:11 +0000 |
commit | 5d87695f37678f96492b258bbab36486c59866b4 (patch) | |
tree | be9783bbaf04fb930c4d74ca9c00b5e7954c8bc6 /chromium/third_party/blink/renderer/modules/service_worker | |
parent | 6c11fb357ec39bf087b8b632e2b1e375aef1b38b (diff) | |
download | qtwebengine-chromium-5d87695f37678f96492b258bbab36486c59866b4.tar.gz |
BASELINE: Update Chromium to 75.0.3770.56
Change-Id: I86d2007fd27a45d5797eee06f4c9369b8b50ac4f
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/service_worker')
30 files changed, 816 insertions, 320 deletions
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h index abc9f4cca60..083665e6367 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h @@ -92,7 +92,7 @@ class MODULES_EXPORT FetchEvent final private: Member<FetchRespondWithObserver> observer_; - TraceWrapperMember<Request> request_; + Member<Request> request_; Member<PreloadResponseProperty> preload_response_property_; std::unique_ptr<WebURLResponse> preload_response_; Member<DataPipeBytesConsumer::CompletionNotifier> body_completion_notifier_; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc index d8ea0a1685b..8e711000b66 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc @@ -12,6 +12,7 @@ #include "base/metrics/histogram_macros.h" #include "services/network/public/mojom/fetch_api.mojom-blink.h" #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" @@ -20,7 +21,6 @@ #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/fetch/body_stream_buffer.h" #include "third_party/blink/renderer/core/inspector/console_message.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h" #include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -216,9 +216,10 @@ FetchRespondWithObserver* FetchRespondWithObserver::Create( void FetchRespondWithObserver::OnResponseRejected( ServiceWorkerResponseError error) { DCHECK(GetExecutionContext()); - GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, - GetMessageForResponseError(error, request_url_))); + GetExecutionContext()->AddConsoleMessage( + ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kWarning, + GetMessageForResponseError(error, request_url_))); // The default value of WebServiceWorkerResponse's status is 0, which maps // to a network error. @@ -366,6 +367,7 @@ void FetchRespondWithObserver::OnResponseFulfilled( } void FetchRespondWithObserver::OnNoResponse() { + DCHECK(GetExecutionContext()); ServiceWorkerGlobalScopeClient::From(GetExecutionContext()) ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_, base::TimeTicks::Now()); diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc index 7183dc9dd14..3c48c20ce58 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc @@ -32,14 +32,14 @@ ScriptPromise NavigationPreloadManager::setHeaderValue( "') is not a valid HTTP header field value.")); } - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); registration_->SetNavigationPreloadHeader(value, resolver); return promise; } ScriptPromise NavigationPreloadManager::getState(ScriptState* script_state) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); registration_->GetNavigationPreloadState(resolver); return promise; @@ -51,7 +51,7 @@ NavigationPreloadManager::NavigationPreloadManager( ScriptPromise NavigationPreloadManager::SetEnabled(bool enable, ScriptState* script_state) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); registration_->EnableNavigationPreload(enable, resolver); return promise; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc index 7f43d541d1d..eb0a2d7f0a6 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc @@ -90,7 +90,7 @@ ServiceWorkerContainer* NavigatorServiceWorker::GetOrCreateContainer( ->GetSecurityOrigin() ->CanAccessServiceWorkers()) { String error_message; - if (frame->GetSecurityContext()->IsSandboxed(kSandboxOrigin)) { + if (frame->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kOrigin)) { error_message = "Service worker is disabled because the context is sandboxed and " "lacks the 'allow-same-origin' flag."; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc index 216334f6947..d1082d43cc4 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc @@ -18,21 +18,12 @@ using blink::mojom::ServiceWorkerResponseError; namespace blink { -void RespondWithObserver::ContextDestroyed(ExecutionContext*) { - if (observer_) { - DCHECK_EQ(kPending, state_); - observer_.Clear(); - } - state_ = kDone; -} - void RespondWithObserver::WillDispatchEvent() { event_dispatch_time_ = WTF::CurrentTimeTicks(); } void RespondWithObserver::DidDispatchEvent( DispatchEventResult dispatch_result) { - DCHECK(GetExecutionContext()); if (state_ != kInitial) return; @@ -43,21 +34,35 @@ void RespondWithObserver::DidDispatchEvent( } state_ = kDone; - observer_.Clear(); } +// https://w3c.github.io/ServiceWorker/#fetch-event-respondwith void RespondWithObserver::RespondWith(ScriptState* script_state, ScriptPromise script_promise, ExceptionState& exception_state) { + // 1. `If the dispatch flag is unset, throw an "InvalidStateError" + // DOMException.` + if (!observer_->IsDispatchingEvent()) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "The event handler is already finished."); + return; + } + + // 2. `If the respond-with entered flag is set, throw an "InvalidStateError" + // DOMException.` if (state_ != kInitial) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The event has already been responded to."); + // Non-initial state during event dispatch means respondWith() was already + // called. + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "respondWith() was already called."); return; } + // 3. `Add r to the extend lifetime promises.` + // 4. `Increment the pending promises count by one.` + // This is accomplised by WaitUntil(). state_ = kPending; - observer_->WaitUntil( + bool will_wait = observer_->WaitUntil( script_state, script_promise, exception_state, WTF::BindRepeating(&RespondWithObserver::ResponseWasFulfilled, WrapPersistent(this), exception_state.Context(), @@ -66,13 +71,19 @@ void RespondWithObserver::RespondWith(ScriptState* script_state, WTF::BindRepeating(&RespondWithObserver::ResponseWasRejected, WrapPersistent(this), ServiceWorkerResponseError::kPromiseRejected)); + // If the WaitUntilObserver won't observe the response promise, the event can + // end before the response result is reported back to the + // ServiceWorkerContextClient, which it doesn't expect (e.g., for fetch + // events, RespondToFetchEvent*() must be called before + // DidHandleFetchEvent()). So WaitUntilObserver must observe the promise and + // call our callbacks before it determines the event is done. + DCHECK(will_wait); } void RespondWithObserver::ResponseWasRejected(ServiceWorkerResponseError error, const ScriptValue& value) { OnResponseRejected(error); state_ = kDone; - observer_.Clear(); } void RespondWithObserver::ResponseWasFulfilled( @@ -82,20 +93,19 @@ void RespondWithObserver::ResponseWasFulfilled( const ScriptValue& value) { OnResponseFulfilled(value, context_type, interface_name, property_name); state_ = kDone; - observer_.Clear(); } RespondWithObserver::RespondWithObserver(ExecutionContext* context, int event_id, WaitUntilObserver* observer) - : ContextLifecycleObserver(context), + : ContextClient(context), event_id_(event_id), state_(kInitial), observer_(observer) {} void RespondWithObserver::Trace(blink::Visitor* visitor) { visitor->Trace(observer_); - ContextLifecycleObserver::Trace(visitor); + ContextClient::Trace(visitor); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h index 42130eaf4da..1a356dd83d2 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h @@ -26,20 +26,19 @@ class WaitUntilObserver; // overriding onResponseFulfilled, onResponseRejected and onNoResponse. class MODULES_EXPORT RespondWithObserver : public GarbageCollectedFinalized<RespondWithObserver>, - public ContextLifecycleObserver { + public ContextClient { USING_GARBAGE_COLLECTED_MIXIN(RespondWithObserver); public: virtual ~RespondWithObserver() = default; - void ContextDestroyed(ExecutionContext*) override; - void WillDispatchEvent(); void DidDispatchEvent(DispatchEventResult dispatch_result); - // The respondWith() observes the promise until the given promise is resolved - // or rejected and then delays calling ServiceWorkerGlobalScopeClient:: - // didHandle*Event() in order to notify the result to the client. + // Observes the given promise and calls OnResponseRejected() or + // OnResponseFulfilled() when it settles. It also keeps the event alive by + // telling the event's WaitUntilObserver to observe the promise. The result of + // RespondWith() is therefore reported back before the event finishes. void RespondWith(ScriptState*, ScriptPromise, ExceptionState&); // Called when the respondWith() promise was rejected. diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc index 89173f7e2bc..bb612367bcf 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc @@ -101,7 +101,7 @@ void ServiceWorker::postMessage(ScriptState* script_state, } ScriptPromise ServiceWorker::InternalsTerminate(ScriptState* script_state) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); host_->TerminateForTesting( WTF::Bind([](ScriptPromiseResolver* resolver) { resolver->Resolve(); }, diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl index 8ee3e022618..ab4fbd7ecc2 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl @@ -52,4 +52,4 @@ enum ServiceWorkerState { attribute EventHandler onstatechange; }; -ServiceWorker implements AbstractWorker; +ServiceWorker includes AbstractWorker; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc index 6ea5d173152..f0a4897a219 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc @@ -117,7 +117,7 @@ ScriptPromise ServiceWorkerClients::get(ScriptState* script_state, if (!execution_context) return ScriptPromise(); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ServiceWorkerGlobalScopeClient::From(execution_context) ->GetClient(id, WTF::Bind(&DidGetClient, WrapPersistent(resolver))); return resolver->Promise(); @@ -131,7 +131,7 @@ ScriptPromise ServiceWorkerClients::matchAll( if (!execution_context) return ScriptPromise(); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ServiceWorkerGlobalScopeClient::From(execution_context) ->GetClients( mojom::blink::ServiceWorkerClientQueryOptions::New( @@ -147,7 +147,7 @@ ScriptPromise ServiceWorkerClients::claim(ScriptState* script_state) { if (!execution_context) return ScriptPromise(); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ServiceWorkerGlobalScopeClient::From(execution_context) ->Claim(WTF::Bind(&DidClaim, WrapPersistent(resolver))); return resolver->Promise(); @@ -155,7 +155,7 @@ ScriptPromise ServiceWorkerClients::claim(ScriptState* script_state) { ScriptPromise ServiceWorkerClients::openWindow(ScriptState* script_state, const String& url) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); ExecutionContext* context = ExecutionContext::From(script_state); diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc index ca5e8c657a3..e9123ef2246 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc @@ -63,6 +63,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" #include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { @@ -148,31 +149,6 @@ class ServiceWorkerContainer::DomContentLoadedListener final } }; -class ServiceWorkerContainer::GetRegistrationForReadyCallback - : public WebServiceWorkerProvider:: - WebServiceWorkerGetRegistrationForReadyCallbacks { - public: - explicit GetRegistrationForReadyCallback(ReadyProperty* ready) - : ready_(ready) {} - ~GetRegistrationForReadyCallback() override = default; - - void OnSuccess(WebServiceWorkerRegistrationObjectInfo info) override { - DCHECK_EQ(ready_->GetState(), ReadyProperty::kPending); - - if (ready_->GetExecutionContext() && - !ready_->GetExecutionContext()->IsContextDestroyed()) { - ready_->Resolve( - ServiceWorkerContainer::From( - To<Document>(ready_->GetExecutionContext())) - ->GetOrCreateServiceWorkerRegistration(std::move(info))); - } - } - - private: - Persistent<ReadyProperty> ready_; - DISALLOW_COPY_AND_ASSIGN(GetRegistrationForReadyCallback); -}; - const char ServiceWorkerContainer::kSupplementName[] = "ServiceWorkerContainer"; ServiceWorkerContainer* ServiceWorkerContainer::From(Document* document) { @@ -234,7 +210,7 @@ ScriptPromise ServiceWorkerContainer::registerServiceWorker( ScriptState* script_state, const String& url, const RegistrationOptions* options) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); // TODO(asamidoi): Remove this check after module loading for @@ -370,7 +346,7 @@ ScriptPromise ServiceWorkerContainer::registerServiceWorker( ScriptPromise ServiceWorkerContainer::getRegistration( ScriptState* script_state, const String& document_url) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); ExecutionContext* execution_context = ExecutionContext::From(script_state); @@ -422,7 +398,7 @@ ScriptPromise ServiceWorkerContainer::getRegistration( ScriptPromise ServiceWorkerContainer::getRegistrations( ScriptState* script_state) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); if (!provider_) { @@ -483,7 +459,8 @@ ScriptPromise ServiceWorkerContainer::ready(ScriptState* caller_state) { ready_ = CreateReadyProperty(); if (provider_) { provider_->GetRegistrationForReady( - std::make_unique<GetRegistrationForReadyCallback>(ready_.Get())); + WTF::Bind(&ServiceWorkerContainer::OnGetRegistrationForReady, + WrapPersistent(this))); } } @@ -499,6 +476,9 @@ void ServiceWorkerContainer::SetController( if (controller_) { UseCounter::Count(GetExecutionContext(), WebFeature::kServiceWorkerControlledPage); + GetExecutionContext()->GetScheduler()->RegisterStickyFeature( + SchedulingPolicy::Feature::kServiceWorkerControlledPage, + {SchedulingPolicy::RecordMetricsForBackForwardCache()}); } if (should_notify_controller_change) DispatchEvent(*Event::Create(event_type_names::kControllerchange)); @@ -655,4 +635,17 @@ void ServiceWorkerContainer::DispatchMessageEvent( EnqueueEvent(*event, TaskType::kServiceWorkerClientMessage); } +void ServiceWorkerContainer::OnGetRegistrationForReady( + WebServiceWorkerRegistrationObjectInfo info) { + DCHECK_EQ(ready_->GetState(), ReadyProperty::kPending); + + if (ready_->GetExecutionContext() && + !ready_->GetExecutionContext()->IsContextDestroyed()) { + ready_->Resolve( + ServiceWorkerContainer::From( + To<Document>(ready_->GetExecutionContext())) + ->GetOrCreateServiceWorkerRegistration(std::move(info))); + } +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h index 59053342879..817fc4e62e4 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h @@ -120,7 +120,6 @@ class MODULES_EXPORT ServiceWorkerContainer final private: class DomContentLoadedListener; - class GetRegistrationForReadyCallback; using ReadyProperty = ScriptPromiseProperty<Member<ServiceWorkerContainer>, @@ -132,6 +131,8 @@ class MODULES_EXPORT ServiceWorkerContainer final void DispatchMessageEvent(WebServiceWorkerObjectInfo source, TransferableMessage); + void OnGetRegistrationForReady(WebServiceWorkerRegistrationObjectInfo info); + std::unique_ptr<WebServiceWorkerProvider> provider_; Member<ServiceWorker> controller_; Member<ReadyProperty> ready_; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc index f2838ed468d..57d91f605fc 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc @@ -26,6 +26,7 @@ #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "v8/include/v8.h" @@ -276,6 +277,8 @@ TEST_F(ServiceWorkerContainerTest, GetRegistration_CrossOriginURLIsRejected) { } class StubWebServiceWorkerProvider { + DISALLOW_NEW(); + public: StubWebServiceWorkerProvider() : register_call_count_(0), diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index f7e2c95b4e6..9643b11c37e 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc @@ -53,9 +53,11 @@ #include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h" #include "third_party/blink/renderer/core/loader/threadable_loader.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" +#include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/installed_scripts_manager.h" +#include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h" #include "third_party/blink/renderer/core/workers/worker_clients.h" #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" #include "third_party/blink/renderer/modules/event_target_modules.h" @@ -71,11 +73,13 @@ #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" #include "third_party/blink/renderer/platform/histogram.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/weborigin/security_policy.h" #include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -106,7 +110,7 @@ ServiceWorkerGlobalScope* ServiceWorkerGlobalScope::Create( creation_params->script_url)) { // CSP headers, referrer policy, and origin trial tokens will be provided by // the InstalledScriptsManager in EvaluateClassicScript(). - DCHECK(creation_params->content_security_policy_parsed_headers.IsEmpty()); + DCHECK(creation_params->outside_content_security_policy_headers.IsEmpty()); DCHECK_EQ(network::mojom::ReferrerPolicy::kDefault, creation_params->referrer_policy); DCHECK(creation_params->origin_trial_tokens->IsEmpty()); @@ -138,25 +142,123 @@ bool ServiceWorkerGlobalScope::ShouldInstallV8Extensions() const { WebSecurityOrigin(GetSecurityOrigin())); } -void ServiceWorkerGlobalScope::ImportModuleScript( +// https://w3c.github.io/ServiceWorker/#update +void ServiceWorkerGlobalScope::FetchAndRunClassicScript( + const KURL& script_url, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + const v8_inspector::V8StackTraceId& stack_id) { + DCHECK(base::FeatureList::IsEnabled( + features::kOffMainThreadServiceWorkerScriptFetch)); + DCHECK(!IsContextPaused()); + + // Step 9. "Switching on job's worker type, run these substeps with the + // following options:" + // "classic: Fetch a classic worker script given job's serialized script url, + // job's client, "serviceworker", and the to-be-created environment settings + // object for this service worker." + auto destination = mojom::RequestContextType::SERVICE_WORKER; + + // "To perform the fetch given request, run the following steps:" + // Step 9.1. "Append `Service-Worker`/`script` to request's header list." + // Step 9.2. "Set request's cache mode to "no-cache" if any of the following + // are true:" + // Step 9.3. "Set request's service-workers mode to "none"." + // The browser process takes care of these steps. + + // Step 9.4. "If the is top-level flag is unset, then return the result of + // fetching request." + // This step makes sense only when the worker type is "module". For classic + // script fetch, the top-level flag is always set. + + // Step 9.5. "Set request's redirect mode to "error"." + // The browser process takes care of this step. + + // Step 9.6. "Fetch request, and asynchronously wait to run the remaining + // steps as part of fetch's process response for the response response." + WorkerClassicScriptLoader* classic_script_loader = + MakeGarbageCollected<WorkerClassicScriptLoader>(); + classic_script_loader->LoadTopLevelScriptAsynchronously( + *this, CreateOutsideSettingsFetcher(outside_settings_object), script_url, + destination, network::mojom::FetchRequestMode::kSameOrigin, + network::mojom::FetchCredentialsMode::kSameOrigin, + outside_settings_object.GetAddressSpace(), + WTF::Bind(&ServiceWorkerGlobalScope::DidReceiveResponseForClassicScript, + WrapWeakPersistent(this), + WrapPersistent(classic_script_loader)), + WTF::Bind(&ServiceWorkerGlobalScope::DidFetchClassicScript, + WrapWeakPersistent(this), WrapPersistent(classic_script_loader), + stack_id)); +} + +void ServiceWorkerGlobalScope::FetchAndRunModuleScript( const KURL& module_url_record, const FetchClientSettingsObjectSnapshot& outside_settings_object, network::mojom::FetchCredentialsMode credentials_mode) { - Modulator* modulator = Modulator::From(ScriptController()->GetScriptState()); + DCHECK(IsContextThread()); + FetchModuleScript(module_url_record, outside_settings_object, + mojom::RequestContextType::SERVICE_WORKER, credentials_mode, + ModuleScriptCustomFetchType::kWorkerConstructor, + MakeGarbageCollected<ServiceWorkerModuleTreeClient>( + Modulator::From(ScriptController()->GetScriptState()))); +} + +void ServiceWorkerGlobalScope::RunInstalledClassicScript( + const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id) { + DCHECK(IsContextThread()); - ModuleScriptCustomFetchType fetch_type = - ModuleScriptCustomFetchType::kWorkerConstructor; InstalledScriptsManager* installed_scripts_manager = GetThread()->GetInstalledScriptsManager(); - if (installed_scripts_manager && - installed_scripts_manager->IsScriptInstalled(module_url_record)) { - fetch_type = ModuleScriptCustomFetchType::kInstalledServiceWorker; + DCHECK(installed_scripts_manager); + DCHECK(installed_scripts_manager->IsScriptInstalled(script_url)); + + // GetScriptData blocks until the script is received from the browser. + std::unique_ptr<InstalledScriptsManager::ScriptData> script_data = + installed_scripts_manager->GetScriptData(script_url); + if (!script_data) { + ReportingProxy().DidFailToLoadClassicScript(); + // This will eventually initiate worker thread termination. See + // ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() for details. + close(); + return; + } + ReportingProxy().DidLoadClassicScript(); + + std::unique_ptr<Vector<String>> origin_trial_tokens = + script_data->CreateOriginTrialTokens(); + OriginTrialContext::AddTokens(this, origin_trial_tokens.get()); + + auto referrer_policy = network::mojom::ReferrerPolicy::kDefault; + if (!script_data->GetReferrerPolicy().IsNull()) { + SecurityPolicy::ReferrerPolicyFromHeaderValue( + script_data->GetReferrerPolicy(), + kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy); } - FetchModuleScript( - module_url_record, outside_settings_object, - mojom::RequestContextType::SERVICE_WORKER, credentials_mode, fetch_type, - MakeGarbageCollected<ServiceWorkerModuleTreeClient>(modulator)); + // Construct a ContentSecurityPolicy object to convert + // ContentSecurityPolicyResponseHeaders to CSPHeaderAndType. + // TODO(nhiroki): Find an efficient way to do this. + auto* content_security_policy = MakeGarbageCollected<ContentSecurityPolicy>(); + content_security_policy->DidReceiveHeaders( + script_data->GetContentSecurityPolicyResponseHeaders()); + + RunClassicScript( + script_url, referrer_policy, content_security_policy->Headers(), + script_data->TakeSourceText(), script_data->TakeMetaData(), stack_id); +} + +void ServiceWorkerGlobalScope::RunInstalledModuleScript( + const KURL& module_url_record, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + network::mojom::FetchCredentialsMode credentials_mode) { + DCHECK(IsContextThread()); + // The installed scripts will be read from the service worker script storage + // during module script fetch. + FetchModuleScript(module_url_record, outside_settings_object, + mojom::RequestContextType::SERVICE_WORKER, credentials_mode, + ModuleScriptCustomFetchType::kInstalledServiceWorker, + MakeGarbageCollected<ServiceWorkerModuleTreeClient>( + Modulator::From(ScriptController()->GetScriptState()))); } void ServiceWorkerGlobalScope::Dispose() { @@ -225,6 +327,111 @@ void ServiceWorkerGlobalScope::DidEvaluateScript() { } } +void ServiceWorkerGlobalScope::DidReceiveResponseForClassicScript( + WorkerClassicScriptLoader* classic_script_loader) { + DCHECK(IsContextThread()); + DCHECK(base::FeatureList::IsEnabled( + features::kOffMainThreadServiceWorkerScriptFetch)); + probe::DidReceiveScriptResponse(this, classic_script_loader->Identifier()); +} + +// https://w3c.github.io/ServiceWorker/#update +void ServiceWorkerGlobalScope::DidFetchClassicScript( + WorkerClassicScriptLoader* classic_script_loader, + const v8_inspector::V8StackTraceId& stack_id) { + DCHECK(IsContextThread()); + DCHECK(base::FeatureList::IsEnabled( + features::kOffMainThreadServiceWorkerScriptFetch)); + + // Step 9. "If the algorithm asynchronously completes with null, then:" + if (classic_script_loader->Failed()) { + // Step 9.1. "Invoke Reject Job Promise with job and TypeError." + // Step 9.2. "If newestWorker is null, invoke Clear Registration algorithm + // passing registration as its argument." + // Step 9.3. "Invoke Finish Job with job and abort these steps." + // The browser process takes care of these steps. + ReportingProxy().DidFailToFetchClassicScript(); + return; + } + ReportingProxy().DidFetchScript(); + probe::ScriptImported(this, classic_script_loader->Identifier(), + classic_script_loader->SourceText()); + + // Step 10. "If hasUpdatedResources is false, then:" + // Step 10.1. "Invoke Resolve Job Promise with job and registration." + // Steo 10.2. "Invoke Finish Job with job and abort these steps." + // Step 11. "Let worker be a new service worker." + // Step 12. "Set worker's script url to job's script url, worker's script + // resource to script, worker's type to job's worker type, and worker's + // script resource map to updatedResourceMap." + // Step 13. "Append url to worker's set of used scripts." + // The browser process takes care of these steps. + + // Step 14. "Set worker's script resource's HTTPS state to httpsState." + // This is done in the constructor of WorkerGlobalScope. + + // Step 15. "Set worker's script resource's referrer policy to + // referrerPolicy." + auto referrer_policy = network::mojom::ReferrerPolicy::kDefault; + if (!classic_script_loader->GetReferrerPolicy().IsNull()) { + SecurityPolicy::ReferrerPolicyFromHeaderValue( + classic_script_loader->GetReferrerPolicy(), + kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy); + } + + // Step 16. "Invoke Run Service Worker algorithm given worker, with the force + // bypass cache for importscripts flag set if job’s force bypass cache flag + // is set, and with the following callback steps given evaluationStatus:" + RunClassicScript( + classic_script_loader->ResponseURL(), referrer_policy, + classic_script_loader->GetContentSecurityPolicy() + ? classic_script_loader->GetContentSecurityPolicy()->Headers() + : Vector<CSPHeaderAndType>(), + classic_script_loader->SourceText(), + classic_script_loader->ReleaseCachedMetadata(), stack_id); +} + +// https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm +void ServiceWorkerGlobalScope::RunClassicScript( + const KURL& response_url, + network::mojom::ReferrerPolicy referrer_policy, + const Vector<CSPHeaderAndType> csp_headers, + const String& source_code, + std::unique_ptr<Vector<uint8_t>> cached_meta_data, + const v8_inspector::V8StackTraceId& stack_id) { + // Step 4.5. "Set workerGlobalScope's url to serviceWorker's script url." + InitializeURL(response_url); + + // Step 4.6. "Set workerGlobalScope's HTTPS state to serviceWorker's script + // resource's HTTPS state." + // This is done in the constructor of WorkerGlobalScope. + + // Step 4.7. "Set workerGlobalScope's referrer policy to serviceWorker's + // script resource's referrer policy." + SetReferrerPolicy(referrer_policy); + + // TODO(nhiroki): Clarify mappings between the steps 4.8-4.11 and + // implementation. + + // This is quoted from the "Content Security Policy" algorithm: + // "Whenever a user agent invokes Run Service Worker algorithm with a service + // worker serviceWorker: + // - If serviceWorker's script resource was delivered with a + // Content-Security-Policy HTTP header containing the value policy, the + // user agent must enforce policy for serviceWorker. + // - If serviceWorker's script resource was delivered with a + // Content-Security-Policy-Report-Only HTTP header containing the value + // policy, the user agent must monitor policy for serviceWorker." + InitContentSecurityPolicyFromVector(csp_headers); + BindContentSecurityPolicyToExecutionContext(); + + // Step 4.12. "Let evaluationStatus be the result of running the classic + // script script if script is a classic script, otherwise, the result of + // running the module script script if script is a module script." + EvaluateClassicScript(response_url, source_code, std::move(cached_meta_data), + stack_id); +} + void ServiceWorkerGlobalScope::CountScriptInternal( size_t script_size, size_t cached_metadata_size) { @@ -250,7 +457,7 @@ ScriptPromise ServiceWorkerGlobalScope::skipWaiting(ScriptState* script_state) { if (!execution_context) return ScriptPromise(); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ServiceWorkerGlobalScopeClient::From(execution_context) ->SkipWaiting(WTF::Bind(&DidSkipWaiting, WrapPersistent(resolver))); return resolver->Promise(); @@ -270,6 +477,16 @@ void ServiceWorkerGlobalScope::SetRegistration( GetExecutionContext(), std::move(info)); } +void ServiceWorkerGlobalScope::SetFetchHandlerExistence( + FetchHandlerExistence fetch_handler_existence) { + DCHECK(IsContextThread()); + if (fetch_handler_existence == FetchHandlerExistence::EXISTS && + base::FeatureList::IsEnabled( + features::kServiceWorkerIsolateInForeground)) { + GetThread()->GetIsolate()->IsolateInForegroundNotification(); + } +} + ServiceWorker* ServiceWorkerGlobalScope::GetOrCreateServiceWorker( WebServiceWorkerObjectInfo info) { if (info.version_id == mojom::blink::kInvalidServiceWorkerVersionId) @@ -291,8 +508,9 @@ bool ServiceWorkerGlobalScope::AddEventListenerInternal( "Event handler of '%s' event must be added on the initial evaluation " "of worker script.", event_type.Utf8().data()); - AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); + AddConsoleMessage( + ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kWarning, message)); } return WorkerGlobalScope::AddEventListenerInternal(event_type, listener, options); @@ -304,6 +522,8 @@ void ServiceWorkerGlobalScope::EvaluateClassicScriptInternal( std::unique_ptr<Vector<uint8_t>> cached_meta_data) { DCHECK(IsContextThread()); + // TODO(nhiroki): Move this mechanism to + // WorkerGlobalScope::EvaluateClassicScriptInternal(). if (!evaluate_script_ready_) { evaluate_script_ = WTF::Bind(&ServiceWorkerGlobalScope::EvaluateClassicScriptInternal, @@ -312,55 +532,6 @@ void ServiceWorkerGlobalScope::EvaluateClassicScriptInternal( return; } - // Receive the main script via script streaming if needed. - // TODO(nhiroki): Merge script loading from the installed script manager - // into regular off-the-main-thread script fetch path so that we can remove - // this special casing. - InstalledScriptsManager* installed_scripts_manager = - GetThread()->GetInstalledScriptsManager(); - if (installed_scripts_manager && - installed_scripts_manager->IsScriptInstalled(script_url)) { - // GetScriptData blocks until the script is received from the browser. - std::unique_ptr<InstalledScriptsManager::ScriptData> script_data = - installed_scripts_manager->GetScriptData(script_url); - if (!script_data) { - ReportingProxy().DidFailToLoadClassicScript(); - // This will eventually initiate worker thread termination. See - // ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() for details. - close(); - return; - } - - if (base::FeatureList::IsEnabled( - features::kOffMainThreadServiceWorkerScriptFetch)) { - // WorkerGlobalScope sets the URL in DidImportClassicScript() when - // off-the-main-thread fetch is enabled. Since we bypass calling - // DidImportClassicScript(), set the URL here. - InitializeURL(script_url); - } - - DCHECK(source_code.IsEmpty()); - DCHECK(!cached_meta_data); - source_code = script_data->TakeSourceText(); - cached_meta_data = script_data->TakeMetaData(); - - base::Optional<ContentSecurityPolicyResponseHeaders> - content_security_policy_raw_headers = - script_data->GetContentSecurityPolicyResponseHeaders(); - ApplyContentSecurityPolicyFromHeaders( - content_security_policy_raw_headers.value()); - - String referrer_policy = script_data->GetReferrerPolicy(); - if (!referrer_policy.IsNull()) - ParseAndSetReferrerPolicy(referrer_policy); - - std::unique_ptr<Vector<String>> origin_trial_tokens = - script_data->CreateOriginTrialTokens(); - OriginTrialContext::AddTokens(this, origin_trial_tokens.get()); - - ReportingProxy().DidLoadClassicScript(); - } - WorkerGlobalScope::EvaluateClassicScriptInternal(script_url, source_code, std::move(cached_meta_data)); } @@ -433,9 +604,9 @@ void ServiceWorkerGlobalScope::importScripts( SingleCachedMetadataHandler* ServiceWorkerGlobalScope::CreateWorkerScriptCachedMetadataHandler( const KURL& script_url, - const Vector<uint8_t>* meta_data) { + std::unique_ptr<Vector<uint8_t>> meta_data) { return ServiceWorkerScriptCachedMetadataHandler::Create(this, script_url, - meta_data); + std::move(meta_data)); } ScriptPromise ServiceWorkerGlobalScope::fetch(ScriptState* script_state, @@ -452,11 +623,6 @@ void ServiceWorkerGlobalScope::ExceptionThrown(ErrorEvent* event) { debugger->ExceptionThrown(GetThread(), event); } -mojom::RequestContextType -ServiceWorkerGlobalScope::GetDestinationForMainScript() { - return mojom::RequestContextType::SERVICE_WORKER; -} - void ServiceWorkerGlobalScope::CountCacheStorageInstalledScript( uint64_t script_size, uint64_t script_metadata_size) { diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h index b399e8bc3eb..ad08b81c53c 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h @@ -53,6 +53,7 @@ class ServiceWorkerRegistration; class ServiceWorkerThread; class StringOrTrustedScriptURL; class WaitUntilObserver; +class WorkerClassicScriptLoader; struct GlobalScopeCreationParams; struct WebServiceWorkerObjectInfo; struct WebServiceWorkerRegistrationObjectInfo; @@ -63,6 +64,8 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope { DEFINE_WRAPPERTYPEINFO(); public: + using FetchHandlerExistence = mojom::FetchHandlerExistence; + static ServiceWorkerGlobalScope* Create( ServiceWorkerThread*, std::unique_ptr<GlobalScopeCreationParams>, @@ -79,13 +82,33 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope { bool IsServiceWorkerGlobalScope() const override { return true; } bool ShouldInstallV8Extensions() const final; - // Implements WorkerGlobalScope. - void ImportModuleScript( + // Implements WorkerGlobalScope: + // Fetches and runs the top-level classic worker script for the 'new' or + // 'update' service worker cases. + void FetchAndRunClassicScript( + const KURL& script_url, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + const v8_inspector::V8StackTraceId& stack_id) override; + // Fetches and runs the top-level module worker script for the 'new' or + // 'update' service worker cases. + void FetchAndRunModuleScript( const KURL& module_url_record, const FetchClientSettingsObjectSnapshot& outside_settings_object, network::mojom::FetchCredentialsMode) override; void Dispose() override; + // Runs the installed top-level classic worker script for the 'installed' + // service worker case. + void RunInstalledClassicScript(const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id); + + // Runs the installed top-level module worker script for the 'installed' + // service worker case. + void RunInstalledModuleScript( + const KURL& module_url_record, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + network::mojom::FetchCredentialsMode); + // Counts an evaluated script and its size. Called for the main worker script. void CountWorkerScript(size_t script_size, size_t cached_metadata_size); @@ -110,6 +133,7 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope { void BindServiceWorkerHost(mojom::blink::ServiceWorkerHostAssociatedPtrInfo); void SetRegistration(WebServiceWorkerRegistrationObjectInfo info); + void SetFetchHandlerExistence(FetchHandlerExistence fetch_handler_existence); // Returns the ServiceWorker object described by the given info. Creates a new // object if needed, or else returns the existing one. @@ -165,9 +189,21 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope { ExceptionState&) override; SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler( const KURL& script_url, - const Vector<uint8_t>* meta_data) override; + std::unique_ptr<Vector<uint8_t>> meta_data) override; void ExceptionThrown(ErrorEvent*) override; - mojom::RequestContextType GetDestinationForMainScript() override; + + void DidReceiveResponseForClassicScript( + WorkerClassicScriptLoader* classic_script_loader); + void DidFetchClassicScript(WorkerClassicScriptLoader* classic_script_loader, + const v8_inspector::V8StackTraceId& stack_id); + + // https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm + void RunClassicScript(const KURL& response_url, + network::mojom::ReferrerPolicy, + const Vector<CSPHeaderAndType>, + const String& source_code, + std::unique_ptr<Vector<uint8_t>> cached_meta_data, + const v8_inspector::V8StackTraceId&); // Counts the |script_size| and |cached_metadata_size| for UMA to measure the // number of scripts and the total bytes of scripts. diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc index 69f8f1e3b9b..63b63bbe9f3 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc @@ -187,6 +187,11 @@ void ServiceWorkerGlobalScopeProxy::SetRegistration( WorkerGlobalScope()->SetRegistration(std::move(info)); } +void ServiceWorkerGlobalScopeProxy::SetFetchHandlerExistence( + FetchHandlerExistence fetch_handler_existence) { + WorkerGlobalScope()->SetFetchHandlerExistence(fetch_handler_existence); +} + void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); WorkerGlobalScope()->ReadyToEvaluateScript(); @@ -194,7 +199,7 @@ void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() { void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent( int event_id, - const WebBackgroundFetchRegistration& registration) { + WebBackgroundFetchRegistration registration) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id); @@ -209,7 +214,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent( BackgroundFetchEventInit* init = BackgroundFetchEventInit::Create(); init->setRegistration(MakeGarbageCollected<BackgroundFetchRegistration>( WorkerGlobalScope()->registration() /* service_worker_registration */, - registration)); + std::move(registration))); BackgroundFetchEvent* event = BackgroundFetchEvent::Create( event_type_names::kBackgroundfetchabort, init, observer); @@ -219,7 +224,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent( void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent( int event_id, - const WebBackgroundFetchRegistration& registration) { + WebBackgroundFetchRegistration registration) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id); @@ -227,7 +232,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent( BackgroundFetchEventInit* init = BackgroundFetchEventInit::Create(); init->setRegistration(MakeGarbageCollected<BackgroundFetchRegistration>( WorkerGlobalScope()->registration() /* service_worker_registration */, - registration)); + std::move(registration))); BackgroundFetchEvent* event = BackgroundFetchEvent::Create( event_type_names::kBackgroundfetchclick, init, observer); @@ -237,7 +242,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent( void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent( int event_id, - const WebBackgroundFetchRegistration& registration) { + WebBackgroundFetchRegistration registration) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id); @@ -252,7 +257,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent( BackgroundFetchEventInit* init = BackgroundFetchEventInit::Create(); init->setRegistration(MakeGarbageCollected<BackgroundFetchRegistration>( WorkerGlobalScope()->registration() /* service_worker_registration */, - registration)); + std::move(registration))); BackgroundFetchUpdateUIEvent* event = BackgroundFetchUpdateUIEvent::Create( event_type_names::kBackgroundfetchfail, init, observer, @@ -263,7 +268,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent( void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchSuccessEvent( int event_id, - const WebBackgroundFetchRegistration& registration) { + WebBackgroundFetchRegistration registration) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchSuccess, @@ -279,7 +284,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchSuccessEvent( BackgroundFetchEventInit* init = BackgroundFetchEventInit::Create(); init->setRegistration(MakeGarbageCollected<BackgroundFetchRegistration>( WorkerGlobalScope()->registration() /* service_worker_registration */, - registration)); + std::move(registration))); BackgroundFetchUpdateUIEvent* event = BackgroundFetchUpdateUIEvent::Create( event_type_names::kBackgroundfetchsuccess, init, observer, @@ -434,8 +439,8 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError( : error->unsanitized_message; if (!error_message.IsEmpty()) { WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create( - kWorkerMessageSource, mojom::ConsoleMessageLevel::kError, - error_message)); + mojom::ConsoleMessageSource::kWorker, + mojom::ConsoleMessageLevel::kError, error_message)); } // Reject the preloadResponse promise. fetch_event->OnNavigationPreloadError( @@ -613,7 +618,7 @@ void ServiceWorkerGlobalScopeProxy::ReportException( } void ServiceWorkerGlobalScopeProxy::ReportConsoleMessage( - MessageSource source, + mojom::ConsoleMessageSource source, mojom::ConsoleMessageLevel level, const String& message, SourceLocation* location) { diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h index f841f009a83..9e55234a0f3 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h @@ -83,22 +83,24 @@ class ServiceWorkerGlobalScopeProxy final void BindServiceWorkerHost( mojo::ScopedInterfaceEndpointHandle service_worker_host) override; void SetRegistration(WebServiceWorkerRegistrationObjectInfo info) override; + void SetFetchHandlerExistence( + FetchHandlerExistence fetch_handler_existence) override; // Must be called after the above BindServiceWorkerHost() and // SetRegistration() got called. void ReadyToEvaluateScript() override; void DispatchActivateEvent(int) override; void DispatchBackgroundFetchAbortEvent( int event_id, - const WebBackgroundFetchRegistration& registration) override; + WebBackgroundFetchRegistration registration) override; void DispatchBackgroundFetchClickEvent( int event_id, - const WebBackgroundFetchRegistration& registration) override; + WebBackgroundFetchRegistration registration) override; void DispatchBackgroundFetchFailEvent( int event_id, - const WebBackgroundFetchRegistration& registration) override; + WebBackgroundFetchRegistration registration) override; void DispatchBackgroundFetchSuccessEvent( int event_id, - const WebBackgroundFetchRegistration& registration) override; + WebBackgroundFetchRegistration registration) override; void DispatchCookieChangeEvent( int event_id, const WebCanonicalCookie& cookie, @@ -151,7 +153,7 @@ class ServiceWorkerGlobalScopeProxy final void ReportException(const String& error_message, std::unique_ptr<SourceLocation>, int exception_id) override; - void ReportConsoleMessage(MessageSource, + void ReportConsoleMessage(mojom::ConsoleMessageSource, mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc index 96e90785cce..aad7f26c6df 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc @@ -34,8 +34,6 @@ class Receiver { DISALLOW_NEW(); public: - using BytesChunk = Vector<char>; - Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes, scoped_refptr<base::SingleThreadTaskRunner> task_runner) @@ -43,7 +41,9 @@ class Receiver { watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, std::move(task_runner)), - remaining_bytes_(total_bytes) {} + remaining_bytes_(total_bytes) { + data_.ReserveInitialCapacity(SafeCast<wtf_size_t>(total_bytes)); + } void Start(base::OnceClosure callback) { if (!handle_.is_valid()) { @@ -88,11 +88,9 @@ class Receiver { return; } - if (bytes_read > 0) { - BytesChunk chunk; - chunk.Append(static_cast<const char*>(buffer), bytes_read); - chunks_.emplace_back(std::move(chunk)); - } + if (bytes_read > 0) + data_.Append(static_cast<const uint8_t*>(buffer), bytes_read); + rv = handle_->EndReadData(bytes_read); DCHECK_EQ(rv, MOJO_RESULT_OK); CHECK_GE(remaining_bytes_, bytes_read); @@ -103,9 +101,9 @@ class Receiver { bool IsRunning() const { return handle_.is_valid(); } bool HasReceivedAllData() const { return remaining_bytes_ == 0; } - Vector<BytesChunk> TakeChunks() { + Vector<uint8_t> TakeData() { DCHECK(!IsRunning()); - return std::move(chunks_); + return std::move(data_); } private: @@ -113,7 +111,7 @@ class Receiver { handle_.reset(); watcher_.Cancel(); if (!HasReceivedAllData()) - chunks_.clear(); + data_.clear(); DCHECK(callback_); std::move(callback_).Run(); } @@ -122,7 +120,7 @@ class Receiver { mojo::ScopedDataPipeConsumerHandle handle_; mojo::SimpleWatcher watcher_; - Vector<BytesChunk> chunks_; + Vector<uint8_t> data_; uint64_t remaining_bytes_; }; @@ -218,9 +216,9 @@ class Internal : public mojom::blink::ServiceWorkerInstalledScriptsManager { return; } - auto script_data = RawScriptData::Create( - script_info->encoding, receivers->body()->TakeChunks(), - receivers->meta_data()->TakeChunks()); + auto script_data = std::make_unique<RawScriptData>( + script_info->encoding, receivers->body()->TakeData(), + receivers->meta_data()->TakeData()); for (const auto& entry : script_info->headers) script_data->AddHeader(entry.key, entry.value); script_container_->AddOnIOThread(script_info->script_url, @@ -267,6 +265,9 @@ bool ServiceWorkerInstalledScriptsManager::IsScriptInstalled( std::unique_ptr<InstalledScriptsManager::ScriptData> ServiceWorkerInstalledScriptsManager::GetScriptData(const KURL& script_url) { DCHECK(!IsMainThread()); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerInstalledScriptsManager::GetScriptData", "url", + script_url.GetString().Utf8().data()); if (!IsScriptInstalled(script_url)) return nullptr; @@ -277,30 +278,25 @@ ServiceWorkerInstalledScriptsManager::GetScriptData(const KURL& script_url) { // This is from WorkerClassicScriptLoader::DidReceiveData. std::unique_ptr<TextResourceDecoder> decoder = - TextResourceDecoder::Create(TextResourceDecoderOptions( + std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions( TextResourceDecoderOptions::kPlainTextContent, raw_script_data->Encoding().IsEmpty() ? UTF8Encoding() : WTF::TextEncoding(raw_script_data->Encoding()))); - StringBuilder source_text_builder; - for (const auto& chunk : raw_script_data->ScriptTextChunks()) - source_text_builder.Append(decoder->Decode(chunk.data(), chunk.size())); + Vector<uint8_t> source_text = raw_script_data->TakeScriptText(); + String decoded_source_text = decoder->Decode( + reinterpret_cast<const char*>(source_text.data()), source_text.size()); + // TODO(crbug.com/946676): Remove the unique_ptr<> wrapper around the Vector + // as we can just use Vector::IsEmpty() to distinguish missing code cache. std::unique_ptr<Vector<uint8_t>> meta_data; - if (raw_script_data->MetaDataChunks().size() > 0) { - size_t total_metadata_size = 0; - for (const auto& chunk : raw_script_data->MetaDataChunks()) - total_metadata_size += chunk.size(); - meta_data = std::make_unique<Vector<uint8_t>>(); - meta_data->ReserveInitialCapacity( - SafeCast<wtf_size_t>(total_metadata_size)); - for (const auto& chunk : raw_script_data->MetaDataChunks()) - meta_data->Append(chunk.data(), static_cast<wtf_size_t>(chunk.size())); - } + Vector<uint8_t> meta_data_in = raw_script_data->TakeMetaData(); + if (meta_data_in.size() > 0) + meta_data = std::make_unique<Vector<uint8_t>>(std::move(meta_data_in)); return std::make_unique<InstalledScriptsManager::ScriptData>( - script_url, source_text_builder.ToString(), std::move(meta_data), + script_url, decoded_source_text, std::move(meta_data), raw_script_data->TakeHeaders()); } diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc index 637064031e2..e266f992cec 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc @@ -245,16 +245,14 @@ TEST_F(ServiceWorkerInstalledScriptsManagerTest, GetRawScriptData) { // Wait for the script's arrival. get_raw_script_data_waiter->Wait(); EXPECT_TRUE(script_data); - ASSERT_EQ(1u, script_data->ScriptTextChunks().size()); - ASSERT_EQ(kExpectedBody.size() + 1, - script_data->ScriptTextChunks()[0].size()); + Vector<uint8_t> script_text = script_data->TakeScriptText(); + Vector<uint8_t> meta_data = script_data->TakeMetaData(); + ASSERT_EQ(kExpectedBody.size() + 1, script_text.size()); EXPECT_STREQ(kExpectedBody.data(), - script_data->ScriptTextChunks()[0].data()); - ASSERT_EQ(1u, script_data->MetaDataChunks().size()); - ASSERT_EQ(kExpectedMetaData.size() + 1, - script_data->MetaDataChunks()[0].size()); + reinterpret_cast<const char*>(script_text.data())); + ASSERT_EQ(kExpectedMetaData.size() + 1, meta_data.size()); EXPECT_STREQ(kExpectedMetaData.data(), - script_data->MetaDataChunks()[0].data()); + reinterpret_cast<const char*>(meta_data.data())); EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding()); EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders), *(script_data->TakeHeaders())); @@ -290,16 +288,14 @@ TEST_F(ServiceWorkerInstalledScriptsManagerTest, GetRawScriptData) { // Wait for the script's arrival. get_raw_script_data_waiter->Wait(); EXPECT_TRUE(script_data); - ASSERT_EQ(1u, script_data->ScriptTextChunks().size()); - ASSERT_EQ(kExpectedBody.size() + 1, - script_data->ScriptTextChunks()[0].size()); + Vector<uint8_t> script_text = script_data->TakeScriptText(); + Vector<uint8_t> meta_data = script_data->TakeMetaData(); + ASSERT_EQ(kExpectedBody.size() + 1, script_text.size()); EXPECT_STREQ(kExpectedBody.data(), - script_data->ScriptTextChunks()[0].data()); - ASSERT_EQ(1u, script_data->MetaDataChunks().size()); - ASSERT_EQ(kExpectedMetaData.size() + 1, - script_data->MetaDataChunks()[0].size()); + reinterpret_cast<const char*>(script_text.data())); + ASSERT_EQ(kExpectedMetaData.size() + 1, meta_data.size()); EXPECT_STREQ(kExpectedMetaData.data(), - script_data->MetaDataChunks()[0].data()); + reinterpret_cast<const char*>(meta_data.data())); EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding()); EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders), *(script_data->TakeHeaders())); diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc index 1f9aba8b0a0..918c9e28698 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc @@ -228,7 +228,7 @@ ScriptPromise ServiceWorkerRegistration::update(ScriptState* script_state) { "Failed to update a ServiceWorkerRegistration: No " "associated provider is available.")); } - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); host_->Update( WTF::Bind(&DidUpdate, WrapPersistent(resolver), WrapPersistent(this))); return resolver->Promise(); @@ -243,7 +243,7 @@ ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* script_state) { "ServiceWorkerRegistration: No " "associated provider is available.")); } - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); host_->Unregister(WTF::Bind(&DidUnregister, WrapPersistent(resolver))); return resolver->Promise(); } diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc index fc05eaca6f4..cc887664175 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc @@ -15,11 +15,12 @@ ServiceWorkerScriptCachedMetadataHandler:: ServiceWorkerScriptCachedMetadataHandler( WorkerGlobalScope* worker_global_scope, const KURL& script_url, - const Vector<uint8_t>* meta_data) + std::unique_ptr<Vector<uint8_t>> meta_data) : worker_global_scope_(worker_global_scope), script_url_(script_url) { - if (meta_data) - cached_metadata_ = CachedMetadata::CreateFromSerializedData( - meta_data->data(), meta_data->size()); + if (meta_data) { + cached_metadata_ = + CachedMetadata::CreateFromSerializedData(std::move(*meta_data)); + } } ServiceWorkerScriptCachedMetadataHandler:: diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h index d395583226b..46a52fa0d5c 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h @@ -22,14 +22,15 @@ class ServiceWorkerScriptCachedMetadataHandler static ServiceWorkerScriptCachedMetadataHandler* Create( WorkerGlobalScope* worker_global_scope, const KURL& script_url, - const Vector<uint8_t>* meta_data) { + std::unique_ptr<Vector<uint8_t>> meta_data) { return MakeGarbageCollected<ServiceWorkerScriptCachedMetadataHandler>( - worker_global_scope, script_url, meta_data); + worker_global_scope, script_url, std::move(meta_data)); } - ServiceWorkerScriptCachedMetadataHandler(WorkerGlobalScope*, - const KURL& script_url, - const Vector<uint8_t>* meta_data); + ServiceWorkerScriptCachedMetadataHandler( + WorkerGlobalScope*, + const KURL& script_url, + std::unique_ptr<Vector<uint8_t>> meta_data); ~ServiceWorkerScriptCachedMetadataHandler() override; void Trace(blink::Visitor*) override; void SetCachedMetadata(uint32_t data_type_id, diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc index 338ac091918..c0c6a49fe31 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc @@ -32,11 +32,16 @@ #include <memory> +#include "third_party/blink/renderer/core/inspector/thread_debugger.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "v8/include/v8-inspector.h" namespace blink { @@ -47,8 +52,8 @@ ServiceWorkerThread::ServiceWorkerThread( mojom::blink::CacheStoragePtrInfo cache_storage_info) : WorkerThread(*global_scope_proxy), global_scope_proxy_(global_scope_proxy), - worker_backing_thread_( - WorkerBackingThread::Create(ThreadCreationParams(GetThreadType()))), + worker_backing_thread_(std::make_unique<WorkerBackingThread>( + ThreadCreationParams(GetThreadType()))), installed_scripts_manager_(std::move(installed_scripts_manager)), cache_storage_info_(std::move(cache_storage_info)) {} @@ -69,6 +74,52 @@ void ServiceWorkerThread::TerminateForTesting() { WorkerThread::TerminateForTesting(); } +void ServiceWorkerThread::RunInstalledClassicScript( + const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id) { + // Use TaskType::kDOMManipulation for consistency with + // WorkerThread::EvaluateClassicScript(). + PostCrossThreadTask( + *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE, + CrossThreadBind( + &ServiceWorkerThread::RunInstalledClassicScriptOnWorkerThread, + CrossThreadUnretained(this), script_url, stack_id)); +} + +void ServiceWorkerThread::RunInstalledModuleScript( + const KURL& module_url_record, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + network::mojom::FetchCredentialsMode credentials_mode) { + PostCrossThreadTask( + *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE, + CrossThreadBind( + &ServiceWorkerThread::RunInstalledModuleScriptOnWorkerThread, + CrossThreadUnretained(this), module_url_record, + WTF::Passed(outside_settings_object.CopyData()), credentials_mode)); +} + +void ServiceWorkerThread::RunInstalledClassicScriptOnWorkerThread( + const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id) { + DCHECK(IsCurrentThread()); + To<ServiceWorkerGlobalScope>(GlobalScope()) + ->RunInstalledClassicScript(script_url, stack_id); +} + +void ServiceWorkerThread::RunInstalledModuleScriptOnWorkerThread( + const KURL& module_url_record, + std::unique_ptr<CrossThreadFetchClientSettingsObjectData> + outside_settings_object, + network::mojom::FetchCredentialsMode credentials_mode) { + DCHECK(IsCurrentThread()); + To<ServiceWorkerGlobalScope>(GlobalScope()) + ->RunInstalledModuleScript( + module_url_record, + *MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( + std::move(outside_settings_object)), + credentials_mode); +} + WorkerOrWorkletGlobalScope* ServiceWorkerThread::CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params) { return ServiceWorkerGlobalScope::Create(this, std::move(creation_params), diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h index 43b427e46d0..2cf6ecf7971 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h @@ -59,6 +59,13 @@ class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread { InstalledScriptsManager* GetInstalledScriptsManager() override; void TerminateForTesting() override; + void RunInstalledClassicScript(const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id); + void RunInstalledModuleScript( + const KURL& module_url_record, + const FetchClientSettingsObjectSnapshot& outside_settings_object, + network::mojom::FetchCredentialsMode); + private: WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) override; @@ -67,6 +74,15 @@ class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread { return WebThreadType::kServiceWorkerThread; } + void RunInstalledClassicScriptOnWorkerThread( + const KURL& script_url, + const v8_inspector::V8StackTraceId& stack_id); + void RunInstalledModuleScriptOnWorkerThread( + const KURL& module_url_record, + std::unique_ptr<CrossThreadFetchClientSettingsObjectData> + outside_settings_object, + network::mojom::FetchCredentialsMode); + Persistent<ServiceWorkerGlobalScopeProxy> global_scope_proxy_; std::unique_ptr<WorkerBackingThread> worker_backing_thread_; std::unique_ptr<ServiceWorkerInstalledScriptsManager> diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc index 72637d13b2d..3cd6cc05fdb 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc @@ -71,7 +71,7 @@ String ServiceWorkerWindowClient::visibilityState() const { } ScriptPromise ServiceWorkerWindowClient::focus(ScriptState* script_state) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); if (!ExecutionContext::From(script_state)->IsWindowInteractionAllowed()) { @@ -88,7 +88,7 @@ ScriptPromise ServiceWorkerWindowClient::focus(ScriptState* script_state) { ScriptPromise ServiceWorkerWindowClient::navigate(ScriptState* script_state, const String& url) { - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); ExecutionContext* context = ExecutionContext::From(script_state); diff --git a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc index 4d0db13a062..2596ead94fb 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc @@ -8,19 +8,10 @@ namespace blink { -// static -std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> -ThreadSafeScriptContainer::RawScriptData::Create(const String& encoding, - Vector<BytesChunk> script_text, - Vector<BytesChunk> meta_data) { - return base::WrapUnique(new RawScriptData(encoding, std::move(script_text), - std::move(meta_data))); -} - ThreadSafeScriptContainer::RawScriptData::RawScriptData( const String& encoding, - Vector<BytesChunk> script_text, - Vector<BytesChunk> meta_data) + Vector<uint8_t> script_text, + Vector<uint8_t> meta_data) : encoding_(encoding.IsolatedCopy()), script_text_(std::move(script_text)), meta_data_(std::move(meta_data)), diff --git a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h index 22069d93198..654849333f3 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h @@ -47,21 +47,21 @@ class MODULES_EXPORT ThreadSafeScriptContainer USING_FAST_MALLOC(RawScriptData); public: - static std::unique_ptr<RawScriptData> Create(const String& encoding, - Vector<BytesChunk> script_text, - Vector<BytesChunk> meta_data); - + RawScriptData(const String& encoding, + Vector<uint8_t> script_text, + Vector<uint8_t> meta_data); ~RawScriptData(); void AddHeader(const String& key, const String& value); // The encoding of the script text. const String& Encoding() const { return encoding_; } - // An array of raw byte chunks of the script text. - const Vector<BytesChunk>& ScriptTextChunks() const { return script_text_; } - // An array of raw byte chunks of the scripts's meta data from the script's - // V8 code cache. - const Vector<BytesChunk>& MetaDataChunks() const { return meta_data_; } + + // An array of raw bytes representing the script text. + Vector<uint8_t> TakeScriptText() { return std::move(script_text_); } + + // An array of raw bytes representing the cached metadata. + Vector<uint8_t> TakeMetaData() { return std::move(meta_data_); } // The HTTP headers of the script. std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() { @@ -69,12 +69,9 @@ class MODULES_EXPORT ThreadSafeScriptContainer } private: - RawScriptData(const String& encoding, - Vector<BytesChunk> script_text, - Vector<BytesChunk> meta_data); String encoding_; - Vector<BytesChunk> script_text_; - Vector<BytesChunk> meta_data_; + Vector<uint8_t> script_text_; + Vector<uint8_t> meta_data_; std::unique_ptr<CrossThreadHTTPHeaderMapData> headers_; }; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc index d321c139fe6..d4bb1e036c9 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc @@ -46,10 +46,11 @@ class ThreadSafeScriptContainerTest : public ::testing::Test { [](scoped_refptr<ThreadSafeScriptContainer> container, ThreadSafeScriptContainer::RawScriptData** out_data, base::WaitableEvent* waiter) { - auto data = ThreadSafeScriptContainer::RawScriptData::Create( - String::FromUTF8("utf-8") /* encoding */, - Vector<Vector<char>>() /* script_text */, - Vector<Vector<char>>() /* meta_data */); + auto data = + std::make_unique<ThreadSafeScriptContainer::RawScriptData>( + String::FromUTF8("utf-8") /* encoding */, + Vector<uint8_t>() /* script_text */, + Vector<uint8_t>() /* meta_data */); *out_data = data.get(); container->AddOnIOThread(KURL(kKeyUrl), std::move(data)); waiter->Signal(); diff --git a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc index 473f8b106fb..c8ab77268cc 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc @@ -111,6 +111,8 @@ WaitUntilObserver* WaitUntilObserver::Create(ExecutionContext* context, } void WaitUntilObserver::WillDispatchEvent() { + DCHECK(GetExecutionContext()); + // When handling a notificationclick, paymentrequest, or backgroundfetchclick // event, we want to allow one window to be focused or opened. These calls are // allowed between the call to willDispatchEvent() and the last call to @@ -118,7 +120,7 @@ void WaitUntilObserver::WillDispatchEvent() { // between willDispatchEvent() and didDispatchEvent(). if (type_ == kNotificationClick || type_ == kPaymentRequest || type_ == kBackgroundFetchClick) { - execution_context_->AllowWindowInteraction(); + GetExecutionContext()->AllowWindowInteraction(); } DCHECK_EQ(EventDispatchState::kInitial, event_dispatch_state_); @@ -132,24 +134,27 @@ void WaitUntilObserver::DidDispatchEvent(bool event_dispatch_failed) { MaybeCompleteEvent(); } -void WaitUntilObserver::WaitUntil(ScriptState* script_state, +// https://w3c.github.io/ServiceWorker/#dom-extendableevent-waituntil +bool WaitUntilObserver::WaitUntil(ScriptState* script_state, ScriptPromise script_promise, ExceptionState& exception_state, PromiseSettledCallback on_promise_fulfilled, PromiseSettledCallback on_promise_rejected) { DCHECK_NE(event_dispatch_state_, EventDispatchState::kInitial); - if (!IsEventActive(script_state)) { + // 1. `If the isTrusted attribute is false, throw an "InvalidStateError" + // DOMException.` + // This might not yet be implemented. + + // 2. `If not active, throw an "InvalidStateError" DOMException.` + if (!IsEventActive()) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidStateError, "The event handler is already finished and no extend lifetime " "promises are outstanding."); - return; + return false; } - if (!execution_context_) - return; - // When handling a notificationclick event, we want to allow one window to // be focused or opened. See comments in ::willDispatchEvent(). When // waitUntil() is being used, opening or closing a window must happen in a @@ -160,42 +165,33 @@ void WaitUntilObserver::WaitUntil(ScriptState* script_state, FROM_HERE); } + // 3. `Add f to the extend lifetime promises.` + // 4. `Increment the pending promises count by one.` IncrementPendingPromiseCount(); script_promise.Then( ThenFunction::CreateFunction(script_state, this, ThenFunction::kFulfilled, std::move(on_promise_fulfilled)), ThenFunction::CreateFunction(script_state, this, ThenFunction::kRejected, std::move(on_promise_rejected))); + return true; } -bool WaitUntilObserver::IsEventActive(ScriptState* script_state) const { - if (pending_promises_ > 0) - return true; +// https://w3c.github.io/ServiceWorker/#extendableevent-active +bool WaitUntilObserver::IsEventActive() const { + // `An ExtendableEvent object is said to be active when its timed out flag is + // unset and either its pending promises count is greater than zero or its + // dispatch flag is set.` + return pending_promises_ > 0 || IsDispatchingEvent(); +} - switch (event_dispatch_state_) { - case EventDispatchState::kDispatching: - // DidDispatchEvent() is called after both the event handler - // execution finished and microtasks queued by the event handler execution - // finished, it's hard to get the precise time point between the 2 - // execution phases. - // So even in EventDispatchState::kDispatching state at this time point, - // running microtask indicates that event handler execution has actually - // finished, in such case if there aren't any outstanding extend lifetime - // promises. - return !v8::MicrotasksScope::IsRunningMicrotasks( - script_state->GetIsolate()); - case EventDispatchState::kInitial: - case EventDispatchState::kDispatched: - case EventDispatchState::kFailed: - return false; - } - NOTREACHED(); +bool WaitUntilObserver::IsDispatchingEvent() const { + return event_dispatch_state_ == EventDispatchState::kDispatching; } WaitUntilObserver::WaitUntilObserver(ExecutionContext* context, EventType type, int event_id) - : execution_context_(context), + : ContextClient(context), type_(type), event_id_(event_id), consume_window_interaction_timer_( @@ -223,7 +219,7 @@ void WaitUntilObserver::DecrementPendingPromiseCount() { } void WaitUntilObserver::MaybeCompleteEvent() { - if (!execution_context_) + if (!GetExecutionContext()) return; switch (event_dispatch_state_) { @@ -246,7 +242,7 @@ void WaitUntilObserver::MaybeCompleteEvent() { } ServiceWorkerGlobalScopeClient* client = - ServiceWorkerGlobalScopeClient::From(execution_context_); + ServiceWorkerGlobalScopeClient::From(GetExecutionContext()); mojom::ServiceWorkerEventStatus status = (event_dispatch_state_ == EventDispatchState::kFailed || has_rejected_promise_) @@ -269,7 +265,8 @@ void WaitUntilObserver::MaybeCompleteEvent() { client->DidHandleFetchEvent(event_id_, status); break; case kInstall: - To<ServiceWorkerGlobalScope>(*execution_context_).SetIsInstalling(false); + To<ServiceWorkerGlobalScope>(*GetExecutionContext()) + .SetIsInstalling(false); client->DidHandleInstallEvent(event_id_, status); break; case kMessage: @@ -305,17 +302,15 @@ void WaitUntilObserver::MaybeCompleteEvent() { client->DidHandleBackgroundFetchSuccessEvent(event_id_, status); break; } - execution_context_ = nullptr; } void WaitUntilObserver::ConsumeWindowInteraction(TimerBase*) { - if (!execution_context_) - return; - execution_context_->ConsumeWindowInteraction(); + if (ExecutionContext* context = GetExecutionContext()) + context->ConsumeWindowInteraction(); } void WaitUntilObserver::Trace(blink::Visitor* visitor) { - visitor->Trace(execution_context_); + ContextClient::Trace(visitor); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h index 2f025fc8070..4a80d125d2e 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h +++ b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h @@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_WAIT_UNTIL_OBSERVER_H_ #include "base/callback.h" +#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h" #include "third_party/blink/renderer/platform/timer.h" @@ -14,14 +15,16 @@ namespace blink { class ExceptionState; -class ExecutionContext; class ScriptPromise; class ScriptState; class ScriptValue; // Created for each ExtendableEvent instance. class MODULES_EXPORT WaitUntilObserver final - : public GarbageCollectedFinalized<WaitUntilObserver> { + : public GarbageCollectedFinalized<WaitUntilObserver>, + public ContextClient { + USING_GARBAGE_COLLECTED_MIXIN(WaitUntilObserver); + public: using PromiseSettledCallback = base::RepeatingCallback<void(const ScriptValue&)>; @@ -58,13 +61,19 @@ class MODULES_EXPORT WaitUntilObserver final void DidDispatchEvent(bool event_dispatch_failed); // Observes the promise and delays reporting to ServiceWorkerGlobalScopeClient - // that the event completed until the given promise is resolved or rejected. + // that the event completed until the promise is resolved or rejected. + // // WaitUntil may be called multiple times. The event is extended until all // promises have settled. + // // If provided, |on_promise_fulfilled| or |on_promise_rejected| is invoked // once |script_promise| fulfills or rejects. This enables the caller to do // custom handling. - void WaitUntil( + // + // If the event is not active, throws a DOMException and returns false. In + // this case the promise is ignored, and |on_promise_fulfilled| and + // |on_promise_rejected| will not be called. + bool WaitUntil( ScriptState*, ScriptPromise /* script_promise */, ExceptionState&, @@ -73,9 +82,15 @@ class MODULES_EXPORT WaitUntilObserver final // Whether the associated event is active. // https://w3c.github.io/ServiceWorker/#extendableevent-active. - bool IsEventActive(ScriptState* script_state) const; + bool IsEventActive() const; + + // Whether the event is being dispatched, i.e., the event handler + // is being run. + // https://dom.spec.whatwg.org/#dispatch-flag + // TODO(falken): Can this just use Event::IsBeingDispatched? + bool IsDispatchingEvent() const; - virtual void Trace(blink::Visitor*); + void Trace(blink::Visitor*) override; private: friend class InternalsServiceWorker; @@ -108,7 +123,6 @@ class MODULES_EXPORT WaitUntilObserver final void MaybeCompleteEvent(); - Member<ExecutionContext> execution_context_; EventType type_; int event_id_; int pending_promises_ = 0; diff --git a/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc index 8153e348947..1ae16b666e3 100644 --- a/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc +++ b/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc @@ -6,15 +6,20 @@ #include <memory> +#include "base/feature_list.h" #include "base/synchronization/waitable_event.h" +#include "base/test/scoped_feature_list.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" +#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h" #include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_content_settings_client.h" +#include "third_party/blink/public/platform/web_url_loader_client.h" #include "third_party/blink/public/platform/web_url_loader_mock_factory.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h" @@ -25,14 +30,17 @@ #include "third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" namespace blink { namespace { +const char* kNotFoundScriptURL = "https://www.example.com/sw-404.js"; + // Fake network provider for service worker execution contexts. -class FakeServiceWorkerNetworkProvider +class FakeServiceWorkerNetworkProvider final : public WebServiceWorkerNetworkProvider { public: FakeServiceWorkerNetworkProvider() = default; @@ -62,7 +70,85 @@ class FakeServiceWorkerNetworkProvider void DispatchNetworkQuiet() override {} }; -class MockServiceWorkerContextClient : public WebServiceWorkerContextClient { +// A fake WebURLLoader which is used for off-main-thread script fetch tests. +class FakeWebURLLoader final : public WebURLLoader { + public: + FakeWebURLLoader() {} + ~FakeWebURLLoader() override = default; + + void LoadSynchronously(const WebURLRequest&, + WebURLLoaderClient*, + WebURLResponse&, + base::Optional<WebURLError>&, + WebData&, + int64_t& encoded_data_length, + int64_t& encoded_body_length, + WebBlobInfo& downloaded_blob) override { + NOTREACHED(); + } + + void LoadAsynchronously(const WebURLRequest& request, + WebURLLoaderClient* client) override { + if (request.Url().GetString() == kNotFoundScriptURL) { + WebURLResponse response; + response.SetMimeType("text/javascript"); + response.SetHttpStatusCode(404); + client->DidReceiveResponse(response); + client->DidFinishLoading(TimeTicks(), 0, 0, 0, false, {}); + return; + } + // Don't handle other requests intentionally to emulate ongoing load. + } + + void Cancel() override {} + void SetDefersLoading(bool defers) override {} + void DidChangePriority(WebURLRequest::Priority, int) override {} + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override { + return base::MakeRefCounted<scheduler::FakeTaskRunner>(); + } +}; + +// A fake WebURLLoaderFactory which is used for off-main-thread script fetch +// tests. +class FakeWebURLLoaderFactory final : public WebURLLoaderFactory { + public: + std::unique_ptr<WebURLLoader> CreateURLLoader( + const WebURLRequest&, + std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>) override { + return std::make_unique<FakeWebURLLoader>(); + } +}; + +// A fake WebWorkerFetchContext which is used for off-main-thread script fetch +// tests. +class FakeWebWorkerFetchContext final : public WebWorkerFetchContext { + public: + void SetTerminateSyncLoadEvent(base::WaitableEvent*) override {} + void InitializeOnWorkerThread(AcceptLanguagesWatcher*) override {} + WebURLLoaderFactory* GetURLLoaderFactory() override { + return &fake_web_url_loader_factory_; + } + std::unique_ptr<WebURLLoaderFactory> WrapURLLoaderFactory( + mojo::ScopedMessagePipeHandle url_loader_factory_handle) override { + return nullptr; + } + void WillSendRequest(WebURLRequest&) override {} + mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() + const override { + return mojom::ControllerServiceWorkerMode::kNoController; + } + WebURL SiteForCookies() const override { return WebURL(); } + base::Optional<WebSecurityOrigin> TopFrameOrigin() const override { + return base::Optional<WebSecurityOrigin>(); + } + WebString GetAcceptLanguages() const override { return WebString(); } + + private: + FakeWebURLLoaderFactory fake_web_url_loader_factory_; +}; + +class MockServiceWorkerContextClient final + : public WebServiceWorkerContextClient { public: MockServiceWorkerContextClient() = default; ~MockServiceWorkerContextClient() override = default; @@ -78,6 +164,14 @@ class MockServiceWorkerContextClient : public WebServiceWorkerContextClient { // message. proxy->ReadyToEvaluateScript(); } + + void FailedToLoadClassicScript() override { + // off-main-script fetch: + // In production code, calling FailedToLoadClassicScript results in + // terminating the worker. + classic_script_load_failure_event_.Signal(); + } + void DidEvaluateScript(bool /* success */) override { script_evaluated_event_.Signal(); } @@ -86,14 +180,26 @@ class MockServiceWorkerContextClient : public WebServiceWorkerContextClient { CreateServiceWorkerNetworkProviderOnMainThread() override { return std::make_unique<FakeServiceWorkerNetworkProvider>(); } + + scoped_refptr<WebWorkerFetchContext> + CreateServiceWorkerFetchContextOnMainThread( + WebServiceWorkerNetworkProvider* network_provider) override { + return base::MakeRefCounted<FakeWebWorkerFetchContext>(); + } + void WorkerContextDestroyed() override { termination_event_.Signal(); } + // These methods must be called on the main thread. void WaitUntilScriptEvaluated() { script_evaluated_event_.Wait(); } void WaitUntilThreadTermination() { termination_event_.Wait(); } + void WaitUntilFailedToLoadClassicScript() { + classic_script_load_failure_event_.Wait(); + } private: base::WaitableEvent script_evaluated_event_; base::WaitableEvent termination_event_; + base::WaitableEvent classic_script_load_failure_event_; }; class MockServiceWorkerInstalledScriptsManager @@ -123,18 +229,17 @@ class MockServiceWorkerInstalledScriptsManager class WebEmbeddedWorkerImplTest : public testing::Test { protected: void SetUp() override { - auto client = std::make_unique<MockServiceWorkerContextClient>(); auto installed_scripts_manager = std::make_unique<MockServiceWorkerInstalledScriptsManager>(); - mock_client_ = client.get(); mock_installed_scripts_manager_ = installed_scripts_manager.get(); + mock_client_ = std::make_unique<MockServiceWorkerContextClient>(); worker_ = WebEmbeddedWorkerImpl::CreateForTesting( - std::move(client), std::move(installed_scripts_manager)); + mock_client_.get(), std::move(installed_scripts_manager)); WebURL script_url = url_test_helpers::ToKURL("https://www.example.com/sw.js"); WebURLResponse response(script_url); - response.SetMIMEType("text/javascript"); + response.SetMimeType("text/javascript"); response.SetHttpStatusCode(200); Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(script_url, response, ""); @@ -156,7 +261,7 @@ class WebEmbeddedWorkerImplTest : public testing::Test { } WebEmbeddedWorkerStartData start_data_; - MockServiceWorkerContextClient* mock_client_; + std::unique_ptr<MockServiceWorkerContextClient> mock_client_; MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_; std::unique_ptr<WebEmbeddedWorkerImpl> worker_; }; @@ -164,28 +269,69 @@ class WebEmbeddedWorkerImplTest : public testing::Test { } // namespace TEST_F(WebEmbeddedWorkerImplTest, TerminateSoonAfterStart) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); EXPECT_CALL(*mock_client_, WorkerContextFailedToStartOnMainThread()).Times(1); worker_->TerminateWorkerContext(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); +} + +TEST_F(WebEmbeddedWorkerImplTest, TerminateSoonAfterStart_OMT_Fetch) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); + worker_->StartWorkerContext(start_data_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); + + worker_->TerminateWorkerContext(); + // The worker thread was started. Wait for shutdown tasks to finish. + worker_->WaitForShutdownForTesting(); } TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileWaitingForDebugger) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); start_data_.wait_for_debugger_mode = WebEmbeddedWorkerStartData::kWaitForDebugger; worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); EXPECT_CALL(*mock_client_, WorkerContextFailedToStartOnMainThread()).Times(1); worker_->TerminateWorkerContext(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); +} + +TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileWaitingForDebugger_OMT_Fetch) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); + start_data_.wait_for_debugger_mode = + WebEmbeddedWorkerStartData::kWaitForDebugger; + worker_->StartWorkerContext(start_data_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); + + worker_->TerminateWorkerContext(); + // The worker thread isn't started yet so we don't have to wait for shutdown. } TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + // Load the shadow page. EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); EXPECT_CALL(*mock_installed_scripts_manager_, @@ -193,16 +339,45 @@ TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) { .Times(testing::AtLeast(1)) .WillRepeatedly(testing::Return(false)); worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Terminate before loading the script. EXPECT_CALL(*mock_client_, WorkerContextFailedToStartOnMainThread()).Times(1); worker_->TerminateWorkerContext(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); +} + +TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript_OMT_Fetch) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + + // Load the shadow page. + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); + EXPECT_CALL(*mock_installed_scripts_manager_, + IsScriptInstalled(KURL(start_data_.script_url))) + .Times(testing::AtLeast(1)) + .WillRepeatedly(testing::Return(false)); + worker_->StartWorkerContext(start_data_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); + testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); + + // Terminate before finishing the script load. + worker_->TerminateWorkerContext(); + // The worker thread was started. Wait for shutdown tasks to finish. + worker_->WaitForShutdownForTesting(); } +// Tests terminating worker context between script download and execution. +// No "OMT_Fetch" variant for this test because "pause after download" doesn't +// have effect for off-main-thread script fetch. When off-main-thread fetch +// is on, pausing/resuming is handled in ServiceWorkerGlobalScope. TEST_F(WebEmbeddedWorkerImplTest, TerminateWhilePausedAfterDownload) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + // Load the shadow page. start_data_.pause_after_download_mode = WebEmbeddedWorkerStartData::kPauseAfterDownload; @@ -212,26 +387,29 @@ TEST_F(WebEmbeddedWorkerImplTest, TerminateWhilePausedAfterDownload) { .Times(testing::AtLeast(1)) .WillRepeatedly(testing::Return(false)); worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Load the script. EXPECT_CALL(*mock_client_, WorkerScriptLoadedOnMainThread()).Times(1); Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); // Terminate before resuming after download. EXPECT_CALL(*mock_client_, WorkerContextFailedToStartOnMainThread()).Times(1); worker_->TerminateWorkerContext(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); } TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + // Load the shadow page. - WebURL script_url = - url_test_helpers::ToKURL("https://www.example.com/sw-404.js"); + WebURL script_url = url_test_helpers::ToKURL(kNotFoundScriptURL); WebURLResponse response; - response.SetMIMEType("text/javascript"); + response.SetMimeType("text/javascript"); response.SetHttpStatusCode(404); ResourceError error = ResourceError::Failure(script_url); Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL( @@ -243,24 +421,61 @@ TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) { .Times(testing::AtLeast(1)) .WillRepeatedly(testing::Return(false)); worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Load the script. EXPECT_CALL(*mock_client_, WorkerScriptLoadedOnMainThread()).Times(0); EXPECT_CALL(*mock_client_, WorkerContextFailedToStartOnMainThread()).Times(1); Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); +} + +TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound_OMT_Fetch) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + + // Load the shadow page. + WebURL script_url = url_test_helpers::ToKURL(kNotFoundScriptURL); + WebURLResponse response; + response.SetMimeType("text/javascript"); + response.SetHttpStatusCode(404); + ResourceError error = ResourceError::Failure(script_url); + Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL( + script_url, response, error); + start_data_.script_url = script_url; + EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); + EXPECT_CALL(*mock_installed_scripts_manager_, + IsScriptInstalled(KURL(start_data_.script_url))) + .Times(testing::AtLeast(1)) + .WillRepeatedly(testing::Return(false)); + // Start worker and load the script. + worker_->StartWorkerContext(start_data_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); + testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); + + mock_client_->WaitUntilFailedToLoadClassicScript(); + + // The worker thread was started. Ask to shutdown and wait for shutdown + // tasks to finish. + worker_->TerminateWorkerContext(); + worker_->WaitForShutdownForTesting(); } // The running worker is detected as a memory leak. crbug.com/586897 and // crbug.com/807754. +// No "OMT_Fetch" variant. See comments on TerminateWhilePausedAfterDownload. #if defined(ADDRESS_SANITIZER) #define MAYBE_DontPauseAfterDownload DISABLED_DontPauseAfterDownload #else #define MAYBE_DontPauseAfterDownload DontPauseAfterDownload #endif TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + // Load the shadow page. EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); EXPECT_CALL(*mock_installed_scripts_manager_, @@ -268,7 +483,7 @@ TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) { .Times(testing::AtLeast(1)) .WillRepeatedly(testing::Return(false)); worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Load the script. @@ -280,7 +495,7 @@ TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) { .WillRepeatedly(testing::Return(false)); Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); mock_client_->WaitUntilScriptEvaluated(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Terminate the running worker thread. @@ -291,12 +506,17 @@ TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) { // The running worker is detected as a memory leak. crbug.com/586897 and // crbug.com/807754. +// No "OMT_Fetch" variant. See comments on TerminateWhilePausedAfterDownload. #if defined(ADDRESS_SANITIZER) #define MAYBE_PauseAfterDownload DISABLED_PauseAfterDownload #else #define MAYBE_PauseAfterDownload PauseAfterDownload #endif TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature( + features::kOffMainThreadServiceWorkerScriptFetch); + // Load the shadow page. EXPECT_CALL(*mock_client_, WorkerReadyForInspectionOnMainThread()).Times(1); EXPECT_CALL(*mock_installed_scripts_manager_, @@ -306,13 +526,13 @@ TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) { start_data_.pause_after_download_mode = WebEmbeddedWorkerStartData::kPauseAfterDownload; worker_->StartWorkerContext(start_data_); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Load the script. EXPECT_CALL(*mock_client_, WorkerScriptLoadedOnMainThread()).Times(1); Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); // Resume after download. // This is called on the worker thread. @@ -322,7 +542,7 @@ TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) { .WillRepeatedly(testing::Return(false)); worker_->ResumeAfterDownload(); mock_client_->WaitUntilScriptEvaluated(); - testing::Mock::VerifyAndClearExpectations(mock_client_); + testing::Mock::VerifyAndClearExpectations(mock_client_.get()); testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_); // Terminate the running worker thread. |