Bug 1188091 - Fix the exposure of Push interfaces; r=dougt,bzbarsky,nsm
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 27 Jul 2015 15:35:28 -0400
changeset 287024 ffd18bccd1ce140a71315e33ead24d7918a5f99f
parent 287023 ea041b07a51b93ea54f50ffb68c65704e18eff57
child 287025 89167fe9d3ba17e66010f05faf98eb82e7719095
child 287074 bce1487864338fa488dcdba1d8f3c96cb209291f
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt, bzbarsky, nsm
bugs1188091
milestone42.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 1188091 - Fix the exposure of Push interfaces; r=dougt,bzbarsky,nsm Currently we don't check the dom.push.enabled pref in some cases for some of these interfaces. This patch unifies how all of these interfaces are exposed to Window, Worker, and ServiceWorker.
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/push/PushManager.cpp
dom/push/PushManager.h
dom/webidl/PushEvent.webidl
dom/webidl/PushManager.webidl
dom/webidl/PushMessageData.webidl
dom/webidl/PushSubscription.webidl
dom/webidl/ServiceWorkerRegistration.webidl
dom/workers/RuntimeService.cpp
dom/workers/ServiceWorkerEvents.h
dom/workers/WorkerPrivate.h
dom/workers/Workers.h
dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
dom/workers/test/test_worker_interfaces.js
modules/libpref/init/all.js
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -46,16 +46,17 @@
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/TextDecoder.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/ShadowRoot.h"
+#include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
@@ -7968,8 +7969,27 @@ nsContentUtils::SetFetchReferrerURIWithP
 
   if (!referrerURI) {
     referrerURI = principalURI;
   }
 
   net::ReferrerPolicy referrerPolicy = aDoc->GetReferrerPolicy();
   return aChannel->SetReferrerWithPolicy(referrerURI, referrerPolicy);
 }
+
+// static
+bool
+nsContentUtils::PushEnabled(JSContext* aCx, JSObject* aObj)
+{
+  if (NS_IsMainThread()) {
+    return Preferences::GetBool("dom.push.enabled", false);
+  }
+
+  using namespace workers;
+
+  // Otherwise, check the pref via the WorkerPrivate
+  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+  if (!workerPrivate) {
+    return false;
+  }
+
+  return workerPrivate->PushEnabled();
+}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2434,16 +2434,18 @@ public:
    * aDoc may be null.
    *
    * https://w3c.github.io/webappsec/specs/referrer-policy/#determine-requests-referrer
    */
   static nsresult SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
                                                 nsIDocument* aDoc,
                                                 nsIHttpChannel* aChannel);
 
+  static bool PushEnabled(JSContext* aCx, JSObject* aObj);
+
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
--- a/dom/push/PushManager.cpp
+++ b/dom/push/PushManager.cpp
@@ -124,33 +124,16 @@ PushSubscription::Constructor(GlobalObje
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PushSubscription, mGlobal, mPrincipal)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PushSubscription)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PushSubscription)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushSubscription)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-// PushManager
-// static
-bool
-PushManager::Enabled(JSContext* aCx, JSObject* aObj)
-{
-  if (NS_IsMainThread()) {
-    return Preferences::GetBool("dom.push.enabled", false);
-  }
-
-  // XXXnsm: As of this patch it seems like Push will be enabled before or with
-  // ServiceWorkers, so this seems OK for now.
-  ServiceWorkerGlobalScope* scope = nullptr;
-  nsresult rv = UnwrapObject<prototypes::id::ServiceWorkerGlobalScope_workers,
-                             mozilla::dom::ServiceWorkerGlobalScopeBinding_workers::NativeType>(aObj, scope);
-  return NS_SUCCEEDED(rv);
-}
-
 PushManager::PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope)
   : mGlobal(aGlobal), mScope(aScope)
 {
   AssertIsOnMainThread();
 }
 
 PushManager::~PushManager()
 {}
--- a/dom/push/PushManager.h
+++ b/dom/push/PushManager.h
@@ -101,19 +101,16 @@ private:
 
 class PushManager final : public nsISupports
                         , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushManager)
 
-  static bool
-  Enabled(JSContext* aCx, JSObject* aObj);
-
   explicit PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope);
 
   nsIGlobalObject*
   GetParentObject() const
   {
     return mGlobal;
   }
 
--- a/dom/webidl/PushEvent.webidl
+++ b/dom/webidl/PushEvent.webidl
@@ -2,18 +2,20 @@
 /* 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/.
  *
  * The origin of this IDL file is
  * https://w3c.github.io/push-api/
  */
 
-[Constructor(DOMString type, optional PushEventInit eventInitDict), Exposed=ServiceWorker]
+[Constructor(DOMString type, optional PushEventInit eventInitDict),
+ Func="nsContentUtils::PushEnabled",
+ Exposed=ServiceWorker]
 interface PushEvent : ExtendableEvent {
   readonly attribute PushMessageData data;
 };
 
 typedef USVString PushMessageDataInit;
 
 dictionary PushEventInit : ExtendableEventInit {
   PushMessageDataInit data;
-};
\ No newline at end of file
+};
--- a/dom/webidl/PushManager.webidl
+++ b/dom/webidl/PushManager.webidl
@@ -17,17 +17,17 @@ interface PushManagerImpl {
     Promise<PushPermissionState> permissionState();
 
     // We need a setter in the bindings so that the C++ can use it,
     // but we don't want it exposed to client JS.  WebPushMethodHider
     // always returns false.
     [Func="ServiceWorkerRegistration::WebPushMethodHider"] void setScope(DOMString scope);
 };
 
-[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"]
+[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
 interface PushManager {
   [ChromeOnly, Throws, Exposed=Window]
   void setPushManagerImpl(PushManagerImpl store);
 
   [Throws]
   Promise<PushSubscription>     subscribe();
   [Throws]
   Promise<PushSubscription?>    getSubscription();
--- a/dom/webidl/PushMessageData.webidl
+++ b/dom/webidl/PushMessageData.webidl
@@ -2,17 +2,18 @@
 /* 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/.
  *
  * The origin of this IDL file is
  * https://w3c.github.io/push-api/
  */
 
-[Exposed=ServiceWorker]
+[Func="nsContentUtils::PushEnabled",
+ Exposed=ServiceWorker]
 interface PushMessageData
 {
     // FIXME(nsm): Bug 1149195.
     // These methods will be exposed once encryption is supported.
     // ArrayBuffer arrayBuffer();
     // Blob        blob();
     // object      json();
     // USVString   text();
--- a/dom/webidl/PushSubscription.webidl
+++ b/dom/webidl/PushSubscription.webidl
@@ -4,17 +4,17 @@
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * The origin of this IDL file is
 * https://w3c.github.io/push-api/
 */
 
 interface Principal;
 
-[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled",
+[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",
  ChromeConstructor(DOMString pushEndpoint, DOMString scope)]
 interface PushSubscription
 {
     readonly attribute USVString endpoint;
     [Throws]
     Promise<boolean> unsubscribe();
     jsonifier;
 
--- a/dom/webidl/ServiceWorkerRegistration.webidl
+++ b/dom/webidl/ServiceWorkerRegistration.webidl
@@ -23,12 +23,12 @@ interface ServiceWorkerRegistration : Ev
   Promise<boolean> unregister();
 
   // event
   attribute EventHandler onupdatefound;
 };
 
 partial interface ServiceWorkerRegistration {
 #ifndef MOZ_SIMPLEPUSH
-  [Throws, Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"]
+  [Throws, Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
   readonly attribute PushManager pushManager;
 #endif
 };
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -161,16 +161,17 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 
 #define PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED "dom.performance.enable_user_timing_logging"
 #define PREF_DOM_WORKERNOTIFICATION_ENABLED  "dom.webnotifications.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_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
 #define PREF_INTERCEPTION_ENABLED      "dom.serviceWorkers.interception.enabled"
 #define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
+#define PREF_PUSH_ENABLED              "dom.push.enabled"
 
 namespace {
 
 const uint32_t kNoIndex = uint32_t(-1);
 
 const JS::ContextOptions kRequiredContextOptions =
   JS::ContextOptions().setDontReportUncaught(true);
 
@@ -1944,16 +1945,20 @@ RuntimeService::Init()
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_PERFORMANCE_LOGGING_ENABLED))) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_SERVICEWORKERS_TESTING_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS_TESTING))) ||
+      NS_FAILED(Preferences::RegisterCallbackAndCall(
+                                  WorkerPrefChanged,
+                                  PREF_PUSH_ENABLED,
+                                  reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
       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,
@@ -2171,16 +2176,20 @@ RuntimeService::Cleanup()
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_DOM_CACHES_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_DOM_WORKERNOTIFICATION_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DOM_WORKERNOTIFICATION))) ||
+        NS_FAILED(Preferences::UnregisterCallback(
+                                  WorkerPrefChanged,
+                                  PREF_PUSH_ENABLED,
+                                  reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
 #if DUMP_CONTROLLED_BY_PREF
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_DOM_WINDOW_DUMP_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
 #endif
 #ifdef JS_GC_ZEAL
         NS_FAILED(Preferences::UnregisterCallback(
@@ -2720,16 +2729,17 @@ RuntimeService::WorkerPrefChanged(const 
     case WORKERPREF_PERFORMANCE_LOGGING_ENABLED:
 #ifdef DUMP_CONTROLLED_BY_PREF
     case WORKERPREF_DUMP:
 #endif
     case WORKERPREF_INTERCEPTION_ENABLED:
     case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
     case WORKERPREF_SERVICEWORKERS:
     case WORKERPREF_SERVICEWORKERS_TESTING:
+    case WORKERPREF_PUSH:
       sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);
       break;
 
     default:
       MOZ_ASSERT_UNREACHABLE("Invalid pref key");
       break;
   }
 
--- a/dom/workers/ServiceWorkerEvents.h
+++ b/dom/workers/ServiceWorkerEvents.h
@@ -15,16 +15,17 @@
 #include "mozilla/dom/workers/bindings/ServiceWorker.h"
 
 #ifndef MOZ_SIMPLEPUSH
 #include "mozilla/dom/PushEventBinding.h"
 #include "mozilla/dom/PushMessageDataBinding.h"
 #endif
 
 #include "nsProxyRelease.h"
+#include "nsContentUtils.h"
 
 class nsIInterceptedChannel;
 
 namespace mozilla {
 namespace dom {
 class Blob;
 class Request;
 class ResponseOrPromise;
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1324,16 +1324,23 @@ public:
   bool
   PerformanceLoggingEnabled() const
   {
     AssertIsOnWorkerThread();
     return mPreferences[WORKERPREF_PERFORMANCE_LOGGING_ENABLED];
   }
 
   bool
+  PushEnabled() const
+  {
+    AssertIsOnWorkerThread();
+    return mPreferences[WORKERPREF_PUSH];
+  }
+
+  bool
   OnLine() const
   {
     AssertIsOnWorkerThread();
     return mOnLine;
   }
 
   void
   StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -201,16 +201,17 @@ enum WorkerPreference
   WORKERPREF_DOM_CACHES, // dom.caches.enabled
   WORKERPREF_SERVICEWORKERS, // dom.serviceWorkers.enabled
   WORKERPREF_INTERCEPTION_ENABLED, // dom.serviceWorkers.interception.enabled
   WORKERPREF_DOM_WORKERNOTIFICATION, // dom.webnotifications.workers.enabled
   WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled
   WORKERPREF_SERVICEWORKERS_TESTING, // dom.serviceWorkers.testing.enabled
   WORKERPREF_INTERCEPTION_OPAQUE_ENABLED, // dom.serviceWorkers.interception.opaque.enabled
   WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
+  WORKERPREF_PUSH, // dom.push.enabled
   WORKERPREF_COUNT
 };
 
 // Implemented in WorkerPrivate.cpp
 
 struct WorkerLoadInfo
 {
   // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -43,18 +43,16 @@ var ecmaGlobals =
     "Iterator",
     "JSON",
     "Map",
     "Math",
     "NaN",
     "Number",
     "Object",
     "Proxy",
-    "PushEvent",
-    "PushMessageData",
     "RangeError",
     "ReferenceError",
     "Reflect",
     "RegExp",
     "Set",
     {name: "SharedArrayBuffer", nightly: true},
     {name: "SharedInt8Array", nightly: true},
     {name: "SharedUint8Array", nightly: true},
@@ -169,19 +167,23 @@ var interfaceNamesInGlobalScope =
     "PerformanceEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Promise",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushManager",
+    { name: "PushEvent", b2g: false, android: false, release: false },
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    { name: "PushManager", b2g: false, android: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushSubscription",
+    { name: "PushMessageData", b2g: false, android: false, release: false },
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    { name: "PushSubscription", b2g: false, android: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Request",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Response",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ServiceWorker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ServiceWorkerGlobalScope",
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -159,16 +159,20 @@ var interfaceNamesInGlobalScope =
     "PerformanceEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Promise",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    { name: "PushManager", b2g: false, android: false, release: false },
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    { name: "PushSubscription", b2g: false, android: false, release: false },
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Request",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Response",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "ServiceWorkerRegistration", release: false, b2g: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextDecoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4424,17 +4424,17 @@ pref("dom.sms.maxReadAheadEntries", 0);
 // WebContacts
 pref("dom.mozContacts.enabled", false);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", false);
 
 // Push
 
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
+#if !defined(MOZ_B2G) && !defined(ANDROID)
 // Desktop prefs
 #ifdef RELEASE_BUILD
 pref("dom.push.enabled", false);
 #else
 pref("dom.push.enabled", true);
 #endif
 #else
 // Mobile prefs