Bug 1598278 - Check that Service Worker controls client in navigate() r=asuth
authorDaniel Huigens <d.huigens@protonmail.com>
Tue, 24 Mar 2020 23:35:38 +0000
changeset 520308 3a4dc0ad12668c5ffcf25c115b15214b9e47834b
parent 520307 47c0d3f679dcb1c2d0f2a5de9e83c088c2c483c9
child 520309 36300cc32afc651a155380297dd1fdc8bcd31c31
push id37246
push useropoprus@mozilla.com
push dateWed, 25 Mar 2020 03:40:33 +0000
treeherdermozilla-central@14b59d4adc95 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1598278
milestone76.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1598278 - Check that Service Worker controls client in navigate() r=asuth Differential Revision: https://phabricator.services.mozilla.com/D66040
dom/clients/api/Client.cpp
dom/clients/manager/ClientIPCTypes.ipdlh
dom/clients/manager/ClientManagerService.cpp
testing/web-platform/meta/service-workers/service-worker/windowclient-navigate.https.html.ini
--- a/dom/clients/api/Client.cpp
+++ b/dom/clients/api/Client.cpp
@@ -180,17 +180,18 @@ already_AddRefed<Promise> Client::Naviga
   workerPrivate->AssertIsOnWorkerThread();
 
   RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
   if (aRv.Failed()) {
     return outerPromise.forget();
   }
 
   ClientNavigateArgs args(mData->info(), NS_ConvertUTF16toUTF8(aURL),
-                          workerPrivate->GetLocationInfo().mHref);
+                          workerPrivate->GetLocationInfo().mHref,
+                          workerPrivate->GetServiceWorkerDescriptor().ToIPC());
   RefPtr<Client> self = this;
 
   StartClientManagerOp(
       &ClientManager::Navigate, args, mGlobal,
       [self, outerPromise](const ClientOpResult& aResult) {
         if (aResult.type() != ClientOpResult::TClientInfoAndState) {
           outerPromise->MaybeResolve(JS::NullHandleValue);
           return;
--- a/dom/clients/manager/ClientIPCTypes.ipdlh
+++ b/dom/clients/manager/ClientIPCTypes.ipdlh
@@ -80,16 +80,17 @@ struct ClientFocusArgs
   CallerType callerType;
 };
 
 struct ClientNavigateArgs
 {
   IPCClientInfo target;
   nsCString url;
   nsCString baseURL;
+  IPCServiceWorkerDescriptor serviceWorker;
 };
 
 struct ClientPostMessageArgs
 {
   ClonedMessageData clonedData;
   IPCServiceWorkerDescriptor serviceWorker;
 };
 
--- a/dom/clients/manager/ClientManagerService.cpp
+++ b/dom/clients/manager/ClientManagerService.cpp
@@ -279,16 +279,29 @@ RefPtr<ClientOpPromise> ClientManagerSer
   ClientSourceParent* source =
       FindSource(aArgs.target().id(), aArgs.target().principalInfo());
   if (!source) {
     CopyableErrorResult rv;
     rv.ThrowInvalidStateError("Unknown client");
     return ClientOpPromise::CreateAndReject(rv, __func__);
   }
 
+  const IPCServiceWorkerDescriptor& serviceWorker = aArgs.serviceWorker();
+
+  // Per https://w3c.github.io/ServiceWorker/#dom-windowclient-navigate step 4,
+  // if the service worker does not control the client, reject with a TypeError.
+  const Maybe<ServiceWorkerDescriptor>& controller = source->GetController();
+  if (controller.isNothing() ||
+      controller.ref().Scope() != serviceWorker.scope() ||
+      controller.ref().Id() != serviceWorker.id()) {
+    CopyableErrorResult rv;
+    rv.ThrowTypeError("Client is not controlled by this Service Worker");
+    return ClientOpPromise::CreateAndReject(rv, __func__);
+  }
+
   PClientManagerParent* manager = source->Manager();
   MOZ_DIAGNOSTIC_ASSERT(manager);
 
   ClientNavigateOpConstructorArgs args;
   args.url() = aArgs.url();
   args.baseURL() = aArgs.baseURL();
 
   // This is safe to do because the ClientSourceChild cannot directly delete
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/service-worker/windowclient-navigate.https.html.ini
+++ /dev/null
@@ -1,32 +0,0 @@
-[windowclient-navigate.https.html]
-  expected: [OK, ERROR, TIMEOUT]
-  [in scope but not controlled test on installing worker worker side]
-    expected: FAIL
-
-  [in scope but not controlled test on active worker worker side]
-    expected: FAIL
-
-  [out of scope worker side]
-    expected: FAIL
-
-  [invalid url (about:blank)]
-    expected: [PASS, TIMEOUT, NOTRUN]
-
-  [in scope but not controlled test on active worker]
-    expected: [PASS, NOTRUN]
-
-  [out of scope]
-    expected: [PASS, NOTRUN]
-
-  [invalid url (view-source://example.com)]
-    expected: [PASS, NOTRUN]
-
-  [invalid url (http://[example.com\])]
-    expected: [PASS, NOTRUN]
-
-  [invalid url (file:///)]
-    expected: [PASS, NOTRUN]
-
-  [cross orgin url]
-    expected: [PASS, NOTRUN]
-