Bug 1173389 - Disable ServiceWorker network interception by default. r=ehsan
authorNikhil Marathe <nsm.nikhil@gmail.com>
Fri, 12 Jun 2015 16:28:13 -0700
changeset 280643 02f640a72dcde29f23dfb32a3b4a7d2a9a99d743
parent 280642 22c57d6465ddf42f46cedea42b4c79268b5f583d
child 280644 d411a0c7047b8da90999e0dd80ec79f4312729ac
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1173389
milestone41.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 1173389 - Disable ServiceWorker network interception by default. r=ehsan
browser/app/profile/firefox.js
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
dom/webidl/ServiceWorkerGlobalScope.webidl
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.h
dom/workers/WorkerScope.cpp
dom/workers/WorkerScope.h
dom/workers/Workers.h
dom/workers/test/serviceworkers/interception_featuredetect.js
dom/workers/test/serviceworkers/mochitest.ini
dom/workers/test/serviceworkers/periodic_update_test.js
dom/workers/test/serviceworkers/test_app_protocol.html
dom/workers/test/serviceworkers/test_bug1151916.html
dom/workers/test/serviceworkers/test_claim.html
dom/workers/test/serviceworkers/test_claim_fetch.html
dom/workers/test/serviceworkers/test_claim_oninstall.html
dom/workers/test/serviceworkers/test_client_focus.html
dom/workers/test/serviceworkers/test_close.html
dom/workers/test/serviceworkers/test_controller.html
dom/workers/test/serviceworkers/test_cross_origin_url_after_redirect.html
dom/workers/test/serviceworkers/test_empty_serviceworker.html
dom/workers/test/serviceworkers/test_fetch_event.html
dom/workers/test/serviceworkers/test_force_refresh.html
dom/workers/test/serviceworkers/test_https_fetch.html
dom/workers/test/serviceworkers/test_https_fetch_cloned_response.html
dom/workers/test/serviceworkers/test_https_synth_fetch_from_cached_sw.html
dom/workers/test/serviceworkers/test_importscript.html
dom/workers/test/serviceworkers/test_install_event.html
dom/workers/test/serviceworkers/test_installation_simple.html
dom/workers/test/serviceworkers/test_interception_featuredetect.html
dom/workers/test/serviceworkers/test_match_all.html
dom/workers/test/serviceworkers/test_match_all_advanced.html
dom/workers/test/serviceworkers/test_match_all_client_id.html
dom/workers/test/serviceworkers/test_match_all_client_properties.html
dom/workers/test/serviceworkers/test_navigator.html
dom/workers/test/serviceworkers/test_post_message.html
dom/workers/test/serviceworkers/test_post_message_advanced.html
dom/workers/test/serviceworkers/test_post_message_source.html
dom/workers/test/serviceworkers/test_request_context.html
dom/workers/test/serviceworkers/test_sandbox_intercept.html
dom/workers/test/serviceworkers/test_sanitize.html
dom/workers/test/serviceworkers/test_sanitize_domain.html
dom/workers/test/serviceworkers/test_scopes.html
dom/workers/test/serviceworkers/test_service_worker_allowed.html
dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
dom/workers/test/serviceworkers/test_serviceworker_not_sharedworker.html
dom/workers/test/serviceworkers/test_skip_waiting.html
dom/workers/test/serviceworkers/test_strict_mode_error.html
dom/workers/test/serviceworkers/test_unregister.html
dom/workers/test/serviceworkers/test_workerUnregister.html
dom/workers/test/serviceworkers/test_workerUpdate.html
dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
mobile/android/app/mobile.js
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1946,9 +1946,10 @@ pref("browser.pocket.oAuthConsumerKey", 
 pref("browser.pocket.useLocaleList", true);
 pref("browser.pocket.enabledLocales", "en-US de es-ES ja ja-JP-mac ru");
 
 pref("view_source.tab", true);
 
 // Enable Service Workers for desktop on non-release builds
 #ifndef RELEASE_BUILD
 pref("dom.serviceWorkers.enabled", true);
+pref("dom.serviceWorkers.interception.enabled", true);
 #endif
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -219,20 +219,22 @@ static NS_DEFINE_CID(kAppShellCID, NS_AP
 #else
 #include <unistd.h> // for getpid()
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::dom::workers::ServiceWorkerManager;
 
-// True means sUseErrorPages has been added to preferences var cache.
+// True means sUseErrorPages and sInterceptionEnabled has been added to
+// preferences var cache.
 static bool gAddedPreferencesVarCache = false;
 
 bool nsDocShell::sUseErrorPages = false;
+bool nsDocShell::sInterceptionEnabled = false;
 
 // Number of documents currently loading
 static int32_t gNumberOfDocumentsLoading = 0;
 
 // Global count of existing docshells.
 static int32_t gDocShellCount = 0;
 
 // Global count of docshells with the private attribute set
@@ -5736,16 +5738,19 @@ nsDocShell::Create()
   // Should we use XUL error pages instead of alerts if possible?
   mUseErrorPages =
     Preferences::GetBool("browser.xul.error_pages.enabled", mUseErrorPages);
 
   if (!gAddedPreferencesVarCache) {
     Preferences::AddBoolVarCache(&sUseErrorPages,
                                  "browser.xul.error_pages.enabled",
                                  mUseErrorPages);
+    Preferences::AddBoolVarCache(&sInterceptionEnabled,
+                                 "dom.serviceWorkers.interception.enabled",
+                                 false);
     gAddedPreferencesVarCache = true;
   }
 
   mDeviceSizeIsPageSize =
     Preferences::GetBool("docshell.device_size_is_page_size",
                          mDeviceSizeIsPageSize);
 
   nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
@@ -14042,16 +14047,21 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
 #endif
 }
 
 NS_IMETHODIMP
 nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
                                       bool* aShouldIntercept)
 {
   *aShouldIntercept = false;
+  // Preffed off.
+  if (!sInterceptionEnabled) {
+    return NS_OK;
+  }
+
   if (mSandboxFlags) {
     // If we're sandboxed, don't intercept.
     return NS_OK;
   }
 
   nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (!swm) {
     return NS_OK;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -898,16 +898,19 @@ protected:
     PARENT_ALLOWS,
     PARENT_PROHIBITS
   };
   FullscreenAllowedState mFullscreenAllowed;
 
   // Cached value of the "browser.xul.error_pages.enabled" preference.
   static bool sUseErrorPages;
 
+  // Cached value of the "dom.serviceWorkers.interception.enabled" preference.
+  static bool sInterceptionEnabled;
+
   bool mCreated;
   bool mAllowSubframes;
   bool mAllowPlugins;
   bool mAllowJavascript;
   bool mAllowMetaRedirects;
   bool mAllowImages;
   bool mAllowMedia;
   bool mAllowDNSPrefetch;
--- a/dom/webidl/ServiceWorkerGlobalScope.webidl
+++ b/dom/webidl/ServiceWorkerGlobalScope.webidl
@@ -16,16 +16,18 @@ interface ServiceWorkerGlobalScope : Wor
   readonly attribute Clients clients;
   readonly attribute ServiceWorkerRegistration registration;
 
   [Throws]
   Promise<boolean> skipWaiting();
 
   attribute EventHandler oninstall;
   attribute EventHandler onactivate;
+
+  [Func="mozilla::dom::workers::ServiceWorkerGlobalScope::InterceptionEnabled"]
   attribute EventHandler onfetch;
   attribute EventHandler onbeforeevicted;
   attribute EventHandler onevicted;
 
   // The event.source of these MessageEvents are instances of Client
   attribute EventHandler onmessage;
 };
 
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -156,16 +156,17 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 
 #define DUMP_CONTROLLED_BY_PREF 1
 #define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
 #endif
 
 #define PREF_DOM_CACHES_ENABLED        "dom.caches.enabled"
 #define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
 #define PREF_INTL_ACCEPT_LANGUAGES     "intl.accept_languages"
 #define PREF_SERVICEWORKERS_ENABLED    "dom.serviceWorkers.enabled"
+#define PREF_INTERCEPTION_ENABLED      "dom.serviceWorkers.interception.enabled"
 
 namespace {
 
 const uint32_t kNoIndex = uint32_t(-1);
 
 const JS::ContextOptions kRequiredContextOptions =
   JS::ContextOptions().setDontReportUncaught(true);
 
@@ -1900,16 +1901,20 @@ RuntimeService::Init()
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_DOM_CACHES_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_SERVICEWORKERS_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS))) ||
+      NS_FAILED(Preferences::RegisterCallbackAndCall(
+                                  WorkerPrefChanged,
+                                  PREF_INTERCEPTION_ENABLED,
+                                  reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
       NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
                                               PREF_JS_OPTIONS_PREFIX,
                                               nullptr)) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                                    LoadRuntimeOptions,
                                                    PREF_WORKERS_OPTIONS_PREFIX,
                                                    nullptr)) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(PrefLanguagesChanged,
@@ -2097,16 +2102,20 @@ RuntimeService::Cleanup()
         NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
                                                   PREF_JS_OPTIONS_PREFIX,
                                                   nullptr)) ||
         NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
                                                   PREF_WORKERS_OPTIONS_PREFIX,
                                                   nullptr)) ||
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
+                                  PREF_INTERCEPTION_ENABLED,
+                                  reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
+        NS_FAILED(Preferences::UnregisterCallback(
+                                  WorkerPrefChanged,
                                   PREF_SERVICEWORKERS_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS))) ||
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_DOM_CACHES_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
 #if DUMP_CONTROLLED_BY_PREF
         NS_FAILED(Preferences::UnregisterCallback(
@@ -2651,16 +2660,20 @@ RuntimeService::WorkerPrefChanged(const 
   if (key == WORKERPREF_DOM_CACHES) {
     key = WORKERPREF_DOM_CACHES;
     sDefaultPreferences[WORKERPREF_DOM_CACHES] =
       Preferences::GetBool(PREF_DOM_CACHES_ENABLED, false);
   } else if (key == WORKERPREF_SERVICEWORKERS) {
     key = WORKERPREF_SERVICEWORKERS;
     sDefaultPreferences[WORKERPREF_SERVICEWORKERS] =
       Preferences::GetBool(PREF_SERVICEWORKERS_ENABLED, false);
+  } else if (key == WORKERPREF_INTERCEPTION_ENABLED) {
+    key = WORKERPREF_INTERCEPTION_ENABLED;
+    sDefaultPreferences[key] =
+      Preferences::GetBool(PREF_INTERCEPTION_ENABLED, false);
   }
   // This function should never be registered as a callback for a preference it
   // does not handle.
   MOZ_ASSERT(key != WORKERPREF_COUNT);
 
   RuntimeService* rts = RuntimeService::GetService();
   if (rts) {
     rts->UpdateAllWorkerPreference(key, sDefaultPreferences[key]);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1235,16 +1235,23 @@ public:
   bool
   ServiceWorkersEnabled() const
   {
     AssertIsOnWorkerThread();
     return mPreferences[WORKERPREF_SERVICEWORKERS];
   }
 
   bool
+  InterceptionEnabled() const
+  {
+    AssertIsOnWorkerThread();
+    return mPreferences[WORKERPREF_INTERCEPTION_ENABLED];
+  }
+
+  bool
   OnLine() const
   {
     AssertIsOnWorkerThread();
     return mOnLine;
   }
 
   void
   StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -616,16 +616,26 @@ ServiceWorkerGlobalScope::SkipWaiting(Er
   aRv = NS_DispatchToMainThread(runnable);
   if (NS_WARN_IF(aRv.Failed())) {
     promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
   }
 
   return promise.forget();
 }
 
+// static
+bool
+ServiceWorkerGlobalScope::InterceptionEnabled(JSContext* aCx, JSObject* aObj)
+{
+  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
+  MOZ_ASSERT(worker);
+  worker->AssertIsOnWorkerThread();
+  return worker->InterceptionEnabled();
+}
+
 WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
                                                   WorkerPrivate* aWorkerPrivate)
 : mWorkerPrivate(aWorkerPrivate)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 }
 
 WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope()
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -210,16 +210,19 @@ public:
                                            WorkerGlobalScope)
 
   ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsACString& aScope);
 
   virtual bool
   WrapGlobalObject(JSContext* aCx,
                    JS::MutableHandle<JSObject*> aReflector) override;
 
+  static bool
+  InterceptionEnabled(JSContext* aCx, JSObject* aObj);
+
   void
   GetScope(nsString& aScope) const
   {
     aScope = mScope;
   }
 
   ServiceWorkerClients*
   Clients();
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -193,16 +193,17 @@ struct JSSettings
   }
 };
 
 enum WorkerPreference
 {
   WORKERPREF_DUMP = 0, // browser.dom.window.dump.enabled
   WORKERPREF_DOM_CACHES, // dom.caches.enabled
   WORKERPREF_SERVICEWORKERS, // dom.serviceWorkers.enabled
+  WORKERPREF_INTERCEPTION_ENABLED, // dom.serviceWorkers.interception.enabled
   WORKERPREF_COUNT
 };
 
 // Implemented in WorkerPrivate.cpp
 
 struct WorkerLoadInfo
 {
   // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/interception_featuredetect.js
@@ -0,0 +1,4 @@
+// Only succeeds if onfetch is available.
+if (!("onfetch" in self)) {
+  throw new Error("Not capable of interception");
+}
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -124,16 +124,17 @@ support-files =
   sw_clients/refresher_compressed.html
   sw_clients/refresher_compressed.html^headers^
   sw_clients/refresher_cached.html
   sw_clients/refresher_cached_compressed.html
   sw_clients/refresher_cached_compressed.html^headers^
   strict_mode_error.js
   skip_waiting_installed_worker.js
   skip_waiting_scope/index.html
+  interception_featuredetect.js
   thirdparty/iframe1.html
   thirdparty/iframe2.html
   thirdparty/register.html
   thirdparty/unregister.html
   thirdparty/sw.js
   register_https.html
   gzip_redirect_worker.js
   sw_clients/navigator.html
@@ -178,16 +179,17 @@ support-files =
 [test_service_worker_allowed.html]
 [test_app_protocol.html]
 [test_third_party_iframes.html]
 [test_claim_fetch.html]
 [test_force_refresh.html]
 [test_skip_waiting.html]
 [test_strict_mode_error.html]
 [test_cross_origin_url_after_redirect.html]
+[test_interception_featuredetect.html]
 [test_origin_after_redirect.html]
 [test_origin_after_redirect_cached.html]
 [test_origin_after_redirect_to_https.html]
 [test_origin_after_redirect_to_https_cached.html]
 [test_https_origin_after_redirect.html]
 [test_https_origin_after_redirect_cached.html]
 [test_gzip_redirect.html]
 [test_register_base.html]
--- a/dom/workers/test/serviceworkers/periodic_update_test.js
+++ b/dom/workers/test/serviceworkers/periodic_update_test.js
@@ -60,14 +60,15 @@ function unregisterSW() {
   return testFrame(gPrefix + "periodic/unregister.html");
 }
 
 function runTheTest() {
   SimpleTest.waitForExplicitFinish();
 
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, function() {
     start();
   });
 }
--- a/dom/workers/test/serviceworkers/test_app_protocol.html
+++ b/dom/workers/test/serviceworkers/test_app_protocol.html
@@ -22,16 +22,17 @@ const appManifestURL =
 let gApp;
 
 function setup() {
   return new Promise((resolve, reject) => {
     SpecialPowers.setAllAppsLaunchable(true);
     SpecialPowers.pushPrefEnv({'set': [
       ['dom.mozBrowserFramesEnabled', true],
       ['dom.serviceWorkers.exemptFromPerDomainMax', true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ['dom.serviceWorkers.enabled', true],
       ['dom.serviceWorkers.testing.enabled', true],
       ['dom.caches.enabled', true],
     ]}, () => {
       SpecialPowers.pushPermissions([
         { 'type': 'webapps-manage', 'allow': 1, 'context': document },
         { 'type': 'browser', 'allow': 1, 'context': document },
         { 'type': 'embed-apps', 'allow': 1, 'context': document }
--- a/dom/workers/test/serviceworkers/test_bug1151916.html
+++ b/dom/workers/test/serviceworkers/test_bug1151916.html
@@ -89,16 +89,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
     ["dom.caches.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_claim.html
+++ b/dom/workers/test/serviceworkers/test_claim.html
@@ -157,16 +157,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_claim_fetch.html
+++ b/dom/workers/test/serviceworkers/test_claim_fetch.html
@@ -83,16 +83,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_claim_oninstall.html
+++ b/dom/workers/test/serviceworkers/test_claim_oninstall.html
@@ -58,16 +58,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_client_focus.html
+++ b/dom/workers/test/serviceworkers/test_client_focus.html
@@ -81,16 +81,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_close.html
+++ b/dom/workers/test/serviceworkers/test_close.html
@@ -49,16 +49,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_controller.html
+++ b/dom/workers/test/serviceworkers/test_controller.html
@@ -69,16 +69,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_cross_origin_url_after_redirect.html
+++ b/dom/workers/test/serviceworkers/test_cross_origin_url_after_redirect.html
@@ -35,16 +35,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_empty_serviceworker.html
+++ b/dom/workers/test/serviceworkers/test_empty_serviceworker.html
@@ -31,16 +31,17 @@
       SimpleTest.finish();
     });
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true]
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_fetch_event.html
+++ b/dom/workers/test/serviceworkers/test_fetch_event.html
@@ -68,16 +68,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_force_refresh.html
+++ b/dom/workers/test/serviceworkers/test_force_refresh.html
@@ -69,16 +69,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
     ["dom.caches.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_https_fetch.html
+++ b/dom/workers/test/serviceworkers/test_https_fetch.html
@@ -42,16 +42,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true]
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_https_fetch_cloned_response.html
+++ b/dom/workers/test/serviceworkers/test_https_fetch_cloned_response.html
@@ -40,16 +40,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true]
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_https_synth_fetch_from_cached_sw.html
+++ b/dom/workers/test/serviceworkers/test_https_synth_fetch_from_cached_sw.html
@@ -53,16 +53,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true]
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_importscript.html
+++ b/dom/workers/test/serviceworkers/test_importscript.html
@@ -58,15 +58,16 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_install_event.html
+++ b/dom/workers/test/serviceworkers/test_install_event.html
@@ -98,16 +98,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_installation_simple.html
+++ b/dom/workers/test/serviceworkers/test_installation_simple.html
@@ -196,16 +196,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.messageChannel.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/test_interception_featuredetect.html
@@ -0,0 +1,96 @@
+
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1173389 - Test fetch interception feature detection.</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"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  function register() {
+    // Randomness required to prevent reusing existing registration.
+    return navigator.serviceWorker.register("interception_featuredetect.js",
+                                            { scope: "featuredetect/" + Math.random() });
+  }
+
+  function registerWithPrefDisabled() {
+    return new Promise(function(resolve, reject) {
+      SpecialPowers.pushPrefEnv(
+        {"set": [["dom.serviceWorkers.interception.enabled", false]]},
+        function() {
+          register().then(function(v) {
+              ok(false, "Registration should fail when interception is disabled.");
+              reject();
+            }, function(e) {
+              ok(true, "Registration should fail when interception is disabled.");
+              resolve();
+            });
+        });
+    });
+  }
+
+  function registerWithPrefEnabled() {
+    return new Promise(function(resolve, reject) {
+      SpecialPowers.pushPrefEnv(
+        {"set": [["dom.serviceWorkers.interception.enabled", true]]},
+        function() {
+          register().then(function(v) {
+              ok(true, "Registration should succeed when interception is enabled.");
+              resolve();
+            }, function(e) {
+              ok(false, "Registration should succeed when interception is enabled.");
+              reject()
+            });
+        });
+    });
+  }
+
+  function unregister() {
+    return navigator.serviceWorker.getRegistrations().then(function(regs) {
+      var unregs = [];
+      regs.forEach(function(reg) {
+        if (reg.scope.indexOf("featuredetect") > -1) {
+          unregs.push(reg.unregister());
+        }
+      })
+
+      return Promise.all(unregs);
+    });
+  }
+
+  function runTest() {
+    Promise.resolve()
+      .then(registerWithPrefDisabled)
+      .then(registerWithPrefEnabled)
+      .then(registerWithPrefDisabled)
+      .then(unregister)
+      // put more tests here.
+      .then(function() {
+        SimpleTest.finish();
+      }).catch(function(e) {
+        ok(false, "Some test failed with error " + e);
+        SimpleTest.finish();
+      });
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", false],
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.testing.enabled", true]
+  ]}, runTest);
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/workers/test/serviceworkers/test_match_all.html
+++ b/dom/workers/test/serviceworkers/test_match_all.html
@@ -65,16 +65,17 @@
         ok(true, "Didn't crash on resolving matchAll promises while worker shuts down.");
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_match_all_advanced.html
+++ b/dom/workers/test/serviceworkers/test_match_all_advanced.html
@@ -85,16 +85,17 @@
         SimpleTest.finish();
       });
 
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_match_all_client_id.html
+++ b/dom/workers/test/serviceworkers/test_match_all_client_id.html
@@ -76,15 +76,16 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_match_all_client_properties.html
+++ b/dom/workers/test/serviceworkers/test_match_all_client_properties.html
@@ -83,15 +83,16 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_navigator.html
+++ b/dom/workers/test/serviceworkers/test_navigator.html
@@ -23,16 +23,17 @@
     ok(navigator.serviceWorker.ready instanceof Promise, "navigator.serviceWorker.ready should be a Promise.");
     ok(navigator.serviceWorker.controller === null, "There should be no controller worker for an uncontrolled document.");
   }
 
   SimpleTest.waitForExplicitFinish();
 
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true]
   ]}, function() {
     checkEnabled();
     SimpleTest.finish();
   });
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_post_message.html
+++ b/dom/workers/test/serviceworkers/test_post_message.html
@@ -64,16 +64,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_post_message_advanced.html
+++ b/dom/workers/test/serviceworkers/test_post_message_advanced.html
@@ -93,16 +93,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_post_message_source.html
+++ b/dom/workers/test/serviceworkers/test_post_message_source.html
@@ -52,16 +52,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_request_context.html
+++ b/dom/workers/test/serviceworkers/test_request_context.html
@@ -83,16 +83,17 @@
     SpecialPowers.pushPrefEnv({"set": [
       ["beacon.enabled", true],
       ["browser.send_pings", true],
       ["browser.send_pings.max_per_link", -1],
       ["dom.caches.enabled", true],
       ["dom.image.picture.enabled", true],
       ["dom.image.srcset.enabled", true],
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_sandbox_intercept.html
+++ b/dom/workers/test/serviceworkers/test_sandbox_intercept.html
@@ -35,16 +35,17 @@
       }
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_sanitize.html
+++ b/dom/workers/test/serviceworkers/test_sanitize.html
@@ -70,16 +70,17 @@
   function registerSW() {
     return testFrame("sanitize/register.html");
   }
 
   SimpleTest.waitForExplicitFinish();
 
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, function() {
     start();
   });
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_sanitize_domain.html
+++ b/dom/workers/test/serviceworkers/test_sanitize_domain.html
@@ -73,16 +73,17 @@
               return testFrame("http://prefixexample.com/tests/dom/workers/test/serviceworkers/sanitize/register.html");
             });
   }
 
   SimpleTest.waitForExplicitFinish();
 
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, function() {
     start();
   });
 </script>
 </pre>
 </body>
--- a/dom/workers/test/serviceworkers/test_scopes.html
+++ b/dom/workers/test/serviceworkers/test_scopes.html
@@ -106,16 +106,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_service_worker_allowed.html
+++ b/dom/workers/test/serviceworkers/test_service_worker_allowed.html
@@ -62,13 +62,14 @@
     });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
@@ -99,16 +99,17 @@
     // if service workers are disabled by default we want to force on both
     // service workers and "dom.caches.enabled".  But if service workers are
     // enabled by default, we do not want to mess with the "dom.caches.enabled"
     // value, since that would defeat the purpose of the test.  Use a subframe
     // to decide whether service workers are enabled by default, so we don't
     // force creation of our own Navigator object before our prefs are set.
     var prefs = [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ];
 
     var subframe = document.createElement("iframe");
     document.body.appendChild(subframe);
     if (!("serviceWorker" in subframe.contentWindow.navigator)) {
 	prefs.push(["dom.caches.enabled", true]);
--- a/dom/workers/test/serviceworkers/test_serviceworker_not_sharedworker.html
+++ b/dom/workers/test/serviceworkers/test_serviceworker_not_sharedworker.html
@@ -51,16 +51,17 @@
       sw.postMessage({msg: "whoareyou"});
     };
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true]
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_skip_waiting.html
+++ b/dom/workers/test/serviceworkers/test_skip_waiting.html
@@ -81,15 +81,16 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_strict_mode_error.html
+++ b/dom/workers/test/serviceworkers/test_strict_mode_error.html
@@ -24,16 +24,17 @@
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+      ["dom.serviceWorkers.interception.enabled", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/serviceworkers/test_unregister.html
+++ b/dom/workers/test/serviceworkers/test_unregister.html
@@ -123,16 +123,17 @@
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_workerUnregister.html
+++ b/dom/workers/test/serviceworkers/test_workerUnregister.html
@@ -67,16 +67,17 @@
     }).then(function() {
       SimpleTest.finish();
     });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_workerUpdate.html
+++ b/dom/workers/test/serviceworkers/test_workerUpdate.html
@@ -40,16 +40,17 @@
     }).then(function() {
       SimpleTest.finish();
     });
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true]
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
+++ b/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
@@ -70,16 +70,17 @@
       .catch(function(e) {
         ok(false, "Some test failed with error " + e);
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -913,9 +913,10 @@ pref("caret.manages-android-actionbar", 
 pref("consoleservice.logcat", false);
 #else
 pref("consoleservice.logcat", true);
 #endif
 
 // Enable Service Workers for Android on non-release builds
 #ifndef RELEASE_BUILD
 pref("dom.serviceWorkers.enabled", true);
+pref("dom.serviceWorkers.interception.enabled", true);
 #endif
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
@@ -1,3 +1,3 @@
 [cache-add.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
@@ -1,3 +1,3 @@
 [cache-delete.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
@@ -1,3 +1,3 @@
 [cache-match.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
@@ -1,3 +1,3 @@
 [cache-put.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
@@ -1,3 +1,3 @@
 [cache-storage-keys.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
@@ -1,3 +1,3 @@
 [cache-storage-match.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
@@ -1,3 +1,3 @@
 [cache-storage.https.html]
   type: testharness
-  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
+  prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]