blob: 8e50f970578930d32c5a08e54df61d2803e21a8b [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h"
#include <memory>
#include <utility>
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/web_serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/headers.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event_init.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event_init.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event_init.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event_init.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h"
#include "third_party/blink/renderer/modules/background_sync/sync_event.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_change_event.h"
#include "third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h"
#include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
#include "third_party/blink/renderer/modules/notifications/notification_event.h"
#include "third_party/blink/renderer/modules/notifications/notification_event_init.h"
#include "third_party/blink/renderer/modules/payments/abort_payment_event.h"
#include "third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h"
#include "third_party/blink/renderer/modules/payments/can_make_payment_event.h"
#include "third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h"
#include "third_party/blink/renderer/modules/payments/payment_event_data_conversion.h"
#include "third_party/blink/renderer/modules/payments/payment_request_event.h"
#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
#include "third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h"
#include "third_party/blink/renderer/modules/push_messaging/push_event.h"
#include "third_party/blink/renderer/modules/push_messaging/push_message_data.h"
#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
#include "third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h"
#include "third_party/blink/renderer/modules/serviceworkers/fetch_event.h"
#include "third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h"
#include "third_party/blink/renderer/modules/serviceworkers/install_event.h"
#include "third_party/blink/renderer/modules/serviceworkers/service_worker_client.h"
#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
namespace {
void SetContentSecurityPolicyAndReferrerPolicyOnMainThread(
WebEmbeddedWorkerImpl* embedded_worker,
ContentSecurityPolicyResponseHeaders csp_headers,
String referrer_policy,
WaitableEvent* waitable_event) {
DCHECK(IsMainThread());
ContentSecurityPolicy* content_security_policy =
ContentSecurityPolicy::Create();
content_security_policy->DidReceiveHeaders(csp_headers);
embedded_worker->SetContentSecurityPolicyAndReferrerPolicy(
content_security_policy, std::move(referrer_policy));
waitable_event->Signal();
}
} // namespace
ServiceWorkerGlobalScopeProxy* ServiceWorkerGlobalScopeProxy::Create(
WebEmbeddedWorkerImpl& embedded_worker,
WebServiceWorkerContextClient& client) {
return new ServiceWorkerGlobalScopeProxy(embedded_worker, client);
}
ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() {
DCHECK(IsMainThread());
// Verify that the proxy has been detached.
DCHECK(!embedded_worker_);
}
void ServiceWorkerGlobalScopeProxy::Trace(blink::Visitor* visitor) {
visitor->Trace(parent_execution_context_task_runners_);
}
void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() {
WorkerGlobalScope()->ReadyToEvaluateScript();
}
void ServiceWorkerGlobalScopeProxy::SetRegistration(
std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WorkerGlobalScope()->SetRegistration(std::move(handle));
}
void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent(
int event_id,
const WebString& developer_id,
const WebString& unique_id,
const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id);
ScriptState* script_state =
WorkerGlobalScope()->ScriptController()->GetScriptState();
// Do not remove this, |scope| is needed by
// BackgroundFetchSettledFetches::Create which eventually calls ToV8.
ScriptState::Scope scope(script_state);
BackgroundFetchSettledEventInit init;
init.setId(developer_id);
init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
BackgroundFetchSettledEvent* event = BackgroundFetchSettledEvent::Create(
EventTypeNames::backgroundfetchabort, init, unique_id, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent(
int event_id,
const WebString& developer_id,
BackgroundFetchState status) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id);
BackgroundFetchClickEventInit init;
init.setId(developer_id);
switch (status) {
case BackgroundFetchState::kPending:
init.setState("pending");
break;
case BackgroundFetchState::kSucceeded:
init.setState("succeeded");
break;
case BackgroundFetchState::kFailed:
init.setState("failed");
break;
}
BackgroundFetchClickEvent* event = BackgroundFetchClickEvent::Create(
EventTypeNames::backgroundfetchclick, init, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent(
int event_id,
const WebString& developer_id,
const WebString& unique_id,
const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id);
ScriptState* script_state =
WorkerGlobalScope()->ScriptController()->GetScriptState();
// Do not remove this, |scope| is needed by
// BackgroundFetchSettledFetches::Create which eventually calls ToV8.
ScriptState::Scope scope(script_state);
BackgroundFetchSettledEventInit init;
init.setId(developer_id);
init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
EventTypeNames::backgroundfetched, init, unique_id, script_state,
observer, worker_global_scope_->registration());
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchedEvent(
int event_id,
const WebString& developer_id,
const WebString& unique_id,
const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetched, event_id);
ScriptState* script_state =
WorkerGlobalScope()->ScriptController()->GetScriptState();
// Do not remove this, |scope| is needed by
// BackgroundFetchSettledFetches::Create which eventually calls ToV8.
ScriptState::Scope scope(script_state);
BackgroundFetchSettledEventInit init;
init.setId(developer_id);
init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
EventTypeNames::backgroundfetched, init, unique_id, script_state,
observer, worker_global_scope_->registration());
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchActivateEvent(int event_id) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kActivate, event_id);
Event* event = ExtendableEvent::Create(EventTypeNames::activate,
ExtendableEventInit(), observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchCookieChangeEvent(
int event_id,
const WebCanonicalCookie& cookie,
network::mojom::CookieChangeCause change_cause) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kCookieChange, event_id);
HeapVector<CookieListItem> changed;
HeapVector<CookieListItem> deleted;
CookieChangeEvent::ToEventInfo(cookie, change_cause, changed, deleted);
Event* event = ExtendableCookieChangeEvent::Create(
EventTypeNames::cookiechange, std::move(changed), std::move(deleted),
observer);
// TODO(pwnall): Handle handle the case when
// (changed.IsEmpty() && deleted.IsEmpty()).
// TODO(pwnall): Investigate dispatching this on cookieStore.
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
int event_id,
TransferableMessage message,
const WebSecurityOrigin& source_origin,
const WebServiceWorkerClientInfo& client) {
DCHECK(WorkerGlobalScope()->IsContextThread());
auto msg = ToBlinkTransferableMessage(std::move(message));
MessagePortArray* ports =
MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
String origin;
if (!source_origin.IsOpaque())
origin = source_origin.ToString();
ServiceWorkerClient* source = nullptr;
if (client.client_type == mojom::ServiceWorkerClientType::kWindow)
source = ServiceWorkerWindowClient::Create(client);
else
source = ServiceWorkerClient::Create(client);
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
ports, source, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
int event_id,
TransferableMessage message,
const WebSecurityOrigin& source_origin,
std::unique_ptr<WebServiceWorker::Handle> handle) {
DCHECK(WorkerGlobalScope()->IsContextThread());
auto msg = ToBlinkTransferableMessage(std::move(message));
MessagePortArray* ports =
MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
String origin;
if (!source_origin.IsOpaque())
origin = source_origin.ToString();
ServiceWorker* source =
ServiceWorker::From(worker_global_scope_->GetExecutionContext(),
base::WrapUnique(handle.release()));
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
ports, source, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchFetchEvent(
int fetch_event_id,
const WebServiceWorkerRequest& web_request,
bool navigation_preload_sent) {
DCHECK(WorkerGlobalScope()->IsContextThread());
ScriptState::Scope scope(
WorkerGlobalScope()->ScriptController()->GetScriptState());
WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kFetch, fetch_event_id);
FetchRespondWithObserver* respond_with_observer =
FetchRespondWithObserver::Create(
WorkerGlobalScope(), fetch_event_id, web_request.Url(),
web_request.Mode(), web_request.RedirectMode(),
web_request.GetFrameType(), web_request.GetRequestContext(),
wait_until_observer);
Request* request = Request::Create(
WorkerGlobalScope()->ScriptController()->GetScriptState(), web_request);
request->getHeaders()->SetGuard(Headers::kImmutableGuard);
FetchEventInit event_init;
event_init.setCancelable(true);
event_init.setRequest(request);
event_init.setClientId(
web_request.IsMainResourceLoad() ? WebString() : web_request.ClientId());
event_init.setIsReload(web_request.IsReload());
ScriptState* script_state =
WorkerGlobalScope()->ScriptController()->GetScriptState();
FetchEvent* fetch_event = FetchEvent::Create(
script_state, EventTypeNames::fetch, event_init, respond_with_observer,
wait_until_observer, navigation_preload_sent);
if (navigation_preload_sent) {
// Keep |fetchEvent| until OnNavigationPreloadComplete() or
// onNavigationPreloadError() will be called.
pending_preload_fetch_events_.insert(fetch_event_id, fetch_event);
}
WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
fetch_event, wait_until_observer, respond_with_observer);
}
void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<WebURLResponse> response,
std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
DCHECK(WorkerGlobalScope()->IsContextThread());
auto it = pending_preload_fetch_events_.find(fetch_event_id);
DCHECK(it != pending_preload_fetch_events_.end());
FetchEvent* fetch_event = it->value.Get();
DCHECK(fetch_event);
fetch_event->OnNavigationPreloadResponse(
WorkerGlobalScope()->ScriptController()->GetScriptState(),
std::move(response), std::move(data_consume_handle));
}
void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
int fetch_event_id,
std::unique_ptr<WebServiceWorkerError> error) {
DCHECK(WorkerGlobalScope()->IsContextThread());
FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
DCHECK(fetch_event);
// Display an unsanitized console message.
if (!error->unsanitized_message.IsEmpty()) {
WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create(
kWorkerMessageSource, blink::MessageLevel::kErrorMessageLevel,
error->unsanitized_message));
}
// Reject the preloadResponse promise.
fetch_event->OnNavigationPreloadError(
WorkerGlobalScope()->ScriptController()->GetScriptState(),
std::move(error));
}
void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadComplete(
int fetch_event_id,
TimeTicks completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
DCHECK(WorkerGlobalScope()->IsContextThread());
FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
DCHECK(fetch_event);
fetch_event->OnNavigationPreloadComplete(
WorkerGlobalScope(), completion_time, encoded_data_length,
encoded_body_length, decoded_body_length);
}
void ServiceWorkerGlobalScopeProxy::DispatchInstallEvent(int event_id) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kInstall, event_id);
Event* event = InstallEvent::Create(
EventTypeNames::install, ExtendableEventInit(), event_id, observer);
WorkerGlobalScope()->SetIsInstalling(true);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchNotificationClickEvent(
int event_id,
const WebString& notification_id,
const WebNotificationData& data,
int action_index,
const WebString& reply) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kNotificationClick, event_id);
NotificationEventInit event_init;
event_init.setNotification(Notification::Create(
WorkerGlobalScope(), notification_id, data, true /* showing */));
if (0 <= action_index && action_index < static_cast<int>(data.actions.size()))
event_init.setAction(data.actions[action_index].action);
event_init.setReply(reply);
Event* event = NotificationEvent::Create(EventTypeNames::notificationclick,
event_init, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchNotificationCloseEvent(
int event_id,
const WebString& notification_id,
const WebNotificationData& data) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kNotificationClose, event_id);
NotificationEventInit event_init;
event_init.setAction(WTF::String()); // initialize as null.
event_init.setNotification(Notification::Create(
WorkerGlobalScope(), notification_id, data, false /* showing */));
Event* event = NotificationEvent::Create(EventTypeNames::notificationclose,
event_init, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchPushEvent(int event_id,
const WebString& data) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kPush, event_id);
Event* event = PushEvent::Create(EventTypeNames::push,
PushMessageData::Create(data), observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchSyncEvent(int event_id,
const WebString& id,
bool last_chance) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kSync, event_id);
Event* event =
SyncEvent::Create(EventTypeNames::sync, id, last_chance, observer);
WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchAbortPaymentEvent(int event_id) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kAbortPayment, event_id);
AbortPaymentRespondWithObserver* respond_with_observer =
new AbortPaymentRespondWithObserver(WorkerGlobalScope(), event_id,
wait_until_observer);
Event* event = AbortPaymentEvent::Create(
EventTypeNames::abortpayment, ExtendableEventInit(),
respond_with_observer, wait_until_observer);
WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
event, wait_until_observer, respond_with_observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchCanMakePaymentEvent(
int event_id,
const WebCanMakePaymentEventData& web_event_data) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kCanMakePayment, event_id);
CanMakePaymentRespondWithObserver* respond_with_observer =
new CanMakePaymentRespondWithObserver(WorkerGlobalScope(), event_id,
wait_until_observer);
Event* event = CanMakePaymentEvent::Create(
EventTypeNames::canmakepayment,
PaymentEventDataConversion::ToCanMakePaymentEventInit(
WorkerGlobalScope()->ScriptController()->GetScriptState(),
web_event_data),
respond_with_observer, wait_until_observer);
WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
event, wait_until_observer, respond_with_observer);
}
void ServiceWorkerGlobalScopeProxy::DispatchPaymentRequestEvent(
int event_id,
const WebPaymentRequestEventData& web_app_request) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
WorkerGlobalScope(), WaitUntilObserver::kPaymentRequest, event_id);
PaymentRequestRespondWithObserver* respond_with_observer =
PaymentRequestRespondWithObserver::Create(WorkerGlobalScope(), event_id,
wait_until_observer);
Event* event = PaymentRequestEvent::Create(
EventTypeNames::paymentrequest,
PaymentEventDataConversion::ToPaymentRequestEventInit(
WorkerGlobalScope()->ScriptController()->GetScriptState(),
web_app_request),
respond_with_observer, wait_until_observer);
WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
event, wait_until_observer, respond_with_observer);
}
bool ServiceWorkerGlobalScopeProxy::HasFetchEventHandler() {
DCHECK(WorkerGlobalScope()->IsContextThread());
return WorkerGlobalScope()->HasEventListeners(EventTypeNames::fetch);
}
void ServiceWorkerGlobalScopeProxy::CountFeature(WebFeature feature) {
Client().CountFeature(feature);
}
void ServiceWorkerGlobalScopeProxy::CountDeprecation(WebFeature feature) {
// Go through the same code path with countFeature() because a deprecation
// message is already shown on the worker console and a remaining work is just
// to record an API use.
CountFeature(feature);
}
void ServiceWorkerGlobalScopeProxy::ReportException(
const String& error_message,
std::unique_ptr<SourceLocation> location,
int exception_id) {
Client().ReportException(error_message, location->LineNumber(),
location->ColumnNumber(), location->Url());
}
void ServiceWorkerGlobalScopeProxy::ReportConsoleMessage(
MessageSource source,
MessageLevel level,
const String& message,
SourceLocation* location) {
Client().ReportConsoleMessage(source, level, message, location->LineNumber(),
location->Url());
}
void ServiceWorkerGlobalScopeProxy::PostMessageToPageInspector(
int session_id,
const String& message) {
DCHECK(embedded_worker_);
PostCrossThreadTask(
*parent_execution_context_task_runners_->Get(
TaskType::kInternalInspector),
FROM_HERE,
CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
CrossThreadUnretained(embedded_worker_), session_id,
message));
}
void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
WorkerOrWorkletGlobalScope* worker_global_scope) {
DCHECK(!worker_global_scope_);
worker_global_scope_ =
static_cast<ServiceWorkerGlobalScope*>(worker_global_scope);
Client().WorkerContextStarted(this);
}
void ServiceWorkerGlobalScopeProxy::DidInitializeWorkerContext() {
DCHECK(WorkerGlobalScope()->IsContextThread());
ScriptState::Scope scope(
WorkerGlobalScope()->ScriptController()->GetScriptState());
Client().DidInitializeWorkerContext(
WorkerGlobalScope()->ScriptController()->GetContext());
}
void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript(
const ContentSecurityPolicyResponseHeaders& csp_headers_on_worker_thread,
const String& referrer_policy_on_worker_thread) {
// Post a task to the main thread to set CSP and ReferrerPolicy on the shadow
// page.
DCHECK(embedded_worker_);
WaitableEvent waitable_event;
PostCrossThreadTask(
*parent_execution_context_task_runners_->Get(TaskType::kInternalWorker),
FROM_HERE,
CrossThreadBind(&SetContentSecurityPolicyAndReferrerPolicyOnMainThread,
CrossThreadUnretained(embedded_worker_),
csp_headers_on_worker_thread,
referrer_policy_on_worker_thread,
CrossThreadUnretained(&waitable_event)));
Client().WorkerScriptLoaded();
// Wait for the task to complete before returning. This ensures that worker
// script evaluation can't start and issue any fetches until CSP and
// ReferrerPolicy are set.
waitable_event.Wait();
}
void ServiceWorkerGlobalScopeProxy::WillEvaluateClassicScript(
size_t script_size,
size_t cached_metadata_size) {
DCHECK(WorkerGlobalScope()->IsContextThread());
worker_global_scope_->CountWorkerScript(script_size, cached_metadata_size);
}
void ServiceWorkerGlobalScopeProxy::WillEvaluateImportedClassicScript(
size_t script_size,
size_t cached_metadata_size) {
DCHECK(WorkerGlobalScope()->IsContextThread());
worker_global_scope_->CountImportedScript(script_size, cached_metadata_size);
}
void ServiceWorkerGlobalScopeProxy::DidEvaluateClassicScript(bool success) {
DCHECK(WorkerGlobalScope()->IsContextThread());
WorkerGlobalScope()->DidEvaluateClassicScript();
Client().DidEvaluateClassicScript(success);
}
void ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() {
// This should never be called because close() is not defined in
// ServiceWorkerGlobalScope.
NOTREACHED();
}
void ServiceWorkerGlobalScopeProxy::WillDestroyWorkerGlobalScope() {
DCHECK(WorkerGlobalScope()->IsContextThread());
v8::HandleScope handle_scope(WorkerGlobalScope()->GetThread()->GetIsolate());
Client().WillDestroyWorkerContext(
WorkerGlobalScope()->ScriptController()->GetContext());
worker_global_scope_ = nullptr;
}
void ServiceWorkerGlobalScopeProxy::DidTerminateWorkerThread() {
// This should be called after WillDestroyWorkerGlobalScope().
DCHECK(!worker_global_scope_);
Client().WorkerContextDestroyed();
}
ServiceWorkerGlobalScopeProxy::ServiceWorkerGlobalScopeProxy(
WebEmbeddedWorkerImpl& embedded_worker,
WebServiceWorkerContextClient& client)
: embedded_worker_(&embedded_worker),
client_(&client),
worker_global_scope_(nullptr) {
DCHECK(IsMainThread());
// ServiceWorker can sometimes run tasks that are initiated by/associated with
// a document's frame but these documents can be from a different process. So
// we intentionally populate the task runners with default task runners of the
// main thread.
parent_execution_context_task_runners_ =
ParentExecutionContextTaskRunners::Create();
}
void ServiceWorkerGlobalScopeProxy::Detach() {
DCHECK(IsMainThread());
embedded_worker_ = nullptr;
client_ = nullptr;
}
void ServiceWorkerGlobalScopeProxy::TerminateWorkerContext() {
embedded_worker_->TerminateWorkerContext();
}
WebServiceWorkerContextClient& ServiceWorkerGlobalScopeProxy::Client() const {
DCHECK(client_);
return *client_;
}
ServiceWorkerGlobalScope* ServiceWorkerGlobalScopeProxy::WorkerGlobalScope()
const {
DCHECK(worker_global_scope_);
DCHECK(worker_global_scope_->IsContextThread());
return worker_global_scope_;
}
} // namespace blink