Bug 1131353 - Make ServiceWorkerGlobalScope.close() throw InvalidAccessError; r=baku
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 05 Mar 2015 22:48:07 -0500
changeset 232227 f827206d78403d80266d1082cc87e15875aac62f
parent 232226 dccc995ad9c1aba55cb05dd8a43798aa71af0926
child 232228 f4a651c0953d79e0867026ed76d21e426018d1bd
push id56490
push usereakhgari@mozilla.com
push dateFri, 06 Mar 2015 13:20:22 +0000
treeherdermozilla-inbound@f827206d7840 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1131353
milestone39.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 1131353 - Make ServiceWorkerGlobalScope.close() throw InvalidAccessError; r=baku
dom/webidl/ServiceWorkerGlobalScope.webidl
dom/webidl/WorkerGlobalScope.webidl
dom/workers/WorkerScope.cpp
dom/workers/WorkerScope.h
dom/workers/test/serviceworkers/close_test.js
dom/workers/test/serviceworkers/mochitest.ini
dom/workers/test/serviceworkers/test_close.html
--- a/dom/webidl/ServiceWorkerGlobalScope.webidl
+++ b/dom/webidl/ServiceWorkerGlobalScope.webidl
@@ -23,15 +23,11 @@ interface ServiceWorkerGlobalScope : Wor
   attribute EventHandler oninstall;
   attribute EventHandler onactivate;
   attribute EventHandler onfetch;
   attribute EventHandler onbeforeevicted;
   attribute EventHandler onevicted;
 
   // The event.source of these MessageEvents are instances of Client
   attribute EventHandler onmessage;
-
-  // close() method inherited from WorkerGlobalScope is not exposed.
-  // FIXME(nsm): For now, overridden so it can be a no-op.
-  void close();
 };
 
 
--- a/dom/webidl/WorkerGlobalScope.webidl
+++ b/dom/webidl/WorkerGlobalScope.webidl
@@ -16,16 +16,17 @@
 interface WorkerGlobalScope : EventTarget {
   readonly attribute WorkerGlobalScope self;
 
   [Replaceable]
   readonly attribute Console console;
 
   readonly attribute WorkerLocation location;
 
+  [Throws]
   void close();
   attribute OnErrorEventHandler onerror;
 
   attribute EventHandler onoffline;
   attribute EventHandler ononline;
   // also has additional members in a partial interface
 };
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -166,21 +166,25 @@ WorkerGlobalScope::GetExistingNavigator(
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   nsRefPtr<WorkerNavigator> navigator = mNavigator;
   return navigator.forget();
 }
 
 void
-WorkerGlobalScope::Close(JSContext* aCx)
+WorkerGlobalScope::Close(JSContext* aCx, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
-  mWorkerPrivate->CloseInternal(aCx);
+  if (mWorkerPrivate->IsServiceWorker()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+  } else {
+    mWorkerPrivate->CloseInternal(aCx);
+  }
 }
 
 OnErrorEventHandlerNonNull*
 WorkerGlobalScope::GetOnerror()
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   EventListenerManager* elm = GetExistingListenerManager();
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -93,17 +93,17 @@ public:
 
   already_AddRefed<WorkerNavigator>
   Navigator();
 
   already_AddRefed<WorkerNavigator>
   GetExistingNavigator() const;
 
   void
-  Close(JSContext* aCx);
+  Close(JSContext* aCx, ErrorResult& aRv);
 
   OnErrorEventHandlerNonNull*
   GetOnerror();
   void
   SetOnerror(OnErrorEventHandlerNonNull* aHandler);
 
   void
   ImportScripts(JSContext* aCx, const Sequence<nsString>& aScriptURLs,
@@ -214,22 +214,16 @@ public:
 
   void
   GetScope(nsString& aScope) const
   {
     aScope = mScope;
   }
 
   void
-  Close() const
-  {
-    // no-op close.
-  }
-
-  void
   Update();
 
   already_AddRefed<Promise>
   Unregister(ErrorResult& aRv);
 
   ServiceWorkerClients*
   Clients();
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/close_test.js
@@ -0,0 +1,19 @@
+function ok(v, msg) {
+  client.postMessage({status: "ok", result: !!v, message: msg});
+}
+
+var client;
+onmessage = function(e) {
+  if (e.data.message == "start") {
+    self.clients.matchAll().then(function(clients) {
+      client = clients[0];
+      try {
+        close();
+        ok(false, "close() should throw");
+      } catch (e) {
+        ok(e.name === "InvalidAccessError", "close() should throw InvalidAccessError");
+      }
+      client.postMessage({status: "done"});
+    });
+  }
+}
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -21,16 +21,17 @@ support-files =
   worker_unregister.js
   worker_update.js
   message_posting_worker.js
   fetch/index.html
   fetch/fetch_worker_script.js
   fetch/fetch_tests.js
   match_all_properties_worker.js
   match_all_clients/match_all_controlled.html
+  close_test.js
 
 [test_unregister.html]
 skip-if = true # Bug 1133805
 [test_installation_simple.html]
 [test_fetch_event.html]
 [test_match_all.html]
 [test_install_event.html]
 [test_navigator.html]
@@ -38,8 +39,9 @@ skip-if = true # Bug 1133805
 [test_controller.html]
 [test_workerUpdate.html]
 skip-if = true # Bug 1133805
 [test_workerUnregister.html]
 skip-if = true # Bug 1133805
 [test_post_message.html]
 [test_post_message_advanced.html]
 [test_match_all_client_properties.html]
+[test_close.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/test_close.html
@@ -0,0 +1,69 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1131353 - test WorkerGlobalScope.close() on service workers</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe></iframe>
+</div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  var iframe;
+  function runTest() {
+    navigator.serviceWorker.register("close_test.js", {scope: "."})
+      .then(function(registration) {
+        if (registration.installing) {
+          registration.installing.onstatechange = function(e) {
+            setupSW(registration);
+            e.target.onstatechange = null;
+          };
+        } else {
+          setupSW(registration);
+        }
+      });
+
+    function setupSW(registration) {
+      var worker = registration.waiting ||
+                   registration.active;
+      var iframe = document.createElement("iframe");
+      iframe.src = "message_receiver.html";
+      iframe.onload = function() {
+        worker.postMessage({ message: "start" });
+      };
+      document.body.appendChild(iframe);
+    }
+
+    window.onmessage = function(e) {
+      if (e.data.status == "ok") {
+        ok(e.data.result, e.data.message);
+      } else if (e.data.status == "done") {
+        navigator.serviceWorker.getRegistration().then(function(registration) {
+          registration.unregister().then(function() {
+            SimpleTest.finish();
+          });
+        });
+      }
+    };
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  onload = function() {
+    SpecialPowers.pushPrefEnv({"set": [
+      ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.enabled", true],
+      ["dom.serviceWorkers.testing.enabled", true],
+    ]}, runTest);
+  };
+</script>
+</pre>
+</body>
+</html>