|
@@ -0,0 +1,3110 @@
|
|
|
+# HG changeset patch
|
|
|
+# User Ben Kelly <ben@wanderview.com>
|
|
|
+# Date 1513111487 18000
|
|
|
+# Node ID 63938d2d5492022b7d3808d11a87faf83742ed6b
|
|
|
+# Parent 326a1ff52d1ac22dbd066731eb3b326f490d74d5
|
|
|
+Bug 1293277 P5 Switch bindings over to new Client and Clients classes. r=baku
|
|
|
+
|
|
|
+diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
|
|
|
+--- a/dom/bindings/Bindings.conf
|
|
|
++++ b/dom/bindings/Bindings.conf
|
|
|
+@@ -148,26 +148,16 @@ DOMInterfaces = {
|
|
|
+ 'concrete': False,
|
|
|
+ },
|
|
|
+
|
|
|
+ 'ChromeWorker': {
|
|
|
+ 'headerFile': 'mozilla/dom/WorkerPrivate.h',
|
|
|
+ 'nativeType': 'mozilla::dom::workers::ChromeWorkerPrivate',
|
|
|
+ },
|
|
|
+
|
|
|
+-'Client': {
|
|
|
+- 'nativeType': 'mozilla::dom::workers::ServiceWorkerClient',
|
|
|
+- 'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerClient.h',
|
|
|
+-},
|
|
|
+-
|
|
|
+-'Clients': {
|
|
|
+- 'nativeType': 'mozilla::dom::workers::ServiceWorkerClients',
|
|
|
+- 'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerClients.h',
|
|
|
+-},
|
|
|
+-
|
|
|
+ 'console': {
|
|
|
+ 'nativeType': 'mozilla::dom::Console',
|
|
|
+ },
|
|
|
+
|
|
|
+ 'ConvolverNode': {
|
|
|
+ 'implicitJSContext': [ 'buffer' ],
|
|
|
+ },
|
|
|
+
|
|
|
+@@ -1116,18 +1106,17 @@ DOMInterfaces = {
|
|
|
+ 'nativeType': 'mozilla::extensions::WebExtensionContentScript',
|
|
|
+ },
|
|
|
+
|
|
|
+ 'WebExtensionPolicy': {
|
|
|
+ 'nativeType': 'mozilla::extensions::WebExtensionPolicy',
|
|
|
+ },
|
|
|
+
|
|
|
+ 'WindowClient': {
|
|
|
+- 'nativeType': 'mozilla::dom::workers::ServiceWorkerWindowClient',
|
|
|
+- 'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerWindowClient.h',
|
|
|
++ 'nativeType': 'mozilla::dom::Client',
|
|
|
+ },
|
|
|
+
|
|
|
+ 'WebGLActiveInfo': {
|
|
|
+ 'nativeType': 'mozilla::WebGLActiveInfo',
|
|
|
+ 'headerFile': 'WebGLActiveInfo.h'
|
|
|
+ },
|
|
|
+
|
|
|
+ 'WebGLBuffer': {
|
|
|
+diff --git a/dom/clients/api/Client.cpp b/dom/clients/api/Client.cpp
|
|
|
+--- a/dom/clients/api/Client.cpp
|
|
|
++++ b/dom/clients/api/Client.cpp
|
|
|
+@@ -71,24 +71,20 @@ Client::GetStorageAccess() const
|
|
|
+ {
|
|
|
+ ClientState state(ClientState::FromIPC(mData->state()));
|
|
|
+ return state.GetStorageAccess();
|
|
|
+ }
|
|
|
+
|
|
|
+ JSObject*
|
|
|
+ Client::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
|
+ {
|
|
|
+-#if 0
|
|
|
+- // TODO: Enable when bindings are updated to point to this class.
|
|
|
+ if (mData->info().type() == ClientType::Window) {
|
|
|
+ return WindowClientBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+ }
|
|
|
+ return ClientBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+-#endif
|
|
|
+- return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ nsIGlobalObject*
|
|
|
+ Client::GetParentObject() const
|
|
|
+ {
|
|
|
+ return mGlobal;
|
|
|
+ }
|
|
|
+
|
|
|
+diff --git a/dom/clients/api/Clients.cpp b/dom/clients/api/Clients.cpp
|
|
|
+--- a/dom/clients/api/Clients.cpp
|
|
|
++++ b/dom/clients/api/Clients.cpp
|
|
|
+@@ -39,21 +39,17 @@ Clients::Clients(nsIGlobalObject* aGloba
|
|
|
+ : mGlobal(aGlobal)
|
|
|
+ {
|
|
|
+ MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
|
|
+ }
|
|
|
+
|
|
|
+ JSObject*
|
|
|
+ Clients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
|
+ {
|
|
|
+- // TODO: Enable when bindings are updated to point to this class.
|
|
|
+-#if 0
|
|
|
+ return ClientsBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+-#endif
|
|
|
+- return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ nsIGlobalObject*
|
|
|
+ Clients::GetParentObject() const
|
|
|
+ {
|
|
|
+ return mGlobal;
|
|
|
+ }
|
|
|
+
|
|
|
+diff --git a/dom/webidl/Client.webidl b/dom/webidl/Client.webidl
|
|
|
+--- a/dom/webidl/Client.webidl
|
|
|
++++ b/dom/webidl/Client.webidl
|
|
|
+@@ -8,30 +8,32 @@
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+ [Exposed=ServiceWorker]
|
|
|
+ interface Client {
|
|
|
+ readonly attribute USVString url;
|
|
|
+
|
|
|
+ // Remove frameType in bug 1290936
|
|
|
++ [BinaryName="GetFrameType"]
|
|
|
+ readonly attribute FrameType frameType;
|
|
|
+
|
|
|
+ readonly attribute ClientType type;
|
|
|
+ readonly attribute DOMString id;
|
|
|
+
|
|
|
+ // Implement reserved in bug 1264177
|
|
|
+ // readonly attribute boolean reserved;
|
|
|
+
|
|
|
+ [Throws]
|
|
|
+ void postMessage(any message, optional sequence<object> transfer = []);
|
|
|
+ };
|
|
|
+
|
|
|
+ [Exposed=ServiceWorker]
|
|
|
+ interface WindowClient : Client {
|
|
|
++ [BinaryName="GetVisibilityState"]
|
|
|
+ readonly attribute VisibilityState visibilityState;
|
|
|
+ readonly attribute boolean focused;
|
|
|
+
|
|
|
+ // Implement ancestorOrigins in bug 1264180
|
|
|
+ // [SameObject] readonly attribute FrozenArray<USVString> ancestorOrigins;
|
|
|
+
|
|
|
+ [Throws, NewObject]
|
|
|
+ Promise<WindowClient> focus();
|
|
|
+diff --git a/dom/webidl/ServiceWorkerGlobalScope.webidl b/dom/webidl/ServiceWorkerGlobalScope.webidl
|
|
|
+--- a/dom/webidl/ServiceWorkerGlobalScope.webidl
|
|
|
++++ b/dom/webidl/ServiceWorkerGlobalScope.webidl
|
|
|
+@@ -10,17 +10,18 @@
|
|
|
+ *
|
|
|
+ * You are granted a license to use, reproduce and create derivative works of
|
|
|
+ * this document.
|
|
|
+ */
|
|
|
+
|
|
|
+ [Global=(Worker,ServiceWorker),
|
|
|
+ Exposed=ServiceWorker]
|
|
|
+ interface ServiceWorkerGlobalScope : WorkerGlobalScope {
|
|
|
+- [SameObject] readonly attribute Clients clients;
|
|
|
++ [SameObject, BinaryName="GetClients"]
|
|
|
++ readonly attribute Clients clients;
|
|
|
+ [SameObject] readonly attribute ServiceWorkerRegistration registration;
|
|
|
+
|
|
|
+ [Throws, NewObject]
|
|
|
+ Promise<void> skipWaiting();
|
|
|
+
|
|
|
+ attribute EventHandler oninstall;
|
|
|
+ attribute EventHandler onactivate;
|
|
|
+
|
|
|
+diff --git a/dom/workers/ServiceWorker.cpp b/dom/workers/ServiceWorker.cpp
|
|
|
+--- a/dom/workers/ServiceWorker.cpp
|
|
|
++++ b/dom/workers/ServiceWorker.cpp
|
|
|
+@@ -3,22 +3,23 @@
|
|
|
+ /* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+
|
|
|
+ #include "ServiceWorker.h"
|
|
|
+
|
|
|
+ #include "nsIDocument.h"
|
|
|
+ #include "nsPIDOMWindow.h"
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+ #include "ServiceWorkerManager.h"
|
|
|
+ #include "ServiceWorkerPrivate.h"
|
|
|
+ #include "WorkerPrivate.h"
|
|
|
+
|
|
|
+ #include "mozilla/Preferences.h"
|
|
|
++#include "mozilla/dom/ClientIPCTypes.h"
|
|
|
++#include "mozilla/dom/ClientState.h"
|
|
|
+ #include "mozilla/dom/Promise.h"
|
|
|
+ #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
|
|
|
+
|
|
|
+ #ifdef XP_WIN
|
|
|
+ #undef PostMessage
|
|
|
+ #endif
|
|
|
+
|
|
|
+ using mozilla::ErrorResult;
|
|
|
+@@ -97,16 +98,24 @@ ServiceWorker::PostMessage(JSContext* aC
|
|
|
+ if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
|
|
|
+ ServiceWorkerManager::LocalizeAndReportToAllClients(
|
|
|
+ mInfo->Scope(), "ServiceWorkerPostMessageStorageError",
|
|
|
+ nsTArray<nsString> { NS_ConvertUTF8toUTF16(mInfo->Scope()) });
|
|
|
+ aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(window->GetExtantDoc()));
|
|
|
++ Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
|
|
++ Maybe<ClientState> clientState = window->GetClientState();
|
|
|
++ if (clientInfo.isNothing() || clientState.isNothing()) {
|
|
|
++ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
+ ServiceWorkerPrivate* workerPrivate = mInfo->WorkerPrivate();
|
|
|
+- aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, Move(clientInfo));
|
|
|
++ aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
|
|
++ ClientInfoAndState(clientInfo.ref().ToIPC(),
|
|
|
++ clientState.ref().ToIPC()));
|
|
|
+ }
|
|
|
+
|
|
|
+ } // namespace workers
|
|
|
+ } // namespace dom
|
|
|
+ } // namespace mozilla
|
|
|
+diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerClient.cpp
|
|
|
++++ /dev/null
|
|
|
+@@ -1,286 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
+- */
|
|
|
+-
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+-#include "ServiceWorkerContainer.h"
|
|
|
+-
|
|
|
+-#include "mozilla/dom/MessageEvent.h"
|
|
|
+-#include "mozilla/dom/Navigator.h"
|
|
|
+-#include "nsGlobalWindow.h"
|
|
|
+-#include "nsIBrowserDOMWindow.h"
|
|
|
+-#include "nsIDocument.h"
|
|
|
+-#include "ServiceWorker.h"
|
|
|
+-#include "ServiceWorkerPrivate.h"
|
|
|
+-#include "WorkerPrivate.h"
|
|
|
+-
|
|
|
+-using namespace mozilla;
|
|
|
+-using namespace mozilla::dom;
|
|
|
+-using namespace mozilla::dom::workers;
|
|
|
+-
|
|
|
+-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
|
|
|
+-
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClient)
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClient)
|
|
|
+-
|
|
|
+-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
|
|
|
+- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
+-NS_INTERFACE_MAP_END
|
|
|
+-
|
|
|
+-ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc, uint32_t aOrdinal)
|
|
|
+- : mType(ClientType::Window)
|
|
|
+- , mOrdinal(aOrdinal)
|
|
|
+- , mWindowId(0)
|
|
|
+- , mFrameType(FrameType::None)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(aDoc);
|
|
|
+- nsresult rv = aDoc->GetOrCreateId(mClientId);
|
|
|
+- if (NS_FAILED(rv)) {
|
|
|
+- NS_WARNING("Failed to get the UUID of the document.");
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<nsGlobalWindow> innerWindow = nsGlobalWindow::Cast(aDoc->GetInnerWindow());
|
|
|
+- if (innerWindow) {
|
|
|
+- // XXXcatalinb: The inner window can be null if the document is navigating
|
|
|
+- // and was detached.
|
|
|
+- mWindowId = innerWindow->WindowID();
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> originalURI = aDoc->GetOriginalURI();
|
|
|
+- if (originalURI) {
|
|
|
+- nsAutoCString spec;
|
|
|
+- originalURI->GetSpec(spec);
|
|
|
+- CopyUTF8toUTF16(spec, mUrl);
|
|
|
+- }
|
|
|
+- mVisibilityState = aDoc->VisibilityState();
|
|
|
+-
|
|
|
+- mLastFocusTime = aDoc->LastFocusTime();
|
|
|
+-
|
|
|
+- ErrorResult result;
|
|
|
+- mFocused = aDoc->HasFocus(result);
|
|
|
+- if (result.Failed()) {
|
|
|
+- NS_WARNING("Failed to get focus information.");
|
|
|
+- }
|
|
|
+-
|
|
|
+- MOZ_ASSERT_IF(mLastFocusTime.IsNull(), !mFocused);
|
|
|
+- MOZ_ASSERT_IF(mFocused, !mLastFocusTime.IsNull());
|
|
|
+-
|
|
|
+- RefPtr<nsGlobalWindow> outerWindow = nsGlobalWindow::Cast(aDoc->GetWindow());
|
|
|
+- if (!outerWindow) {
|
|
|
+- MOZ_ASSERT(mFrameType == FrameType::None);
|
|
|
+- } else if (!outerWindow->IsTopLevelWindow()) {
|
|
|
+- mFrameType = FrameType::Nested;
|
|
|
+- } else if (outerWindow->HadOriginalOpener()) {
|
|
|
+- mFrameType = FrameType::Auxiliary;
|
|
|
+- } else {
|
|
|
+- mFrameType = FrameType::Top_level;
|
|
|
+- }
|
|
|
+-}
|
|
|
+-
|
|
|
+-bool
|
|
|
+-ServiceWorkerClientInfo::operator<(const ServiceWorkerClientInfo& aRight) const
|
|
|
+-{
|
|
|
+- // Note: the mLastFocusTime comparisons are reversed because we need to
|
|
|
+- // put most recently focused values first. The mOrdinal comparison is
|
|
|
+- // normal, though, because otherwise we want normal creation order.
|
|
|
+-
|
|
|
+- if (mLastFocusTime == aRight.mLastFocusTime) {
|
|
|
+- return mOrdinal < aRight.mOrdinal;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (mLastFocusTime.IsNull()) {
|
|
|
+- return false;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (aRight.mLastFocusTime.IsNull()) {
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+- return mLastFocusTime > aRight.mLastFocusTime;
|
|
|
+-}
|
|
|
+-
|
|
|
+-bool
|
|
|
+-ServiceWorkerClientInfo::operator==(const ServiceWorkerClientInfo& aRight) const
|
|
|
+-{
|
|
|
+- return mLastFocusTime == aRight.mLastFocusTime &&
|
|
|
+- mOrdinal == aRight.mOrdinal &&
|
|
|
+- mClientId == aRight.mClientId;
|
|
|
+-}
|
|
|
+-
|
|
|
+-JSObject*
|
|
|
+-ServiceWorkerClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
|
+-{
|
|
|
+- return ClientBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+-}
|
|
|
+-
|
|
|
+-ClientType
|
|
|
+-ServiceWorkerClient::Type() const
|
|
|
+-{
|
|
|
+- return mType;
|
|
|
+-}
|
|
|
+-
|
|
|
+-namespace {
|
|
|
+-
|
|
|
+-class ServiceWorkerClientPostMessageRunnable final
|
|
|
+- : public Runnable
|
|
|
+- , public StructuredCloneHolder
|
|
|
+-{
|
|
|
+- const uint64_t mSourceID;
|
|
|
+- const nsCString mSourceScope;
|
|
|
+- const uint64_t mWindowId;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- ServiceWorkerClientPostMessageRunnable(uint64_t aSourceID,
|
|
|
+- const nsACString& aSourceScope,
|
|
|
+- uint64_t aWindowId)
|
|
|
+- : mozilla::Runnable("ServiceWorkerClientPostMessageRunnable")
|
|
|
+- , StructuredCloneHolder(CloningSupported,
|
|
|
+- TransferringSupported,
|
|
|
+- StructuredCloneScope::SameProcessDifferentThread)
|
|
|
+- , mSourceID(aSourceID)
|
|
|
+- , mSourceScope(aSourceScope)
|
|
|
+- , mWindowId(aWindowId)
|
|
|
+- {}
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
|
|
|
+- if (!window) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- dom::Navigator* navigator = window->Navigator();
|
|
|
+- if (!navigator) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
|
|
|
+- AutoJSAPI jsapi;
|
|
|
+- if (NS_WARN_IF(!jsapi.Init(window))) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+- JSContext* cx = jsapi.cx();
|
|
|
+-
|
|
|
+- return DispatchDOMEvent(cx, window->AsInner(), container);
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- NS_IMETHOD
|
|
|
+- DispatchDOMEvent(JSContext* aCx, nsPIDOMWindowInner* aWindow,
|
|
|
+- ServiceWorkerContainer* aTargetContainer)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- MOZ_ASSERT(aTargetContainer->GetParentObject(),
|
|
|
+- "How come we don't have a window here?!");
|
|
|
+-
|
|
|
+- JS::Rooted<JS::Value> messageData(aCx);
|
|
|
+- ErrorResult rv;
|
|
|
+- Read(aTargetContainer->GetParentObject(), aCx, &messageData, rv);
|
|
|
+- if (NS_WARN_IF(rv.Failed())) {
|
|
|
+- xpc::Throw(aCx, rv.StealNSResult());
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RootedDictionary<MessageEventInit> init(aCx);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> principal = aTargetContainer->GetParentObject()->PrincipalOrNull();
|
|
|
+- NS_WARNING_ASSERTION(principal, "Why is the principal null here?");
|
|
|
+-
|
|
|
+- bool isNullPrincipal = false;
|
|
|
+- bool isSystemPrincipal = false;
|
|
|
+- if (principal) {
|
|
|
+- isNullPrincipal = principal->GetIsNullPrincipal();
|
|
|
+- MOZ_ASSERT(!isNullPrincipal);
|
|
|
+- isSystemPrincipal = principal->GetIsSystemPrincipal();
|
|
|
+- MOZ_ASSERT(!isSystemPrincipal);
|
|
|
+- }
|
|
|
+-
|
|
|
+- init.mData = messageData;
|
|
|
+- nsAutoCString origin;
|
|
|
+- if (principal && !isNullPrincipal && !isSystemPrincipal) {
|
|
|
+- principal->GetOrigin(origin);
|
|
|
+- }
|
|
|
+- init.mOrigin = NS_ConvertUTF8toUTF16(origin);
|
|
|
+-
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (swm) {
|
|
|
+- RefPtr<ServiceWorkerRegistrationInfo> reg =
|
|
|
+- swm->GetRegistration(principal, mSourceScope);
|
|
|
+- if (reg) {
|
|
|
+- RefPtr<ServiceWorkerInfo> serviceWorker = reg->GetByID(mSourceID);
|
|
|
+- if (serviceWorker) {
|
|
|
+- init.mSource.SetValue().SetAsServiceWorker() =
|
|
|
+- serviceWorker->GetOrCreateInstance(aWindow);
|
|
|
+- }
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (!TakeTransferredPortsAsSequence(init.mPorts)) {
|
|
|
+- return NS_ERROR_OUT_OF_MEMORY;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<MessageEvent> event =
|
|
|
+- MessageEvent::Constructor(aTargetContainer, NS_LITERAL_STRING("message"),
|
|
|
+- init);
|
|
|
+-
|
|
|
+- event->SetTrusted(true);
|
|
|
+- bool status = false;
|
|
|
+- aTargetContainer->DispatchEvent(static_cast<dom::Event*>(event.get()),
|
|
|
+- &status);
|
|
|
+-
|
|
|
+- if (!status) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-} // namespace
|
|
|
+-
|
|
|
+-void
|
|
|
+-ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|
|
+- const Sequence<JSObject*>& aTransferable,
|
|
|
+- ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+- workerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
|
|
+-
|
|
|
+- aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
|
|
+- &transferable);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // At the moment we only expose Client on ServiceWorker globals.
|
|
|
+- MOZ_ASSERT(workerPrivate->IsServiceWorker());
|
|
|
+- uint32_t serviceWorkerID = workerPrivate->ServiceWorkerID();
|
|
|
+- nsCString scope = workerPrivate->ServiceWorkerScope();
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
|
|
|
+- new ServiceWorkerClientPostMessageRunnable(serviceWorkerID, scope,
|
|
|
+- mWindowId);
|
|
|
+-
|
|
|
+- runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy().denySharedArrayBuffer(),
|
|
|
+- aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- aRv = workerPrivate->DispatchToMainThread(runnable.forget());
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-}
|
|
|
+-
|
|
|
+diff --git a/dom/workers/ServiceWorkerClient.h b/dom/workers/ServiceWorkerClient.h
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerClient.h
|
|
|
++++ /dev/null
|
|
|
+@@ -1,128 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
+- */
|
|
|
+-
|
|
|
+-#ifndef mozilla_dom_workers_serviceworkerclient_h
|
|
|
+-#define mozilla_dom_workers_serviceworkerclient_h
|
|
|
+-
|
|
|
+-#include "nsCOMPtr.h"
|
|
|
+-#include "nsWrapperCache.h"
|
|
|
+-#include "mozilla/ErrorResult.h"
|
|
|
+-#include "mozilla/dom/BindingDeclarations.h"
|
|
|
+-#include "mozilla/dom/ClientBinding.h"
|
|
|
+-
|
|
|
+-class nsIDocument;
|
|
|
+-
|
|
|
+-namespace mozilla {
|
|
|
+-namespace dom {
|
|
|
+-namespace workers {
|
|
|
+-
|
|
|
+-class ServiceWorkerClient;
|
|
|
+-class ServiceWorkerWindowClient;
|
|
|
+-
|
|
|
+-// Used as a container object for information needed to create
|
|
|
+-// client objects.
|
|
|
+-class ServiceWorkerClientInfo final
|
|
|
+-{
|
|
|
+- friend class ServiceWorkerClient;
|
|
|
+- friend class ServiceWorkerWindowClient;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- explicit ServiceWorkerClientInfo(nsIDocument* aDoc, uint32_t aOrdinal = 0);
|
|
|
+-
|
|
|
+- const nsString& ClientId() const
|
|
|
+- {
|
|
|
+- return mClientId;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool operator<(const ServiceWorkerClientInfo& aRight) const;
|
|
|
+- bool operator==(const ServiceWorkerClientInfo& aRight) const;
|
|
|
+-
|
|
|
+-private:
|
|
|
+- const mozilla::dom::ClientType mType;
|
|
|
+- const uint32_t mOrdinal;
|
|
|
+- nsString mClientId;
|
|
|
+- uint64_t mWindowId;
|
|
|
+- nsString mUrl;
|
|
|
+-
|
|
|
+- // Window Clients
|
|
|
+- VisibilityState mVisibilityState;
|
|
|
+- FrameType mFrameType;
|
|
|
+- TimeStamp mLastFocusTime;
|
|
|
+- bool mFocused;
|
|
|
+-};
|
|
|
+-
|
|
|
+-class ServiceWorkerClient : public nsISupports,
|
|
|
+- public nsWrapperCache
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
+- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClient)
|
|
|
+-
|
|
|
+- ServiceWorkerClient(nsISupports* aOwner,
|
|
|
+- const ServiceWorkerClientInfo& aClientInfo)
|
|
|
+- : mOwner(aOwner)
|
|
|
+- , mType(aClientInfo.mType)
|
|
|
+- , mId(aClientInfo.mClientId)
|
|
|
+- , mUrl(aClientInfo.mUrl)
|
|
|
+- , mWindowId(aClientInfo.mWindowId)
|
|
|
+- , mFrameType(aClientInfo.mFrameType)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aOwner);
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsISupports*
|
|
|
+- GetParentObject() const
|
|
|
+- {
|
|
|
+- return mOwner;
|
|
|
+- }
|
|
|
+-
|
|
|
+- void GetId(nsString& aRetval) const
|
|
|
+- {
|
|
|
+- aRetval = mId;
|
|
|
+- }
|
|
|
+-
|
|
|
+- void
|
|
|
+- GetUrl(nsAString& aUrl) const
|
|
|
+- {
|
|
|
+- aUrl.Assign(mUrl);
|
|
|
+- }
|
|
|
+-
|
|
|
+- mozilla::dom::FrameType
|
|
|
+- FrameType() const
|
|
|
+- {
|
|
|
+- return mFrameType;
|
|
|
+- }
|
|
|
+-
|
|
|
+- mozilla::dom::ClientType
|
|
|
+- Type() const;
|
|
|
+-
|
|
|
+- void
|
|
|
+- PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|
|
+- const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
|
|
|
+-
|
|
|
+- JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
|
+-
|
|
|
+-protected:
|
|
|
+- virtual ~ServiceWorkerClient()
|
|
|
+- { }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- nsCOMPtr<nsISupports> mOwner;
|
|
|
+- const ClientType mType;
|
|
|
+- nsString mId;
|
|
|
+- nsString mUrl;
|
|
|
+-
|
|
|
+-protected:
|
|
|
+- uint64_t mWindowId;
|
|
|
+- mozilla::dom::FrameType mFrameType;
|
|
|
+-};
|
|
|
+-
|
|
|
+-} // namespace workers
|
|
|
+-} // namespace dom
|
|
|
+-} // namespace mozilla
|
|
|
+-
|
|
|
+-#endif // mozilla_dom_workers_serviceworkerclient_h
|
|
|
+diff --git a/dom/workers/ServiceWorkerClients.cpp b/dom/workers/ServiceWorkerClients.cpp
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerClients.cpp
|
|
|
++++ /dev/null
|
|
|
+@@ -1,941 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+-
|
|
|
+-#include "ServiceWorkerClients.h"
|
|
|
+-
|
|
|
+-#include "mozilla/dom/Promise.h"
|
|
|
+-#include "mozilla/dom/PromiseWorkerProxy.h"
|
|
|
+-#include "mozilla/JSObjectHolder.h"
|
|
|
+-
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+-#include "ServiceWorkerManager.h"
|
|
|
+-#include "ServiceWorkerPrivate.h"
|
|
|
+-#include "ServiceWorkerWindowClient.h"
|
|
|
+-
|
|
|
+-#include "WorkerPrivate.h"
|
|
|
+-#include "WorkerRunnable.h"
|
|
|
+-#include "WorkerScope.h"
|
|
|
+-
|
|
|
+-#include "nsContentUtils.h"
|
|
|
+-#include "nsIBrowserDOMWindow.h"
|
|
|
+-#include "nsIDocShell.h"
|
|
|
+-#include "nsIDOMChromeWindow.h"
|
|
|
+-#include "nsIDOMWindow.h"
|
|
|
+-#include "nsIWebNavigation.h"
|
|
|
+-#include "nsIWebProgress.h"
|
|
|
+-#include "nsIWebProgressListener.h"
|
|
|
+-#include "nsIWindowMediator.h"
|
|
|
+-#include "nsIWindowWatcher.h"
|
|
|
+-#include "nsNetUtil.h"
|
|
|
+-#include "nsPIWindowWatcher.h"
|
|
|
+-#include "nsWindowWatcher.h"
|
|
|
+-#include "nsWeakReference.h"
|
|
|
+-
|
|
|
+-#ifdef MOZ_WIDGET_ANDROID
|
|
|
+-#include "FennecJNIWrappers.h"
|
|
|
+-#endif
|
|
|
+-
|
|
|
+-using namespace mozilla;
|
|
|
+-using namespace mozilla::dom;
|
|
|
+-using namespace mozilla::dom::workers;
|
|
|
+-
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClients)
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClients)
|
|
|
+-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClients, mWorkerScope)
|
|
|
+-
|
|
|
+-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClients)
|
|
|
+- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
+-NS_INTERFACE_MAP_END
|
|
|
+-
|
|
|
+-ServiceWorkerClients::ServiceWorkerClients(ServiceWorkerGlobalScope* aWorkerScope)
|
|
|
+- : mWorkerScope(aWorkerScope)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(mWorkerScope);
|
|
|
+-}
|
|
|
+-
|
|
|
+-JSObject*
|
|
|
+-ServiceWorkerClients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
|
+-{
|
|
|
+- return ClientsBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+-}
|
|
|
+-
|
|
|
+-namespace {
|
|
|
+-
|
|
|
+-class GetRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- class ResolvePromiseWorkerRunnable final : public WorkerRunnable
|
|
|
+- {
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> mValue;
|
|
|
+- nsresult mRv;
|
|
|
+-
|
|
|
+- public:
|
|
|
+- ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+- PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aValue,
|
|
|
+- nsresult aRv)
|
|
|
+- : WorkerRunnable(aWorkerPrivate),
|
|
|
+- mPromiseProxy(aPromiseProxy),
|
|
|
+- mValue(Move(aValue)),
|
|
|
+- mRv(Move(aRv))
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWorkerPrivate);
|
|
|
+- aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- Promise* promise = mPromiseProxy->WorkerPromise();
|
|
|
+- MOZ_ASSERT(promise);
|
|
|
+-
|
|
|
+- if (NS_FAILED(mRv)) {
|
|
|
+- promise->MaybeReject(mRv);
|
|
|
+- } else if (mValue) {
|
|
|
+- RefPtr<ServiceWorkerWindowClient> windowClient =
|
|
|
+- new ServiceWorkerWindowClient(promise->GetParentObject(), *mValue);
|
|
|
+- promise->MaybeResolve(windowClient.get());
|
|
|
+- } else {
|
|
|
+- promise->MaybeResolveWithUndefined();
|
|
|
+- }
|
|
|
+- mPromiseProxy->CleanUp();
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+- };
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- nsString mClientId;
|
|
|
+-public:
|
|
|
+- GetRunnable(PromiseWorkerProxy* aPromiseProxy, const nsAString& aClientId)
|
|
|
+- : mozilla::Runnable("GetRunnable")
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mClientId(aClientId)
|
|
|
+- {
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> result;
|
|
|
+- ErrorResult rv;
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (!swm) {
|
|
|
+- rv = NS_ERROR_FAILURE;
|
|
|
+- } else {
|
|
|
+- result = swm->GetClient(workerPrivate->GetPrincipal(), mClientId, rv);
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ResolvePromiseWorkerRunnable> r =
|
|
|
+- new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
|
|
|
+- mPromiseProxy, Move(result),
|
|
|
+- rv.StealNSResult());
|
|
|
+- rv.SuppressException();
|
|
|
+-
|
|
|
+- r->Dispatch();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-class MatchAllRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- class ResolvePromiseWorkerRunnable final : public WorkerRunnable
|
|
|
+- {
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- nsTArray<ServiceWorkerClientInfo> mValue;
|
|
|
+-
|
|
|
+- public:
|
|
|
+- ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+- PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- nsTArray<ServiceWorkerClientInfo>& aValue)
|
|
|
+- : WorkerRunnable(aWorkerPrivate),
|
|
|
+- mPromiseProxy(aPromiseProxy)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- mValue.SwapElements(aValue);
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWorkerPrivate);
|
|
|
+- aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- Promise* promise = mPromiseProxy->WorkerPromise();
|
|
|
+- MOZ_ASSERT(promise);
|
|
|
+-
|
|
|
+- nsTArray<RefPtr<ServiceWorkerClient>> ret;
|
|
|
+- for (size_t i = 0; i < mValue.Length(); i++) {
|
|
|
+- ret.AppendElement(RefPtr<ServiceWorkerClient>(
|
|
|
+- new ServiceWorkerWindowClient(promise->GetParentObject(),
|
|
|
+- mValue.ElementAt(i))));
|
|
|
+- }
|
|
|
+-
|
|
|
+- promise->MaybeResolve(ret);
|
|
|
+- mPromiseProxy->CleanUp();
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+- };
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- const nsCString mScope;
|
|
|
+- const uint64_t mServiceWorkerID;
|
|
|
+- const bool mIncludeUncontrolled;
|
|
|
+-public:
|
|
|
+- MatchAllRunnable(PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- const nsCString& aScope,
|
|
|
+- uint64_t aServiceWorkerID,
|
|
|
+- bool aIncludeUncontrolled)
|
|
|
+- : mozilla::Runnable("MatchAllRunnable")
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mScope(aScope)
|
|
|
+- , mServiceWorkerID(aServiceWorkerID)
|
|
|
+- , mIncludeUncontrolled(aIncludeUncontrolled)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(mPromiseProxy);
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsTArray<ServiceWorkerClientInfo> result;
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (swm) {
|
|
|
+- swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(),
|
|
|
+- mScope, mServiceWorkerID, mIncludeUncontrolled,
|
|
|
+- result);
|
|
|
+- }
|
|
|
+- RefPtr<ResolvePromiseWorkerRunnable> r =
|
|
|
+- new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
|
|
|
+- mPromiseProxy, result);
|
|
|
+-
|
|
|
+- r->Dispatch();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-class ResolveClaimRunnable final : public WorkerRunnable
|
|
|
+-{
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- nsresult mResult;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- ResolveClaimRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+- PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- nsresult aResult)
|
|
|
+- : WorkerRunnable(aWorkerPrivate)
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mResult(aResult)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWorkerPrivate);
|
|
|
+- aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
|
|
|
+- MOZ_ASSERT(promise);
|
|
|
+-
|
|
|
+- if (NS_SUCCEEDED(mResult)) {
|
|
|
+- promise->MaybeResolveWithUndefined();
|
|
|
+- } else {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- mPromiseProxy->CleanUp();
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-class ClaimRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- nsCString mScope;
|
|
|
+- uint64_t mServiceWorkerID;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- ClaimRunnable(PromiseWorkerProxy* aPromiseProxy, const nsCString& aScope)
|
|
|
+- : mozilla::Runnable("ClaimRunnable")
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mScope(aScope)
|
|
|
+- // Safe to call GetWorkerPrivate() since we are being called on the worker
|
|
|
+- // thread via script (so no clean up has occured yet).
|
|
|
+- , mServiceWorkerID(aPromiseProxy->GetWorkerPrivate()->ServiceWorkerID())
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- nsresult rv = NS_OK;
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (!swm) {
|
|
|
+- // browser shutdown
|
|
|
+- rv = NS_ERROR_FAILURE;
|
|
|
+- } else {
|
|
|
+- rv = swm->ClaimClients(workerPrivate->GetPrincipal(), mScope,
|
|
|
+- mServiceWorkerID);
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ResolveClaimRunnable> r =
|
|
|
+- new ResolveClaimRunnable(workerPrivate, mPromiseProxy, rv);
|
|
|
+-
|
|
|
+- r->Dispatch();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-class ResolveOpenWindowRunnable final : public WorkerRunnable
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- ResolveOpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
|
|
+- const nsresult aStatus)
|
|
|
+- : WorkerRunnable(aPromiseProxy->GetWorkerPrivate())
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mClientInfo(Move(aClientInfo))
|
|
|
+- , mStatus(aStatus)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWorkerPrivate);
|
|
|
+- aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- Promise* promise = mPromiseProxy->WorkerPromise();
|
|
|
+- if (NS_WARN_IF(NS_FAILED(mStatus))) {
|
|
|
+- promise->MaybeReject(mStatus);
|
|
|
+- } else if (mClientInfo) {
|
|
|
+- RefPtr<ServiceWorkerWindowClient> client =
|
|
|
+- new ServiceWorkerWindowClient(promise->GetParentObject(),
|
|
|
+- *mClientInfo);
|
|
|
+- promise->MaybeResolve(client);
|
|
|
+- } else {
|
|
|
+- promise->MaybeResolve(JS::NullHandleValue);
|
|
|
+- }
|
|
|
+-
|
|
|
+- mPromiseProxy->CleanUp();
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> mClientInfo;
|
|
|
+- const nsresult mStatus;
|
|
|
+-};
|
|
|
+-
|
|
|
+-class WebProgressListener final : public nsIWebProgressListener,
|
|
|
+- public nsSupportsWeakReference
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
+- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebProgressListener, nsIWebProgressListener)
|
|
|
+-
|
|
|
+- WebProgressListener(PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- ServiceWorkerPrivate* aServiceWorkerPrivate,
|
|
|
+- nsPIDOMWindowOuter* aWindow,
|
|
|
+- nsIURI* aBaseURI)
|
|
|
+- : mPromiseProxy(aPromiseProxy)
|
|
|
+- , mServiceWorkerPrivate(aServiceWorkerPrivate)
|
|
|
+- , mWindow(aWindow)
|
|
|
+- , mBaseURI(aBaseURI)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- MOZ_ASSERT(aServiceWorkerPrivate);
|
|
|
+- MOZ_ASSERT(aWindow);
|
|
|
+- MOZ_ASSERT(aWindow->IsOuterWindow());
|
|
|
+- MOZ_ASSERT(aBaseURI);
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- mServiceWorkerPrivate->StoreISupports(static_cast<nsIWebProgressListener*>(this));
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnStateChange(nsIWebProgress* aWebProgress,
|
|
|
+- nsIRequest* aRequest,
|
|
|
+- uint32_t aStateFlags, nsresult aStatus) override
|
|
|
+- {
|
|
|
+- if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
|
|
+- !(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Our caller keeps a strong reference, so it is safe to remove the listener
|
|
|
+- // from ServiceWorkerPrivate.
|
|
|
+- mServiceWorkerPrivate->RemoveISupports(static_cast<nsIWebProgressListener*>(this));
|
|
|
+- aWebProgress->RemoveProgressListener(this);
|
|
|
+-
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
|
|
+- if (doc) {
|
|
|
+- // Check same origin.
|
|
|
+- nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
|
|
+- nsContentUtils::GetSecurityManager();
|
|
|
+- nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
|
|
|
+- mBaseURI, false);
|
|
|
+- if (NS_SUCCEEDED(rv)) {
|
|
|
+- clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ResolveOpenWindowRunnable> r =
|
|
|
+- new ResolveOpenWindowRunnable(mPromiseProxy,
|
|
|
+- Move(clientInfo),
|
|
|
+- NS_OK);
|
|
|
+- r->Dispatch();
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnProgressChange(nsIWebProgress* aWebProgress,
|
|
|
+- nsIRequest* aRequest,
|
|
|
+- int32_t aCurSelfProgress,
|
|
|
+- int32_t aMaxSelfProgress,
|
|
|
+- int32_t aCurTotalProgress,
|
|
|
+- int32_t aMaxTotalProgress) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(false, "Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnLocationChange(nsIWebProgress* aWebProgress,
|
|
|
+- nsIRequest* aRequest,
|
|
|
+- nsIURI* aLocation,
|
|
|
+- uint32_t aFlags) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(false, "Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnStatusChange(nsIWebProgress* aWebProgress,
|
|
|
+- nsIRequest* aRequest,
|
|
|
+- nsresult aStatus, const char16_t* aMessage) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(false, "Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnSecurityChange(nsIWebProgress* aWebProgress,
|
|
|
+- nsIRequest* aRequest,
|
|
|
+- uint32_t aState) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(false, "Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~WebProgressListener()
|
|
|
+- { }
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> mWindow;
|
|
|
+- nsCOMPtr<nsIURI> mBaseURI;
|
|
|
+-};
|
|
|
+-
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_ADDREF(WebProgressListener)
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_RELEASE(WebProgressListener)
|
|
|
+-NS_IMPL_CYCLE_COLLECTION(WebProgressListener, mPromiseProxy,
|
|
|
+- mServiceWorkerPrivate, mWindow)
|
|
|
+-
|
|
|
+-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
+-NS_INTERFACE_MAP_END
|
|
|
+-
|
|
|
+-class OpenWindowRunnable final : public Runnable
|
|
|
+- , public nsIObserver
|
|
|
+- , public nsSupportsWeakReference
|
|
|
+-{
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- nsString mUrl;
|
|
|
+- nsString mScope;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- NS_DECL_ISUPPORTS_INHERITED
|
|
|
+- // Note: |OpenWindowRunnable| cannot be cycle collected because it inherits
|
|
|
+- // thread safe reference counting from |mozilla::Runnable|. On Fennec, we
|
|
|
+- // might use |ServiceWorkerPrivate::StoreISupports| to keep this object alive
|
|
|
+- // while waiting for an event from the observer service. As such, to avoid
|
|
|
+- // creating a cycle that will leak, |OpenWindowRunnable| must not hold a strong
|
|
|
+- // reference to |ServiceWorkerPrivate|.
|
|
|
+-
|
|
|
+- OpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- const nsAString& aUrl,
|
|
|
+- const nsAString& aScope)
|
|
|
+- : mozilla::Runnable("OpenWindowRunnable")
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mUrl(aUrl)
|
|
|
+- , mScope(aScope)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
|
|
|
+- aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Observe(nsISupports* aSubject, const char* aTopic, const char16_t* /* aData */) override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsCString topic(aTopic);
|
|
|
+- if (!topic.EqualsLiteral("BrowserChrome:Ready")) {
|
|
|
+- MOZ_ASSERT(false, "Unexpected topic.");
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
|
+- NS_ENSURE_STATE(os);
|
|
|
+- os->RemoveObserver(this, "BrowserChrome:Ready");
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
|
|
+- NS_ENSURE_STATE(swp);
|
|
|
+-
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
|
|
|
+- swp->RemoveISupports(static_cast<nsIObserver*>(this));
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-#ifdef MOZ_WIDGET_ANDROID
|
|
|
+- // This fires an intent that will start launching Fennec and foreground it,
|
|
|
+- // if necessary.
|
|
|
+- if (jni::IsFennec()) {
|
|
|
+- java::GeckoApp::LaunchOrBringToFront();
|
|
|
+- }
|
|
|
+-#endif
|
|
|
+-
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> window;
|
|
|
+- nsresult rv = OpenWindow(getter_AddRefs(window));
|
|
|
+- if (NS_SUCCEEDED(rv)) {
|
|
|
+- MOZ_ASSERT(window);
|
|
|
+-
|
|
|
+- rv = nsContentUtils::DispatchFocusChromeEvent(window);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+-
|
|
|
+- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
|
|
|
+- nsCOMPtr<nsIURI> baseURI;
|
|
|
+- nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
|
|
+- nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
|
|
+-
|
|
|
+- if (!webProgress) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
|
|
+- NS_ENSURE_STATE(swp);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIWebProgressListener> listener =
|
|
|
+- new WebProgressListener(mPromiseProxy, swp, window, baseURI);
|
|
|
+-
|
|
|
+- rv = webProgress->AddProgressListener(listener,
|
|
|
+- nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
|
|
+- MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-#ifdef MOZ_WIDGET_ANDROID
|
|
|
+- else if (rv == NS_ERROR_NOT_AVAILABLE && jni::IsFennec()) {
|
|
|
+- // We couldn't get a browser window, so Fennec must not be running.
|
|
|
+- // Send an Intent to launch Fennec and wait for "BrowserChrome:Ready"
|
|
|
+- // to try opening a window again.
|
|
|
+- RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
|
|
+- NS_ENSURE_STATE(swp);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
|
+- NS_ENSURE_STATE(os);
|
|
|
+-
|
|
|
+- rv = os->AddObserver(this, "BrowserChrome:Ready", /* weakRef */ true);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- swp->StoreISupports(static_cast<nsIObserver*>(this));
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-#endif
|
|
|
+-
|
|
|
+- RefPtr<ResolveOpenWindowRunnable> resolveRunnable =
|
|
|
+- new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv);
|
|
|
+-
|
|
|
+- Unused << NS_WARN_IF(!resolveRunnable->Dispatch());
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~OpenWindowRunnable()
|
|
|
+- { }
|
|
|
+-
|
|
|
+- ServiceWorkerPrivate*
|
|
|
+- GetServiceWorkerPrivate() const
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (!swm) {
|
|
|
+- // browser shutdown
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(principal);
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
|
+- swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
|
|
|
+- if (NS_WARN_IF(!registration)) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
|
|
|
+- registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
|
|
|
+- if (NS_WARN_IF(!serviceWorkerInfo)) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- return serviceWorkerInfo->WorkerPrivate();
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- OpenWindow(nsPIDOMWindowOuter** aWindow)
|
|
|
+- {
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(aWindow);
|
|
|
+- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> triggeringPrincipal = workerPrivate->GetPrincipal();
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(triggeringPrincipal);
|
|
|
+-
|
|
|
+- // [[1. Let url be the result of parsing url with entry settings object's API
|
|
|
+- // base URL.]]
|
|
|
+- nsCOMPtr<nsIURI> uri;
|
|
|
+- WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> baseURI;
|
|
|
+- nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- rv = NS_NewURI(getter_AddRefs(uri), mUrl, nullptr, baseURI);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // [[6.1 Open Window]]
|
|
|
+- nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID,
|
|
|
+- &rv);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (XRE_IsContentProcess()) {
|
|
|
+-
|
|
|
+- // Let's create a sandbox in order to have a valid JSContext and correctly
|
|
|
+- // propagate the SubjectPrincipal.
|
|
|
+- AutoJSAPI jsapi;
|
|
|
+- jsapi.Init();
|
|
|
+-
|
|
|
+- JSContext* cx = jsapi.cx();
|
|
|
+-
|
|
|
+- nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
|
|
+- MOZ_ASSERT(xpc, "This should never be null!");
|
|
|
+-
|
|
|
+- JS::Rooted<JSObject*> sandbox(cx);
|
|
|
+- rv = xpc->CreateSandbox(cx, triggeringPrincipal, sandbox.address());
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+-
|
|
|
+- JSAutoCompartment ac(cx, sandbox);
|
|
|
+-
|
|
|
+- // ContentProcess
|
|
|
+- nsCOMPtr<nsIWindowWatcher> wwatch =
|
|
|
+- do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+- nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
|
|
|
+- NS_ENSURE_STATE(pwwatch);
|
|
|
+-
|
|
|
+- nsCString spec;
|
|
|
+- rv = uri->GetSpec(spec);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<mozIDOMWindowProxy> newWindow;
|
|
|
+- rv = pwwatch->OpenWindow2(nullptr,
|
|
|
+- spec.get(),
|
|
|
+- nullptr,
|
|
|
+- nullptr,
|
|
|
+- false, false, true, nullptr,
|
|
|
+- // Not a spammy popup; we got permission, we swear!
|
|
|
+- /* aIsPopupSpam = */ false,
|
|
|
+- // Don't force noopener. We're not passing in an
|
|
|
+- // opener anyway, and we _do_ want the returned
|
|
|
+- // window.
|
|
|
+- /* aForceNoOpener = */ false,
|
|
|
+- /* aLoadInfp = */ nullptr,
|
|
|
+- getter_AddRefs(newWindow));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
|
|
|
+- pwindow.forget(aWindow);
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Find the most recent browser window and open a new tab in it.
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
|
|
|
+- nsContentUtils::GetMostRecentNonPBWindow();
|
|
|
+- if (!browserWindow) {
|
|
|
+- // It is possible to be running without a browser window on Mac OS, so
|
|
|
+- // we need to open a new chrome window.
|
|
|
+- // TODO(catalinb): open new chrome window. Bug 1218080
|
|
|
+- return NS_ERROR_NOT_AVAILABLE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow);
|
|
|
+- if (NS_WARN_IF(!chromeWin)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIBrowserDOMWindow> bwin;
|
|
|
+- chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(!bwin)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<mozIDOMWindowProxy> win;
|
|
|
+- rv = bwin->OpenURI(uri, nullptr,
|
|
|
+- nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
|
|
|
+- nsIBrowserDOMWindow::OPEN_NEW,
|
|
|
+- triggeringPrincipal,
|
|
|
+- getter_AddRefs(win));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+- NS_ENSURE_STATE(win);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
|
|
|
+- pWin.forget(aWindow);
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-NS_IMPL_ADDREF_INHERITED(OpenWindowRunnable, Runnable) \
|
|
|
+-NS_IMPL_RELEASE_INHERITED(OpenWindowRunnable, Runnable)
|
|
|
+-
|
|
|
+-NS_INTERFACE_MAP_BEGIN(OpenWindowRunnable)
|
|
|
+-NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
+-NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
|
|
+-NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
|
|
+-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
|
|
+-NS_INTERFACE_MAP_END
|
|
|
+-
|
|
|
+-} // namespace
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerClients::Get(const nsAString& aClientId, ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+- workerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+- if (!promiseProxy) {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<GetRunnable> r =
|
|
|
+- new GetRunnable(promiseProxy, aClientId);
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
|
|
|
+- ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+- workerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- nsString scope;
|
|
|
+- mWorkerScope->GetScope(scope);
|
|
|
+-
|
|
|
+- if (aOptions.mType != ClientType::Window) {
|
|
|
+- aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+- if (!promiseProxy) {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<MatchAllRunnable> r =
|
|
|
+- new MatchAllRunnable(promiseProxy,
|
|
|
+- NS_ConvertUTF16toUTF8(scope),
|
|
|
+- workerPrivate->ServiceWorkerID(),
|
|
|
+- aOptions.mIncludeUncontrolled);
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerClients::OpenWindow(const nsAString& aUrl,
|
|
|
+- ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (aUrl.EqualsLiteral("about:blank")) {
|
|
|
+- promise->MaybeReject(NS_ERROR_TYPE_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- // [[4. If this algorithm is not allowed to show a popup ..]]
|
|
|
+- // In Gecko the service worker is allowed to show a popup only if the user
|
|
|
+- // just clicked on a notification.
|
|
|
+- if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+-
|
|
|
+- if (!promiseProxy) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsString scope;
|
|
|
+- mWorkerScope->GetScope(scope);
|
|
|
+-
|
|
|
+- RefPtr<OpenWindowRunnable> r = new OpenWindowRunnable(promiseProxy,
|
|
|
+- aUrl, scope);
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
|
|
+-
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerClients::Claim(ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+- if (!promiseProxy) {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsString scope;
|
|
|
+- mWorkerScope->GetScope(scope);
|
|
|
+-
|
|
|
+- RefPtr<ClaimRunnable> runnable =
|
|
|
+- new ClaimRunnable(promiseProxy, NS_ConvertUTF16toUTF8(scope));
|
|
|
+-
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(runnable.forget()));
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+diff --git a/dom/workers/ServiceWorkerClients.h b/dom/workers/ServiceWorkerClients.h
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerClients.h
|
|
|
++++ /dev/null
|
|
|
+@@ -1,64 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
+- */
|
|
|
+-
|
|
|
+-#ifndef mozilla_dom_workers_serviceworkerclients_h
|
|
|
+-#define mozilla_dom_workers_serviceworkerclients_h
|
|
|
+-
|
|
|
+-#include "nsWrapperCache.h"
|
|
|
+-
|
|
|
+-#include "mozilla/dom/WorkerScope.h"
|
|
|
+-#include "mozilla/dom/BindingDeclarations.h"
|
|
|
+-#include "mozilla/dom/ClientsBinding.h"
|
|
|
+-#include "mozilla/ErrorResult.h"
|
|
|
+-
|
|
|
+-namespace mozilla {
|
|
|
+-namespace dom {
|
|
|
+-namespace workers {
|
|
|
+-
|
|
|
+-class ServiceWorkerClients final : public nsISupports,
|
|
|
+- public nsWrapperCache
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
+- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClients)
|
|
|
+-
|
|
|
+- explicit ServiceWorkerClients(ServiceWorkerGlobalScope* aWorkerScope);
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- Get(const nsAString& aClientId, ErrorResult& aRv);
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- OpenWindow(const nsAString& aUrl, ErrorResult& aRv);
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- Claim(ErrorResult& aRv);
|
|
|
+-
|
|
|
+- JSObject*
|
|
|
+- WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
|
+-
|
|
|
+- ServiceWorkerGlobalScope*
|
|
|
+- GetParentObject() const
|
|
|
+- {
|
|
|
+- return mWorkerScope;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~ServiceWorkerClients()
|
|
|
+- {
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerGlobalScope> mWorkerScope;
|
|
|
+-};
|
|
|
+-
|
|
|
+-} // namespace workers
|
|
|
+-} // namespace dom
|
|
|
+-} // namespace mozilla
|
|
|
+-
|
|
|
+-#endif // mozilla_dom_workers_serviceworkerclients_h
|
|
|
+diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp
|
|
|
+--- a/dom/workers/ServiceWorkerEvents.cpp
|
|
|
++++ b/dom/workers/ServiceWorkerEvents.cpp
|
|
|
+@@ -19,23 +19,23 @@
|
|
|
+ #include "nsContentUtils.h"
|
|
|
+ #include "nsComponentManagerUtils.h"
|
|
|
+ #include "nsServiceManagerUtils.h"
|
|
|
+ #include "nsStreamUtils.h"
|
|
|
+ #include "nsNetCID.h"
|
|
|
+ #include "nsNetUtil.h"
|
|
|
+ #include "nsSerializationHelper.h"
|
|
|
+ #include "nsQueryObject.h"
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+ #include "ServiceWorkerManager.h"
|
|
|
+
|
|
|
+ #include "mozilla/ErrorResult.h"
|
|
|
+ #include "mozilla/LoadInfo.h"
|
|
|
+ #include "mozilla/Preferences.h"
|
|
|
+ #include "mozilla/dom/BodyUtil.h"
|
|
|
++#include "mozilla/dom/Client.h"
|
|
|
+ #include "mozilla/dom/FetchEventBinding.h"
|
|
|
+ #include "mozilla/dom/MessagePort.h"
|
|
|
+ #include "mozilla/dom/PromiseNativeHandler.h"
|
|
|
+ #include "mozilla/dom/PushEventBinding.h"
|
|
|
+ #include "mozilla/dom/PushMessageDataBinding.h"
|
|
|
+ #include "mozilla/dom/PushUtil.h"
|
|
|
+ #include "mozilla/dom/Request.h"
|
|
|
+ #include "mozilla/dom/TypedArray.h"
|
|
|
+diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h
|
|
|
+--- a/dom/workers/ServiceWorkerEvents.h
|
|
|
++++ b/dom/workers/ServiceWorkerEvents.h
|
|
|
+@@ -20,16 +20,17 @@
|
|
|
+ #include "nsProxyRelease.h"
|
|
|
+ #include "nsContentUtils.h"
|
|
|
+
|
|
|
+ class nsIInterceptedChannel;
|
|
|
+
|
|
|
+ namespace mozilla {
|
|
|
+ namespace dom {
|
|
|
+ class Blob;
|
|
|
++class Client;
|
|
|
+ class MessagePort;
|
|
|
+ class Request;
|
|
|
+ class ResponseOrPromise;
|
|
|
+
|
|
|
+ struct PushEventInit;
|
|
|
+ } // namespace dom
|
|
|
+ } // namespace mozilla
|
|
|
+
|
|
|
+@@ -264,17 +265,17 @@ public:
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ class ExtendableMessageEvent final : public ExtendableEvent
|
|
|
+ {
|
|
|
+ JS::Heap<JS::Value> mData;
|
|
|
+ nsString mOrigin;
|
|
|
+ nsString mLastEventId;
|
|
|
+- RefPtr<ServiceWorkerClient> mClient;
|
|
|
++ RefPtr<Client> mClient;
|
|
|
+ RefPtr<ServiceWorker> mServiceWorker;
|
|
|
+ RefPtr<MessagePort> mMessagePort;
|
|
|
+ nsTArray<RefPtr<MessagePort>> mPorts;
|
|
|
+
|
|
|
+ protected:
|
|
|
+ explicit ExtendableMessageEvent(EventTarget* aOwner);
|
|
|
+ ~ExtendableMessageEvent();
|
|
|
+
|
|
|
+diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
|
|
|
+--- a/dom/workers/ServiceWorkerManager.cpp
|
|
|
++++ b/dom/workers/ServiceWorkerManager.cpp
|
|
|
+@@ -63,17 +63,16 @@
|
|
|
+ #include "nsGlobalWindow.h"
|
|
|
+ #include "nsNetUtil.h"
|
|
|
+ #include "nsProxyRelease.h"
|
|
|
+ #include "nsQueryObject.h"
|
|
|
+ #include "nsTArray.h"
|
|
|
+
|
|
|
+ #include "RuntimeService.h"
|
|
|
+ #include "ServiceWorker.h"
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+ #include "ServiceWorkerContainer.h"
|
|
|
+ #include "ServiceWorkerInfo.h"
|
|
|
+ #include "ServiceWorkerJobQueue.h"
|
|
|
+ #include "ServiceWorkerManagerChild.h"
|
|
|
+ #include "ServiceWorkerPrivate.h"
|
|
|
+ #include "ServiceWorkerRegisterJob.h"
|
|
|
+ #include "ServiceWorkerRegistrar.h"
|
|
|
+ #include "ServiceWorkerRegistration.h"
|
|
|
+@@ -3191,178 +3190,16 @@ FireControllerChangeOnDocument(nsIDocume
|
|
|
+ container->ControllerChanged(result);
|
|
|
+ if (result.Failed()) {
|
|
|
+ NS_WARNING("Failed to dispatch controllerchange event");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } // anonymous namespace
|
|
|
+
|
|
|
+-UniquePtr<ServiceWorkerClientInfo>
|
|
|
+-ServiceWorkerManager::GetClient(nsIPrincipal* aPrincipal,
|
|
|
+- const nsAString& aClientId,
|
|
|
+- ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
|
|
+- nsCOMPtr<nsISupportsInterfacePointer> ifptr =
|
|
|
+- do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
|
|
|
+- if (NS_WARN_IF(!ifptr)) {
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
+- if (NS_WARN_IF(!obs)) {
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsresult rv = obs->NotifyObservers(ifptr, "service-worker-get-client",
|
|
|
+- PromiseFlatString(aClientId).get());
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsISupports> ptr;
|
|
|
+- ifptr->GetData(getter_AddRefs(ptr));
|
|
|
+- nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
|
|
+- if (NS_WARN_IF(!doc || !doc->GetInnerWindow())) {
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool equals = false;
|
|
|
+- aPrincipal->Equals(doc->NodePrincipal(), &equals);
|
|
|
+- if (!equals) {
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (!IsFromAuthenticatedOrigin(doc)) {
|
|
|
+- aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Don't let service worker see 3rd party iframes that are denied storage
|
|
|
+- // access. We don't want these to communicate.
|
|
|
+- auto storageAccess =
|
|
|
+- nsContentUtils::StorageAllowedForWindow(doc->GetInnerWindow());
|
|
|
+- if (storageAccess != nsContentUtils::StorageAccess::eAllow) {
|
|
|
+- nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
|
|
+- NS_LITERAL_CSTRING("Service Workers"), doc,
|
|
|
+- nsContentUtils::eDOM_PROPERTIES,
|
|
|
+- "ServiceWorkerGetClientStorageError");
|
|
|
+- return clientInfo;
|
|
|
+- }
|
|
|
+-
|
|
|
+- clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
|
|
+- return clientInfo;
|
|
|
+-}
|
|
|
+-
|
|
|
+-void
|
|
|
+-ServiceWorkerManager::GetAllClients(nsIPrincipal* aPrincipal,
|
|
|
+- const nsCString& aScope,
|
|
|
+- uint64_t aServiceWorkerID,
|
|
|
+- bool aIncludeUncontrolled,
|
|
|
+- nsTArray<ServiceWorkerClientInfo>& aDocuments)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- MOZ_ASSERT(aPrincipal);
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
|
+- GetRegistration(aPrincipal, aScope);
|
|
|
+-
|
|
|
+- if (!registration) {
|
|
|
+- // The registration was removed, leave the array empty.
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
+- if (NS_WARN_IF(!obs)) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsISimpleEnumerator> enumerator;
|
|
|
+- nsresult rv = obs->EnumerateObservers("service-worker-get-client",
|
|
|
+- getter_AddRefs(enumerator));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Get a list of Client documents out of the observer service
|
|
|
+- AutoTArray<nsCOMPtr<nsIDocument>, 32> docList;
|
|
|
+- bool loop = true;
|
|
|
+- while (NS_SUCCEEDED(enumerator->HasMoreElements(&loop)) && loop) {
|
|
|
+- nsCOMPtr<nsISupports> ptr;
|
|
|
+- rv = enumerator->GetNext(getter_AddRefs(ptr));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
|
|
+- if (!doc || !doc->GetWindow() || !doc->GetInnerWindow()) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool equals = false;
|
|
|
+- Unused << aPrincipal->Equals(doc->NodePrincipal(), &equals);
|
|
|
+- if (!equals) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Treat http windows with devtools opened as secure if the correct devtools
|
|
|
+- // setting is enabled.
|
|
|
+- if (!doc->GetWindow()->GetServiceWorkersTestingEnabled() &&
|
|
|
+- !Preferences::GetBool("dom.serviceWorkers.testing.enabled") &&
|
|
|
+- !IsFromAuthenticatedOrigin(doc)) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Don't let service worker find 3rd party iframes that are denied storage
|
|
|
+- // access. We don't want these to communicate.
|
|
|
+- auto storageAccess =
|
|
|
+- nsContentUtils::StorageAllowedForWindow(doc->GetInnerWindow());
|
|
|
+- if (storageAccess != nsContentUtils::StorageAccess::eAllow) {
|
|
|
+- nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
|
|
+- NS_LITERAL_CSTRING("Service Workers"),
|
|
|
+- doc, nsContentUtils::eDOM_PROPERTIES,
|
|
|
+- "ServiceWorkerGetClientStorageError");
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // If we are only returning controlled Clients then skip any documents
|
|
|
+- // that are for different registrations. We also skip service workers
|
|
|
+- // that don't match the ID of our calling service worker. We should
|
|
|
+- // only return Clients controlled by that precise service worker.
|
|
|
+- if (!aIncludeUncontrolled) {
|
|
|
+- ServiceWorkerRegistrationInfo* reg = mControlledDocuments.GetWeak(doc);
|
|
|
+- if (!reg || reg->mScope != aScope || !reg->GetActive() ||
|
|
|
+- reg->GetActive()->ID() != aServiceWorkerID) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (!aIncludeUncontrolled && !mControlledDocuments.Contains(doc)) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- docList.AppendElement(doc.forget());
|
|
|
+- }
|
|
|
+-
|
|
|
+- // The observer service gives us the list in reverse creation order.
|
|
|
+- // We need to maintain creation order, so reverse the list before
|
|
|
+- // processing.
|
|
|
+- docList.Reverse();
|
|
|
+-
|
|
|
+- // Finally convert to the list of ServiceWorkerClientInfo objects.
|
|
|
+- uint32_t ordinal = 0;
|
|
|
+- for (uint32_t i = 0; i < docList.Length(); ++i) {
|
|
|
+- aDocuments.AppendElement(ServiceWorkerClientInfo(docList[i], ordinal));
|
|
|
+- ordinal += 1;
|
|
|
+- }
|
|
|
+-
|
|
|
+- aDocuments.Sort();
|
|
|
+-}
|
|
|
+-
|
|
|
+ void
|
|
|
+ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
|
|
+ ServiceWorkerRegistrationInfo* aWorkerRegistration)
|
|
|
+ {
|
|
|
+ MOZ_ASSERT(aWorkerRegistration);
|
|
|
+ MOZ_ASSERT(aWorkerRegistration->GetActive());
|
|
|
+
|
|
|
+ // Same origin check
|
|
|
+@@ -3386,56 +3223,16 @@ ServiceWorkerManager::MaybeClaimClient(n
|
|
|
+ if (controllingRegistration) {
|
|
|
+ StopControllingADocument(controllingRegistration);
|
|
|
+ }
|
|
|
+
|
|
|
+ StartControllingADocument(aWorkerRegistration, aDocument, NS_LITERAL_STRING(""));
|
|
|
+ FireControllerChangeOnDocument(aDocument);
|
|
|
+ }
|
|
|
+
|
|
|
+-nsresult
|
|
|
+-ServiceWorkerManager::ClaimClients(nsIPrincipal* aPrincipal,
|
|
|
+- const nsCString& aScope, uint64_t aId)
|
|
|
+-{
|
|
|
+- RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
|
+- GetRegistration(aPrincipal, aScope);
|
|
|
+-
|
|
|
+- if (!registration || !registration->GetActive() ||
|
|
|
+- !(registration->GetActive()->ID() == aId)) {
|
|
|
+- // The worker is not active.
|
|
|
+- return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
+- if (NS_WARN_IF(!obs)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsISimpleEnumerator> enumerator;
|
|
|
+- nsresult rv = obs->EnumerateObservers("service-worker-get-client",
|
|
|
+- getter_AddRefs(enumerator));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return rv;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool loop = true;
|
|
|
+- while (NS_SUCCEEDED(enumerator->HasMoreElements(&loop)) && loop) {
|
|
|
+- nsCOMPtr<nsISupports> ptr;
|
|
|
+- rv = enumerator->GetNext(getter_AddRefs(ptr));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
|
|
+- MaybeClaimClient(doc, registration);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+-}
|
|
|
+-
|
|
|
+ void
|
|
|
+ ServiceWorkerManager::SetSkipWaitingFlag(nsIPrincipal* aPrincipal,
|
|
|
+ const nsCString& aScope,
|
|
|
+ uint64_t aServiceWorkerID)
|
|
|
+ {
|
|
|
+ RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
|
+ GetRegistration(aPrincipal, aScope);
|
|
|
+ if (NS_WARN_IF(!registration)) {
|
|
|
+diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h
|
|
|
+--- a/dom/workers/ServiceWorkerManager.h
|
|
|
++++ b/dom/workers/ServiceWorkerManager.h
|
|
|
+@@ -41,17 +41,16 @@ class OriginAttributes;
|
|
|
+
|
|
|
+ namespace dom {
|
|
|
+
|
|
|
+ class ServiceWorkerRegistrar;
|
|
|
+ class ServiceWorkerRegistrationListener;
|
|
|
+
|
|
|
+ namespace workers {
|
|
|
+
|
|
|
+-class ServiceWorkerClientInfo;
|
|
|
+ class ServiceWorkerInfo;
|
|
|
+ class ServiceWorkerJobQueue;
|
|
|
+ class ServiceWorkerManagerChild;
|
|
|
+ class ServiceWorkerPrivate;
|
|
|
+
|
|
|
+ class ServiceWorkerUpdateFinishCallback
|
|
|
+ {
|
|
|
+ protected:
|
|
|
+@@ -268,35 +267,20 @@ public:
|
|
|
+ const nsString& aMessage,
|
|
|
+ const nsString& aFilename,
|
|
|
+ const nsString& aLine,
|
|
|
+ uint32_t aLineNumber,
|
|
|
+ uint32_t aColumnNumber,
|
|
|
+ uint32_t aFlags,
|
|
|
+ JSExnType aExnType);
|
|
|
+
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>
|
|
|
+- GetClient(nsIPrincipal* aPrincipal,
|
|
|
+- const nsAString& aClientId,
|
|
|
+- ErrorResult& aRv);
|
|
|
+-
|
|
|
+- void
|
|
|
+- GetAllClients(nsIPrincipal* aPrincipal,
|
|
|
+- const nsCString& aScope,
|
|
|
+- uint64_t aServiceWorkerID,
|
|
|
+- bool aIncludeUncontrolled,
|
|
|
+- nsTArray<ServiceWorkerClientInfo>& aDocuments);
|
|
|
+-
|
|
|
+ void
|
|
|
+ MaybeClaimClient(nsIDocument* aDocument,
|
|
|
+ ServiceWorkerRegistrationInfo* aWorkerRegistration);
|
|
|
+
|
|
|
+- nsresult
|
|
|
+- ClaimClients(nsIPrincipal* aPrincipal, const nsCString& aScope, uint64_t aId);
|
|
|
+-
|
|
|
+ void
|
|
|
+ SetSkipWaitingFlag(nsIPrincipal* aPrincipal, const nsCString& aScope,
|
|
|
+ uint64_t aServiceWorkerID);
|
|
|
+
|
|
|
+ static already_AddRefed<ServiceWorkerManager>
|
|
|
+ GetInstance();
|
|
|
+
|
|
|
+ void
|
|
|
+diff --git a/dom/workers/ServiceWorkerManagerService.h b/dom/workers/ServiceWorkerManagerService.h
|
|
|
+--- a/dom/workers/ServiceWorkerManagerService.h
|
|
|
++++ b/dom/workers/ServiceWorkerManagerService.h
|
|
|
+@@ -4,16 +4,17 @@
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+
|
|
|
+ #ifndef mozilla_dom_ServiceWorkerManagerService_h
|
|
|
+ #define mozilla_dom_ServiceWorkerManagerService_h
|
|
|
+
|
|
|
+ #include "nsISupportsImpl.h"
|
|
|
+ #include "nsHashKeys.h"
|
|
|
++#include "nsTArray.h"
|
|
|
+ #include "nsTHashtable.h"
|
|
|
+
|
|
|
+ namespace mozilla {
|
|
|
+
|
|
|
+ class OriginAttributes;
|
|
|
+
|
|
|
+ namespace ipc {
|
|
|
+ class PrincipalInfo;
|
|
|
+diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
|
|
|
+--- a/dom/workers/ServiceWorkerPrivate.cpp
|
|
|
++++ b/dom/workers/ServiceWorkerPrivate.cpp
|
|
|
+@@ -2,17 +2,16 @@
|
|
|
+ /* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+ /* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+
|
|
|
+ #include "ServiceWorkerPrivate.h"
|
|
|
+
|
|
|
+ #include "ServiceWorkerManager.h"
|
|
|
+-#include "ServiceWorkerWindowClient.h"
|
|
|
+ #include "nsContentUtils.h"
|
|
|
+ #include "nsIHttpChannelInternal.h"
|
|
|
+ #include "nsIHttpHeaderVisitor.h"
|
|
|
+ #include "nsINamed.h"
|
|
|
+ #include "nsINetworkInterceptController.h"
|
|
|
+ #include "nsIPushErrorReporter.h"
|
|
|
+ #include "nsISupportsImpl.h"
|
|
|
+ #include "nsITimedChannel.h"
|
|
|
+@@ -20,30 +19,34 @@
|
|
|
+ #include "nsNetUtil.h"
|
|
|
+ #include "nsProxyRelease.h"
|
|
|
+ #include "nsQueryObject.h"
|
|
|
+ #include "nsStreamUtils.h"
|
|
|
+ #include "nsStringStream.h"
|
|
|
+ #include "WorkerRunnable.h"
|
|
|
+ #include "WorkerScope.h"
|
|
|
+ #include "mozilla/Assertions.h"
|
|
|
++#include "mozilla/dom/Client.h"
|
|
|
++#include "mozilla/dom/ClientIPCTypes.h"
|
|
|
+ #include "mozilla/dom/FetchUtil.h"
|
|
|
+ #include "mozilla/dom/IndexedDatabaseManager.h"
|
|
|
+ #include "mozilla/dom/InternalHeaders.h"
|
|
|
+ #include "mozilla/dom/NotificationEvent.h"
|
|
|
+ #include "mozilla/dom/PromiseNativeHandler.h"
|
|
|
+ #include "mozilla/dom/PushEventBinding.h"
|
|
|
+ #include "mozilla/dom/RequestBinding.h"
|
|
|
+ #include "mozilla/Unused.h"
|
|
|
+
|
|
|
+ using namespace mozilla;
|
|
|
+ using namespace mozilla::dom;
|
|
|
+
|
|
|
+ BEGIN_WORKERS_NAMESPACE
|
|
|
+
|
|
|
++using mozilla::ipc::PrincipalInfo;
|
|
|
++
|
|
|
+ NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(ServiceWorkerPrivate)
|
|
|
+ NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(ServiceWorkerPrivate)
|
|
|
+ NS_IMPL_CYCLE_COLLECTION(ServiceWorkerPrivate, mSupportsArray)
|
|
|
+
|
|
|
+ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(ServiceWorkerPrivate, AddRef)
|
|
|
+ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ServiceWorkerPrivate, Release)
|
|
|
+
|
|
|
+ // Tracks the "dom.serviceWorkers.disable_open_click_delay" preference. Modified
|
|
|
+@@ -478,32 +481,31 @@ public:
|
|
|
+ result.SuppressException();
|
|
|
+ return NS_ERROR_XPC_JS_THREW_EXCEPTION;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NS_OK;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+-class SendMesssageEventRunnable final : public ExtendableEventWorkerRunnable
|
|
|
+- , public StructuredCloneHolder
|
|
|
++class SendMessageEventRunnable final : public ExtendableEventWorkerRunnable
|
|
|
++ , public StructuredCloneHolder
|
|
|
+ {
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> mEventSource;
|
|
|
++ const ClientInfoAndState mClientInfoAndState;
|
|
|
+
|
|
|
+ public:
|
|
|
+- SendMesssageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+- KeepAliveToken* aKeepAliveToken,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aEventSource)
|
|
|
++ SendMessageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
++ KeepAliveToken* aKeepAliveToken,
|
|
|
++ const ClientInfoAndState& aClientInfoAndState)
|
|
|
+ : ExtendableEventWorkerRunnable(aWorkerPrivate, aKeepAliveToken)
|
|
|
+ , StructuredCloneHolder(CloningSupported, TransferringSupported,
|
|
|
+ StructuredCloneScope::SameProcessDifferentThread)
|
|
|
+- , mEventSource(Move(aEventSource))
|
|
|
++ , mClientInfoAndState(aClientInfoAndState)
|
|
|
+ {
|
|
|
+ AssertIsOnMainThread();
|
|
|
+- MOZ_ASSERT(mEventSource);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool
|
|
|
+ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
|
|
+ {
|
|
|
+ JS::Rooted<JS::Value> messageData(aCx);
|
|
|
+ nsCOMPtr<nsIGlobalObject> sgo = aWorkerPrivate->GlobalScope();
|
|
|
+ ErrorResult rv;
|
|
|
+@@ -512,26 +514,25 @@ public:
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ Sequence<OwningNonNull<MessagePort>> ports;
|
|
|
+ if (!TakeTransferredPortsAsSequence(ports)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+- RefPtr<ServiceWorkerClient> client = new ServiceWorkerWindowClient(sgo,
|
|
|
+- *mEventSource);
|
|
|
+ RootedDictionary<ExtendableMessageEventInit> init(aCx);
|
|
|
+
|
|
|
+ init.mBubbles = false;
|
|
|
+ init.mCancelable = false;
|
|
|
+
|
|
|
+ init.mData = messageData;
|
|
|
+ init.mPorts = ports;
|
|
|
+- init.mSource.SetValue().SetAsClient() = client;
|
|
|
++ init.mSource.SetValue().SetAsClient() =
|
|
|
++ new Client(sgo, mClientInfoAndState);
|
|
|
+
|
|
|
+ RefPtr<EventTarget> target = aWorkerPrivate->GlobalScope();
|
|
|
+ RefPtr<ExtendableMessageEvent> extendableEvent =
|
|
|
+ ExtendableMessageEvent::Constructor(target, NS_LITERAL_STRING("message"),
|
|
|
+ init, rv);
|
|
|
+ if (NS_WARN_IF(rv.Failed())) {
|
|
|
+ rv.SuppressException();
|
|
|
+ return false;
|
|
|
+@@ -547,17 +548,17 @@ public:
|
|
|
+ };
|
|
|
+
|
|
|
+ } // anonymous namespace
|
|
|
+
|
|
|
+ nsresult
|
|
|
+ ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
|
|
|
+ JS::Handle<JS::Value> aMessage,
|
|
|
+ const Sequence<JSObject*>& aTransferable,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
|
|
++ const ClientInfoAndState& aClientInfoAndState)
|
|
|
+ {
|
|
|
+ AssertIsOnMainThread();
|
|
|
+
|
|
|
+ ErrorResult rv(SpawnWorkerIfNeeded(MessageEvent, nullptr));
|
|
|
+ if (NS_WARN_IF(rv.Failed())) {
|
|
|
+ return rv.StealNSResult();
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -565,18 +566,18 @@ ServiceWorkerPrivate::SendMessageEvent(J
|
|
|
+
|
|
|
+ rv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
|
|
+ &transferable);
|
|
|
+ if (NS_WARN_IF(rv.Failed())) {
|
|
|
+ return rv.StealNSResult();
|
|
|
+ }
|
|
|
+
|
|
|
+ RefPtr<KeepAliveToken> token = CreateEventKeepAliveToken();
|
|
|
+- RefPtr<SendMesssageEventRunnable> runnable =
|
|
|
+- new SendMesssageEventRunnable(mWorkerPrivate, token, Move(aClientInfo));
|
|
|
++ RefPtr<SendMessageEventRunnable> runnable =
|
|
|
++ new SendMessageEventRunnable(mWorkerPrivate, token, aClientInfoAndState);
|
|
|
+
|
|
|
+ runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), rv);
|
|
|
+ if (NS_WARN_IF(rv.Failed())) {
|
|
|
+ return rv.StealNSResult();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!runnable->Dispatch()) {
|
|
|
+ return NS_ERROR_FAILURE;
|
|
|
+diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h
|
|
|
+--- a/dom/workers/ServiceWorkerPrivate.h
|
|
|
++++ b/dom/workers/ServiceWorkerPrivate.h
|
|
|
+@@ -13,16 +13,19 @@
|
|
|
+
|
|
|
+ #define NOTIFICATION_CLICK_EVENT_NAME "notificationclick"
|
|
|
+ #define NOTIFICATION_CLOSE_EVENT_NAME "notificationclose"
|
|
|
+
|
|
|
+ class nsIInterceptedChannel;
|
|
|
+
|
|
|
+ namespace mozilla {
|
|
|
+ namespace dom {
|
|
|
++
|
|
|
++class ClientInfoAndState;
|
|
|
++
|
|
|
+ namespace workers {
|
|
|
+
|
|
|
+ class ServiceWorkerInfo;
|
|
|
+ class ServiceWorkerRegistrationInfo;
|
|
|
+ class KeepAliveToken;
|
|
|
+
|
|
|
+ class LifeCycleEventCallback : public Runnable
|
|
|
+ {
|
|
|
+@@ -80,17 +83,17 @@ protected:
|
|
|
+ NS_DECL_OWNINGTHREAD
|
|
|
+
|
|
|
+ public:
|
|
|
+ explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo);
|
|
|
+
|
|
|
+ nsresult
|
|
|
+ SendMessageEvent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|
|
+ const Sequence<JSObject*>& aTransferable,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aClientInfo);
|
|
|
++ const ClientInfoAndState& aClientInfoAndState);
|
|
|
+
|
|
|
+ // This is used to validate the worker script and continue the installation
|
|
|
+ // process.
|
|
|
+ nsresult
|
|
|
+ CheckScriptEvaluation(LifeCycleEventCallback* aCallback);
|
|
|
+
|
|
|
+ nsresult
|
|
|
+ SendLifeCycleEvent(const nsAString& aEventType,
|
|
|
+diff --git a/dom/workers/ServiceWorkerWindowClient.cpp b/dom/workers/ServiceWorkerWindowClient.cpp
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerWindowClient.cpp
|
|
|
++++ /dev/null
|
|
|
+@@ -1,555 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
+- */
|
|
|
+-
|
|
|
+-#include "ServiceWorkerWindowClient.h"
|
|
|
+-
|
|
|
+-#include "js/Value.h"
|
|
|
+-#include "mozilla/Mutex.h"
|
|
|
+-#include "mozilla/dom/ClientBinding.h"
|
|
|
+-#include "mozilla/dom/Promise.h"
|
|
|
+-#include "mozilla/dom/PromiseWorkerProxy.h"
|
|
|
+-#include "mozilla/UniquePtr.h"
|
|
|
+-#include "nsContentUtils.h"
|
|
|
+-#include "nsGlobalWindow.h"
|
|
|
+-#include "nsIDocShell.h"
|
|
|
+-#include "nsIDocShellLoadInfo.h"
|
|
|
+-#include "nsIDocument.h"
|
|
|
+-#include "nsIGlobalObject.h"
|
|
|
+-#include "nsIPrincipal.h"
|
|
|
+-#include "nsIScriptSecurityManager.h"
|
|
|
+-#include "nsIWebNavigation.h"
|
|
|
+-#include "nsIWebProgress.h"
|
|
|
+-#include "nsIWebProgressListener.h"
|
|
|
+-#include "nsString.h"
|
|
|
+-#include "nsWeakReference.h"
|
|
|
+-#include "ServiceWorker.h"
|
|
|
+-#include "ServiceWorkerInfo.h"
|
|
|
+-#include "ServiceWorkerManager.h"
|
|
|
+-#include "WorkerPrivate.h"
|
|
|
+-#include "WorkerScope.h"
|
|
|
+-
|
|
|
+-using namespace mozilla;
|
|
|
+-using namespace mozilla::dom;
|
|
|
+-using namespace mozilla::dom::workers;
|
|
|
+-
|
|
|
+-using mozilla::UniquePtr;
|
|
|
+-
|
|
|
+-JSObject*
|
|
|
+-ServiceWorkerWindowClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
|
+-{
|
|
|
+- return WindowClientBinding::Wrap(aCx, this, aGivenProto);
|
|
|
+-}
|
|
|
+-
|
|
|
+-namespace {
|
|
|
+-
|
|
|
+-class ResolveOrRejectPromiseRunnable final : public WorkerRunnable
|
|
|
+-{
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> mClientInfo;
|
|
|
+- nsresult mRv;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- // Passing a null clientInfo will resolve the promise with a null value.
|
|
|
+- ResolveOrRejectPromiseRunnable(
|
|
|
+- WorkerPrivate* aWorkerPrivate, PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
|
|
+- : WorkerRunnable(aWorkerPrivate)
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mClientInfo(Move(aClientInfo))
|
|
|
+- , mRv(NS_OK)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Reject the promise with passed nsresult.
|
|
|
+- ResolveOrRejectPromiseRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+- PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- nsresult aRv)
|
|
|
+- : WorkerRunnable(aWorkerPrivate)
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mClientInfo(nullptr)
|
|
|
+- , mRv(aRv)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(NS_FAILED(aRv));
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWorkerPrivate);
|
|
|
+- aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
|
|
|
+- MOZ_ASSERT(promise);
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(NS_FAILED(mRv))) {
|
|
|
+- promise->MaybeReject(mRv);
|
|
|
+- } else if (mClientInfo) {
|
|
|
+- RefPtr<ServiceWorkerWindowClient> client =
|
|
|
+- new ServiceWorkerWindowClient(promise->GetParentObject(), *mClientInfo);
|
|
|
+- promise->MaybeResolve(client);
|
|
|
+- } else {
|
|
|
+- promise->MaybeResolve(JS::NullHandleValue);
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Release the reference on the worker thread.
|
|
|
+- mPromiseProxy->CleanUp();
|
|
|
+-
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-class ClientFocusRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- uint64_t mWindowId;
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- ClientFocusRunnable(uint64_t aWindowId, PromiseWorkerProxy* aPromiseProxy)
|
|
|
+- : mozilla::Runnable("ClientFocusRunnable")
|
|
|
+- , mWindowId(aWindowId)
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(mPromiseProxy);
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
|
|
+-
|
|
|
+- if (window) {
|
|
|
+- nsCOMPtr<nsIDocument> doc = window->GetDocument();
|
|
|
+- if (doc) {
|
|
|
+- nsContentUtils::DispatchFocusChromeEvent(window->GetOuterWindow());
|
|
|
+- clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- DispatchResult(Move(clientInfo));
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- void
|
|
|
+- DispatchResult(UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable;
|
|
|
+- if (aClientInfo) {
|
|
|
+- resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
|
|
+- mPromiseProxy->GetWorkerPrivate(), mPromiseProxy, Move(aClientInfo));
|
|
|
+- } else {
|
|
|
+- resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
|
|
+- mPromiseProxy->GetWorkerPrivate(), mPromiseProxy,
|
|
|
+- NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- resolveRunnable->Dispatch();
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-} // namespace
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+- workerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
|
|
+- MOZ_ASSERT(global);
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+- if (promiseProxy) {
|
|
|
+- RefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId,
|
|
|
+- promiseProxy);
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
|
|
+- } else {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- } else {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+-
|
|
|
+-class WebProgressListener final : public nsIWebProgressListener,
|
|
|
+- public nsSupportsWeakReference
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
+- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebProgressListener,
|
|
|
+- nsIWebProgressListener)
|
|
|
+-
|
|
|
+- WebProgressListener(PromiseWorkerProxy* aPromiseProxy,
|
|
|
+- ServiceWorkerPrivate* aServiceWorkerPrivate,
|
|
|
+- nsPIDOMWindowOuter* aWindow, nsIURI* aBaseURI)
|
|
|
+- : mPromiseProxy(aPromiseProxy)
|
|
|
+- , mServiceWorkerPrivate(aServiceWorkerPrivate)
|
|
|
+- , mWindow(aWindow)
|
|
|
+- , mBaseURI(aBaseURI)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- MOZ_ASSERT(aServiceWorkerPrivate);
|
|
|
+- MOZ_ASSERT(aWindow);
|
|
|
+- MOZ_ASSERT(aWindow->IsOuterWindow());
|
|
|
+- MOZ_ASSERT(aBaseURI);
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- mServiceWorkerPrivate->StoreISupports(static_cast<nsIWebProgressListener*>(this));
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
|
|
+- uint32_t aStateFlags, nsresult aStatus) override
|
|
|
+- {
|
|
|
+- if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
|
|
+- !(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // This is safe because our caller holds a strong ref.
|
|
|
+- mServiceWorkerPrivate->RemoveISupports(static_cast<nsIWebProgressListener*>(this));
|
|
|
+- aWebProgress->RemoveProgressListener(this);
|
|
|
+-
|
|
|
+- WorkerPrivate* workerPrivate;
|
|
|
+-
|
|
|
+- {
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
|
|
+-
|
|
|
+- RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable;
|
|
|
+- UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
|
|
+- if (!doc) {
|
|
|
+- resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
|
|
+- workerPrivate, mPromiseProxy, NS_ERROR_TYPE_ERR);
|
|
|
+- resolveRunnable->Dispatch();
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Check same origin.
|
|
|
+- nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
|
|
+- nsContentUtils::GetSecurityManager();
|
|
|
+- nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
|
|
|
+- mBaseURI, false);
|
|
|
+-
|
|
|
+- if (NS_SUCCEEDED(rv)) {
|
|
|
+- nsContentUtils::DispatchFocusChromeEvent(mWindow->GetOuterWindow());
|
|
|
+- clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
|
|
+- }
|
|
|
+-
|
|
|
+- resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
|
|
+- workerPrivate, mPromiseProxy, Move(clientInfo));
|
|
|
+- resolveRunnable->Dispatch();
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnProgressChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
|
|
+- int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
|
|
|
+- int32_t aCurTotalProgress,
|
|
|
+- int32_t aMaxTotalProgress) override
|
|
|
+- {
|
|
|
+- MOZ_CRASH("Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
|
|
+- nsIURI* aLocation, uint32_t aFlags) override
|
|
|
+- {
|
|
|
+- MOZ_CRASH("Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
|
|
+- nsresult aStatus, const char16_t* aMessage) override
|
|
|
+- {
|
|
|
+- MOZ_CRASH("Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
|
|
+- uint32_t aState) override
|
|
|
+- {
|
|
|
+- MOZ_CRASH("Unexpected notification.");
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~WebProgressListener() {}
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
|
|
|
+- nsCOMPtr<nsPIDOMWindowOuter> mWindow;
|
|
|
+- nsCOMPtr<nsIURI> mBaseURI;
|
|
|
+-};
|
|
|
+-
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_ADDREF(WebProgressListener)
|
|
|
+-NS_IMPL_CYCLE_COLLECTING_RELEASE(WebProgressListener)
|
|
|
+-NS_IMPL_CYCLE_COLLECTION(WebProgressListener, mPromiseProxy,
|
|
|
+- mServiceWorkerPrivate, mWindow)
|
|
|
+-
|
|
|
+-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
|
|
+- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
+-NS_INTERFACE_MAP_END
|
|
|
+-
|
|
|
+-class ClientNavigateRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- uint64_t mWindowId;
|
|
|
+- nsString mUrl;
|
|
|
+- nsCString mBaseUrl;
|
|
|
+- nsString mScope;
|
|
|
+- RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
|
|
+- MOZ_INIT_OUTSIDE_CTOR WorkerPrivate* mWorkerPrivate;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- ClientNavigateRunnable(uint64_t aWindowId,
|
|
|
+- const nsAString& aUrl,
|
|
|
+- const nsAString& aScope,
|
|
|
+- PromiseWorkerProxy* aPromiseProxy)
|
|
|
+- : mozilla::Runnable("ClientNavigateRunnable")
|
|
|
+- , mWindowId(aWindowId)
|
|
|
+- , mUrl(aUrl)
|
|
|
+- , mScope(aScope)
|
|
|
+- , mPromiseProxy(aPromiseProxy)
|
|
|
+- , mWorkerPrivate(nullptr)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aPromiseProxy);
|
|
|
+- MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
|
|
|
+- aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> principal;
|
|
|
+-
|
|
|
+- {
|
|
|
+- MutexAutoLock lock(mPromiseProxy->Lock());
|
|
|
+- if (mPromiseProxy->CleanedUp()) {
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- mWorkerPrivate = mPromiseProxy->GetWorkerPrivate();
|
|
|
+- WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
|
|
|
+- mBaseUrl = info.mHref;
|
|
|
+- principal = mWorkerPrivate->GetPrincipal();
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(principal);
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> baseUrl;
|
|
|
+- nsCOMPtr<nsIURI> url;
|
|
|
+- nsresult rv = ParseUrl(getter_AddRefs(baseUrl), getter_AddRefs(url));
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return RejectPromise(NS_ERROR_TYPE_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsGlobalWindow* window;
|
|
|
+- rv = Navigate(url, principal, &window);
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return RejectPromise(rv);
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
|
|
+- nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
|
|
+- if (NS_WARN_IF(!webProgress)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
|
+- if (!swm) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
|
+- swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
|
|
|
+- if (NS_WARN_IF(!registration)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+- RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
|
|
|
+- registration->GetServiceWorkerInfoById(mWorkerPrivate->ServiceWorkerID());
|
|
|
+- if (NS_WARN_IF(!serviceWorkerInfo)) {
|
|
|
+- return NS_ERROR_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIWebProgressListener> listener =
|
|
|
+- new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(),
|
|
|
+- window->GetOuterWindow(), baseUrl);
|
|
|
+-
|
|
|
+- rv = webProgress->AddProgressListener(
|
|
|
+- listener, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return RejectPromise(rv);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- nsresult
|
|
|
+- RejectPromise(nsresult aRv)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(mWorkerPrivate);
|
|
|
+- RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
|
|
|
+- new ResolveOrRejectPromiseRunnable(mWorkerPrivate, mPromiseProxy, aRv);
|
|
|
+-
|
|
|
+- resolveRunnable->Dispatch();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- ResolvePromise(UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(mWorkerPrivate);
|
|
|
+- RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
|
|
|
+- new ResolveOrRejectPromiseRunnable(mWorkerPrivate, mPromiseProxy,
|
|
|
+- Move(aClientInfo));
|
|
|
+-
|
|
|
+- resolveRunnable->Dispatch();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- ParseUrl(nsIURI** aBaseUrl, nsIURI** aUrl)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aBaseUrl);
|
|
|
+- MOZ_ASSERT(aUrl);
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> baseUrl;
|
|
|
+- nsresult rv = NS_NewURI(getter_AddRefs(baseUrl), mBaseUrl);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> url;
|
|
|
+- rv = NS_NewURI(getter_AddRefs(url), mUrl, nullptr, baseUrl);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- baseUrl.forget(aBaseUrl);
|
|
|
+- url.forget(aUrl);
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- Navigate(nsIURI* aUrl, nsIPrincipal* aPrincipal, nsGlobalWindow** aWindow)
|
|
|
+- {
|
|
|
+- MOZ_ASSERT(aWindow);
|
|
|
+-
|
|
|
+- nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
|
|
|
+- if (NS_WARN_IF(!window)) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocument> doc = window->GetDocument();
|
|
|
+- if (NS_WARN_IF(!doc)) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(!doc->IsActive())) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
|
|
+- if (NS_WARN_IF(!docShell)) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
|
|
|
+- nsresult rv = docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- loadInfo->SetTriggeringPrincipal(aPrincipal);
|
|
|
+- loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
|
|
|
+- loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
|
|
|
+- loadInfo->SetSourceDocShell(docShell);
|
|
|
+- rv =
|
|
|
+- docShell->LoadURI(aUrl, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
|
|
|
+-
|
|
|
+- if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
+- return NS_ERROR_TYPE_ERR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- *aWindow = window;
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-};
|
|
|
+-
|
|
|
+-already_AddRefed<Promise>
|
|
|
+-ServiceWorkerWindowClient::Navigate(const nsAString& aUrl, ErrorResult& aRv)
|
|
|
+-{
|
|
|
+- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
+- MOZ_ASSERT(workerPrivate);
|
|
|
+- workerPrivate->AssertIsOnWorkerThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
|
|
+- MOZ_ASSERT(global);
|
|
|
+-
|
|
|
+- RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
|
+- if (NS_WARN_IF(aRv.Failed())) {
|
|
|
+- return nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (aUrl.EqualsLiteral("about:blank")) {
|
|
|
+- promise->MaybeReject(NS_ERROR_TYPE_ERR);
|
|
|
+- return promise.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- ServiceWorkerGlobalScope* globalScope =
|
|
|
+- static_cast<ServiceWorkerGlobalScope*>(workerPrivate->GlobalScope());
|
|
|
+- nsString scope;
|
|
|
+- globalScope->GetScope(scope);
|
|
|
+-
|
|
|
+- RefPtr<PromiseWorkerProxy> promiseProxy =
|
|
|
+- PromiseWorkerProxy::Create(workerPrivate, promise);
|
|
|
+- if (promiseProxy) {
|
|
|
+- RefPtr<ClientNavigateRunnable> r =
|
|
|
+- new ClientNavigateRunnable(mWindowId, aUrl, scope, promiseProxy);
|
|
|
+- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
|
|
+- } else {
|
|
|
+- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return promise.forget();
|
|
|
+-}
|
|
|
+diff --git a/dom/workers/ServiceWorkerWindowClient.h b/dom/workers/ServiceWorkerWindowClient.h
|
|
|
+deleted file mode 100644
|
|
|
+--- a/dom/workers/ServiceWorkerWindowClient.h
|
|
|
++++ /dev/null
|
|
|
+@@ -1,64 +0,0 @@
|
|
|
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
+-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
+-/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+- * You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
+- */
|
|
|
+-
|
|
|
+-#ifndef mozilla_dom_workers_serviceworkerwindowclient_h
|
|
|
+-#define mozilla_dom_workers_serviceworkerwindowclient_h
|
|
|
+-
|
|
|
+-#include "ServiceWorkerClient.h"
|
|
|
+-
|
|
|
+-namespace mozilla {
|
|
|
+-namespace dom {
|
|
|
+-
|
|
|
+-class Promise;
|
|
|
+-
|
|
|
+-namespace workers {
|
|
|
+-
|
|
|
+-class ServiceWorkerWindowClient final : public ServiceWorkerClient
|
|
|
+-{
|
|
|
+-public:
|
|
|
+- ServiceWorkerWindowClient(nsISupports* aOwner,
|
|
|
+- const ServiceWorkerClientInfo& aClientInfo)
|
|
|
+- : ServiceWorkerClient(aOwner, aClientInfo),
|
|
|
+- mVisibilityState(aClientInfo.mVisibilityState),
|
|
|
+- mFocused(aClientInfo.mFocused)
|
|
|
+- {
|
|
|
+- }
|
|
|
+-
|
|
|
+- virtual JSObject*
|
|
|
+- WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
|
+-
|
|
|
+- mozilla::dom::VisibilityState
|
|
|
+- VisibilityState() const
|
|
|
+- {
|
|
|
+- return mVisibilityState;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool
|
|
|
+- Focused() const
|
|
|
+- {
|
|
|
+- return mFocused;
|
|
|
+- }
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- Focus(ErrorResult& aRv) const;
|
|
|
+-
|
|
|
+- already_AddRefed<Promise>
|
|
|
+- Navigate(const nsAString& aUrl, ErrorResult& aRv);
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~ServiceWorkerWindowClient()
|
|
|
+- { }
|
|
|
+-
|
|
|
+- mozilla::dom::VisibilityState mVisibilityState;
|
|
|
+- bool mFocused;
|
|
|
+-};
|
|
|
+-
|
|
|
+-} // namespace workers
|
|
|
+-} // namespace dom
|
|
|
+-} // namespace mozilla
|
|
|
+-
|
|
|
+-#endif // mozilla_dom_workers_serviceworkerwindowclient_h
|
|
|
+diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp
|
|
|
+--- a/dom/workers/WorkerScope.cpp
|
|
|
++++ b/dom/workers/WorkerScope.cpp
|
|
|
+@@ -4,16 +4,17 @@
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+
|
|
|
+ #include "WorkerScope.h"
|
|
|
+
|
|
|
+ #include "jsapi.h"
|
|
|
+ #include "mozilla/EventListenerManager.h"
|
|
|
+ #include "mozilla/dom/BindingDeclarations.h"
|
|
|
++#include "mozilla/dom/Clients.h"
|
|
|
+ #include "mozilla/dom/Console.h"
|
|
|
+ #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
|
|
|
+ #include "mozilla/dom/Fetch.h"
|
|
|
+ #include "mozilla/dom/FunctionBinding.h"
|
|
|
+ #include "mozilla/dom/IDBFactory.h"
|
|
|
+ #include "mozilla/dom/ImageBitmap.h"
|
|
|
+ #include "mozilla/dom/ImageBitmapBinding.h"
|
|
|
+ #include "mozilla/dom/Performance.h"
|
|
|
+@@ -39,17 +40,16 @@
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #include "Crypto.h"
|
|
|
+ #include "Principal.h"
|
|
|
+ #include "RuntimeService.h"
|
|
|
+ #include "ScriptLoader.h"
|
|
|
+ #include "WorkerPrivate.h"
|
|
|
+ #include "WorkerRunnable.h"
|
|
|
+-#include "ServiceWorkerClients.h"
|
|
|
+ #include "ServiceWorkerManager.h"
|
|
|
+ #include "ServiceWorkerRegistration.h"
|
|
|
+
|
|
|
+ #ifdef XP_WIN
|
|
|
+ #undef PostMessage
|
|
|
+ #endif
|
|
|
+
|
|
|
+ extern already_AddRefed<nsIScriptTimeoutHandler>
|
|
|
+@@ -630,24 +630,25 @@ ServiceWorkerGlobalScope::WrapGlobalObje
|
|
|
+ JS::CompartmentOptions options;
|
|
|
+ mWorkerPrivate->CopyJSCompartmentOptions(options);
|
|
|
+
|
|
|
+ return ServiceWorkerGlobalScopeBinding::Wrap(aCx, this, this, options,
|
|
|
+ GetWorkerPrincipal(),
|
|
|
+ true, aReflector);
|
|
|
+ }
|
|
|
+
|
|
|
+-ServiceWorkerClients*
|
|
|
+-ServiceWorkerGlobalScope::Clients()
|
|
|
++already_AddRefed<Clients>
|
|
|
++ServiceWorkerGlobalScope::GetClients()
|
|
|
+ {
|
|
|
+ if (!mClients) {
|
|
|
+- mClients = new ServiceWorkerClients(this);
|
|
|
++ mClients = new Clients(this);
|
|
|
+ }
|
|
|
+
|
|
|
+- return mClients;
|
|
|
++ RefPtr<Clients> ref = mClients;
|
|
|
++ return ref.forget();
|
|
|
+ }
|
|
|
+
|
|
|
+ ServiceWorkerRegistration*
|
|
|
+ ServiceWorkerGlobalScope::Registration()
|
|
|
+ {
|
|
|
+ if (!mRegistration) {
|
|
|
+ mRegistration =
|
|
|
+ ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate, mScope);
|
|
|
+diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h
|
|
|
+--- a/dom/workers/WorkerScope.h
|
|
|
++++ b/dom/workers/WorkerScope.h
|
|
|
+@@ -14,16 +14,17 @@
|
|
|
+ #include "nsWeakReference.h"
|
|
|
+ #include "mozilla/dom/ImageBitmapSource.h"
|
|
|
+
|
|
|
+ namespace mozilla {
|
|
|
+ namespace dom {
|
|
|
+
|
|
|
+ class AnyCallback;
|
|
|
+ struct ChannelPixelLayout;
|
|
|
++class Clients;
|
|
|
+ class Console;
|
|
|
+ class Crypto;
|
|
|
+ class Function;
|
|
|
+ class IDBFactory;
|
|
|
+ enum class ImageBitmapFormat : uint8_t;
|
|
|
+ class Performance;
|
|
|
+ class Promise;
|
|
|
+ class RequestOrUSVString;
|
|
|
+@@ -35,17 +36,16 @@ enum class CallerType : uint32_t;
|
|
|
+ namespace cache {
|
|
|
+
|
|
|
+ class CacheStorage;
|
|
|
+
|
|
|
+ } // namespace cache
|
|
|
+
|
|
|
+ namespace workers {
|
|
|
+
|
|
|
+-class ServiceWorkerClients;
|
|
|
+ class WorkerPrivate;
|
|
|
+
|
|
|
+ } // namespace workers
|
|
|
+
|
|
|
+ class WorkerGlobalScope : public DOMEventTargetHelper,
|
|
|
+ public nsIGlobalObject,
|
|
|
+ public nsSupportsWeakReference
|
|
|
+ {
|
|
|
+@@ -277,17 +277,17 @@ public:
|
|
|
+ Close(JSContext* aCx);
|
|
|
+
|
|
|
+ IMPL_EVENT_HANDLER(connect)
|
|
|
+ };
|
|
|
+
|
|
|
+ class ServiceWorkerGlobalScope final : public WorkerGlobalScope
|
|
|
+ {
|
|
|
+ const nsString mScope;
|
|
|
+- RefPtr<workers::ServiceWorkerClients> mClients;
|
|
|
++ RefPtr<Clients> mClients;
|
|
|
+ RefPtr<ServiceWorkerRegistration> mRegistration;
|
|
|
+
|
|
|
+ ~ServiceWorkerGlobalScope();
|
|
|
+
|
|
|
+ public:
|
|
|
+ NS_DECL_ISUPPORTS_INHERITED
|
|
|
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope,
|
|
|
+ WorkerGlobalScope)
|
|
|
+@@ -301,18 +301,18 @@ public:
|
|
|
+ JS::MutableHandle<JSObject*> aReflector) override;
|
|
|
+
|
|
|
+ void
|
|
|
+ GetScope(nsString& aScope) const
|
|
|
+ {
|
|
|
+ aScope = mScope;
|
|
|
+ }
|
|
|
+
|
|
|
+- workers::ServiceWorkerClients*
|
|
|
+- Clients();
|
|
|
++ already_AddRefed<Clients>
|
|
|
++ GetClients();
|
|
|
+
|
|
|
+ ServiceWorkerRegistration*
|
|
|
+ Registration();
|
|
|
+
|
|
|
+ already_AddRefed<Promise>
|
|
|
+ SkipWaiting(ErrorResult& aRv);
|
|
|
+
|
|
|
+ IMPL_EVENT_HANDLER(activate)
|
|
|
+diff --git a/dom/workers/moz.build b/dom/workers/moz.build
|
|
|
+--- a/dom/workers/moz.build
|
|
|
++++ b/dom/workers/moz.build
|
|
|
+@@ -32,19 +32,16 @@ EXPORTS.mozilla.dom.workers += [
|
|
|
+ 'ServiceWorkerRegistrationInfo.h',
|
|
|
+ 'WorkerDebuggerManager.h',
|
|
|
+ 'Workers.h',
|
|
|
+ ]
|
|
|
+
|
|
|
+ # Stuff needed for the bindings, not really public though.
|
|
|
+ EXPORTS.mozilla.dom.workers.bindings += [
|
|
|
+ 'ServiceWorker.h',
|
|
|
+- 'ServiceWorkerClient.h',
|
|
|
+- 'ServiceWorkerClients.h',
|
|
|
+- 'ServiceWorkerWindowClient.h',
|
|
|
+ 'SharedWorker.h',
|
|
|
+ 'WorkerHolder.h',
|
|
|
+ 'WorkerHolderToken.h',
|
|
|
+ ]
|
|
|
+
|
|
|
+ XPIDL_MODULE = 'dom_workers'
|
|
|
+
|
|
|
+ XPIDL_SOURCES += [
|
|
|
+@@ -55,18 +52,16 @@ XPIDL_SOURCES += [
|
|
|
+ UNIFIED_SOURCES += [
|
|
|
+ 'ChromeWorkerScope.cpp',
|
|
|
+ 'FileReaderSync.cpp',
|
|
|
+ 'Principal.cpp',
|
|
|
+ 'RegisterBindings.cpp',
|
|
|
+ 'RuntimeService.cpp',
|
|
|
+ 'ScriptLoader.cpp',
|
|
|
+ 'ServiceWorker.cpp',
|
|
|
+- 'ServiceWorkerClient.cpp',
|
|
|
+- 'ServiceWorkerClients.cpp',
|
|
|
+ 'ServiceWorkerContainer.cpp',
|
|
|
+ 'ServiceWorkerDescriptor.cpp',
|
|
|
+ 'ServiceWorkerEvents.cpp',
|
|
|
+ 'ServiceWorkerInfo.cpp',
|
|
|
+ 'ServiceWorkerJob.cpp',
|
|
|
+ 'ServiceWorkerJobQueue.cpp',
|
|
|
+ 'ServiceWorkerManager.cpp',
|
|
|
+ 'ServiceWorkerManagerChild.cpp',
|
|
|
+@@ -77,17 +72,16 @@ UNIFIED_SOURCES += [
|
|
|
+ 'ServiceWorkerRegistrar.cpp',
|
|
|
+ 'ServiceWorkerRegistration.cpp',
|
|
|
+ 'ServiceWorkerRegistrationInfo.cpp',
|
|
|
+ 'ServiceWorkerScriptCache.cpp',
|
|
|
+ 'ServiceWorkerUnregisterJob.cpp',
|
|
|
+ 'ServiceWorkerUpdateJob.cpp',
|
|
|
+ 'ServiceWorkerUpdaterChild.cpp',
|
|
|
+ 'ServiceWorkerUpdaterParent.cpp',
|
|
|
+- 'ServiceWorkerWindowClient.cpp',
|
|
|
+ 'SharedWorker.cpp',
|
|
|
+ 'WorkerDebuggerManager.cpp',
|
|
|
+ 'WorkerHolder.cpp',
|
|
|
+ 'WorkerHolderToken.cpp',
|
|
|
+ 'WorkerLocation.cpp',
|
|
|
+ 'WorkerNavigator.cpp',
|
|
|
+ 'WorkerPrivate.cpp',
|
|
|
+ 'WorkerRunnable.cpp',
|