Bug 838146 part 2. Implement WebIDL API on Navigator for all our nonstandard extensions that are not behind build-time flags. r=smaug, sr=peterv
☠☠ backed out by 33fb417caccf ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 12 Jul 2013 10:35:44 -0400
changeset 150639 1bc7f216750320b2cfa936e9de6166f6dcc62d10
parent 150638 483fbc6878a8ecd493006eba4ef7ecfedc6a8e2a
child 150640 d3b135e58350b949872337e647b85bbc3290f88f
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, peterv
bugs838146
milestone25.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 838146 part 2. Implement WebIDL API on Navigator for all our nonstandard extensions that are not behind build-time flags. r=smaug, sr=peterv
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/bindings/Bindings.conf
dom/camera/DOMCameraManager.cpp
dom/camera/DOMCameraManager.h
dom/media/MediaManager.cpp
dom/mobilemessage/src/SmsManager.cpp
dom/mobilemessage/src/SmsManager.h
dom/webidl/Navigator.webidl
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1094,66 +1094,92 @@ NS_IMETHODIMP Navigator::GetDeviceStorag
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   if (!Preferences::GetBool("device.storage.enabled", false)) {
     return NS_OK;
   }
 
+  ErrorResult rv;
+  NS_IF_ADDREF(*_retval = GetDeviceStorage(aType, rv));
+  return rv.ErrorCode();
+}
+
+nsDOMDeviceStorage*
+Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the pref check here.
   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
 
   nsRefPtr<nsDOMDeviceStorage> storage;
   nsDOMDeviceStorage::CreateDeviceStorageFor(mWindow, aType,
                                              getter_AddRefs(storage));
 
   if (!storage) {
-    return NS_OK;
+    return nullptr;
   }
 
-  NS_ADDREF(*_retval = storage.get());
   mDeviceStorageStores.AppendElement(storage);
-  return NS_OK;
+  return storage;
 }
 
 NS_IMETHODIMP Navigator::GetDeviceStorages(const nsAString &aType, nsIVariant** _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   if (!Preferences::GetBool("device.storage.enabled", false)) {
     return NS_OK;
   }
 
-  if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
-    return NS_ERROR_FAILURE;
+  nsTArray<nsRefPtr<nsDOMDeviceStorage> > stores;
+  ErrorResult rv;
+  GetDeviceStorages(aType, stores, rv);
+  if (rv.Failed()) {
+    return rv.ErrorCode();
   }
 
-  nsTArray<nsRefPtr<nsDOMDeviceStorage> > stores;
-  nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, stores, false);
-
   nsCOMPtr<nsIWritableVariant> result = do_CreateInstance("@mozilla.org/variant;1");
   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
 
   if (stores.Length() == 0) {
     result->SetAsEmptyArray();
   } else {
     result->SetAsArray(nsIDataType::VTYPE_INTERFACE,
                        &NS_GET_IID(nsIDOMDeviceStorage),
                        stores.Length(),
                        const_cast<void*>(static_cast<const void*>(stores.Elements())));
   }
   result.forget(_retval);
 
-  mDeviceStorageStores.AppendElements(stores);
   return NS_OK;
 }
 
+void
+Navigator::GetDeviceStorages(const nsAString& aType,
+                             nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
+                             ErrorResult& aRv)
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the pref check here.
+  if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores, false);
+
+  mDeviceStorageStores.AppendElements(aStores);
+}
+
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorGeolocation
 //*****************************************************************************
 
 NS_IMETHODIMP Navigator::GetGeolocation(nsIDOMGeoGeolocation** _retval)
 {
   ErrorResult rv;
   NS_IF_ADDREF(*_retval = GetGeolocation(rv));
@@ -1236,30 +1262,35 @@ Navigator::MozGetUserMediaDevices(nsIGet
 #endif
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorDesktopNotification
 //*****************************************************************************
 
 NS_IMETHODIMP Navigator::GetMozNotification(nsISupports** aRetVal)
 {
-  NS_ENSURE_ARG_POINTER(aRetVal);
-  *aRetVal = nullptr;
+  ErrorResult rv;
+  NS_IF_ADDREF(*aRetVal = GetMozNotification(rv));
+  return rv.ErrorCode();
+}
 
+DesktopNotificationCenter*
+Navigator::GetMozNotification(ErrorResult& aRv)
+{
   if (mNotification) {
-    NS_ADDREF(*aRetVal = mNotification);
-    return NS_OK;
+    return mNotification;
   }
 
-  NS_ENSURE_TRUE(mWindow && mWindow->GetDocShell(), NS_ERROR_FAILURE);
+  if (!mWindow || !mWindow->GetDocShell()) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   mNotification = new DesktopNotificationCenter(mWindow);
-
-  NS_ADDREF(*aRetVal = mNotification);
-  return NS_OK;
+  return mNotification;
 }
 
 //*****************************************************************************
 //    Navigator::nsINavigatorBattery
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetBattery(nsISupports** aBattery)
@@ -1347,64 +1378,73 @@ Navigator::RequestWakeLock(const nsAStri
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorSms
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozSms(nsIDOMMozSmsManager** aSmsManager)
 {
-  *aSmsManager = nullptr;
-
   if (!mSmsManager) {
-    NS_ENSURE_STATE(mWindow);
-    NS_ENSURE_TRUE(mWindow->GetDocShell(), NS_OK);
-
-    mSmsManager = SmsManager::CreateInstanceIfAllowed(mWindow);
-    NS_ENSURE_TRUE(mSmsManager, NS_OK);
+    if (!mWindow || !SmsManager::CreationIsAllowed(mWindow)) {
+      *aSmsManager = nullptr;
+      return NS_OK;
+    }
   }
 
-  NS_ADDREF(*aSmsManager = mSmsManager);
+  NS_IF_ADDREF(*aSmsManager = GetMozSms());
+  return NS_OK;
+}
 
-  return NS_OK;
+nsIDOMMozSmsManager*
+Navigator::GetMozSms()
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the permission check here.
+  if (!mSmsManager) {
+    NS_ENSURE_TRUE(mWindow, nullptr);
+    NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
+
+    mSmsManager = SmsManager::CreateInstance(mWindow);
+  }
+
+  return mSmsManager;
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorMobileMessage
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozMobileMessage(nsIDOMMozMobileMessageManager** aMobileMessageManager)
 {
-  *aMobileMessageManager = nullptr;
+  if (!HasMobileMessageSupport(mWindow)) {
+    *aMobileMessageManager = nullptr;
+    return NS_OK;
+  }
 
-#ifndef MOZ_WEBSMS_BACKEND
+  NS_IF_ADDREF(*aMobileMessageManager = GetMozMobileMessage());
   return NS_OK;
-#endif
+}
 
-  // First of all, the general pref has to be turned on.
-  bool enabled = false;
-  Preferences::GetBool("dom.sms.enabled", &enabled);
-  NS_ENSURE_TRUE(enabled, NS_OK);
-
+nsIDOMMozMobileMessageManager*
+Navigator::GetMozMobileMessage()
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the permission check here.
   if (!mMobileMessageManager) {
-    NS_ENSURE_STATE(mWindow);
-    NS_ENSURE_TRUE(mWindow->GetDocShell(), NS_OK);
-
-    if (!CheckPermission("sms")) {
-      return NS_OK;
-    }
+    // Check that our window has not gone away
+    NS_ENSURE_TRUE(mWindow, nullptr);
+    NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
 
     mMobileMessageManager = new MobileMessageManager();
     mMobileMessageManager->Init(mWindow);
   }
 
-  NS_ADDREF(*aMobileMessageManager = mMobileMessageManager);
-
-  return NS_OK;
+  return mMobileMessageManager;
 }
 
 #ifdef MOZ_B2G_RIL
 
 //*****************************************************************************
 //    Navigator::nsIMozNavigatorCellBroadcast
 //*****************************************************************************
 
@@ -1538,28 +1578,32 @@ Navigator::GetGamepads(nsIVariant** aRet
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorNetwork
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozConnection(nsIDOMMozConnection** aConnection)
 {
-  *aConnection = nullptr;
+  NS_IF_ADDREF(*aConnection = GetMozConnection());
+  return NS_OK;
+}
 
+nsIDOMMozConnection*
+Navigator::GetMozConnection()
+{
   if (!mConnection) {
-    NS_ENSURE_STATE(mWindow);
-    NS_ENSURE_TRUE(mWindow->GetDocShell(), NS_OK);
+    NS_ENSURE_TRUE(mWindow, nullptr);
+    NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
 
     mConnection = new network::Connection();
     mConnection->Init(mWindow);
   }
 
-  NS_ADDREF(*aConnection = mConnection);
-  return NS_OK;
+  return mConnection;
 }
 
 #ifdef MOZ_B2G_RIL
 //*****************************************************************************
 //    Navigator::nsINavigatorMobileConnection
 //*****************************************************************************
 NS_IMETHODIMP
 Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection)
@@ -1638,37 +1682,76 @@ Navigator::EnsureMessagesManager()
 
 NS_IMETHODIMP
 Navigator::MozHasPendingMessage(const nsAString& aType, bool *aResult)
 {
   if (!Preferences::GetBool("dom.sysmsg.enabled", false)) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  *aResult = false;
+  ErrorResult rv;
+  *aResult = MozHasPendingMessage(aType, rv);
+  return rv.ErrorCode();
+}
+
+bool
+Navigator::MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv)
+{
+  // The WebIDL binding is responsible for the pref check here.
   nsresult rv = EnsureMessagesManager();
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return false;
+  }
 
-  return mMessagesManager->MozHasPendingMessage(aType, aResult);
+  bool result = false;
+  rv = mMessagesManager->MozHasPendingMessage(aType, &result);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return false;
+  }
+  return result;
 }
 
 NS_IMETHODIMP
 Navigator::MozSetMessageHandler(const nsAString& aType,
                                 nsIDOMSystemMessageCallback *aCallback)
 {
   if (!Preferences::GetBool("dom.sysmsg.enabled", false)) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsresult rv = EnsureMessagesManager();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return mMessagesManager->MozSetMessageHandler(aType, aCallback);
 }
 
+void
+Navigator::MozSetMessageHandler(const nsAString& aType,
+                                systemMessageCallback* aCallback,
+                                ErrorResult& aRv)
+{
+  // The WebIDL binding is responsible for the pref check here.
+  nsresult rv = EnsureMessagesManager();
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  CallbackObjectHolder<systemMessageCallback, nsIDOMSystemMessageCallback>
+    holder(aCallback);
+  nsCOMPtr<nsIDOMSystemMessageCallback> callback = holder.ToXPCOMCallback();
+
+  rv = mMessagesManager->MozSetMessageHandler(aType, callback);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+}
+
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorTime
 //*****************************************************************************
 #ifdef MOZ_TIME_MANAGER
 NS_IMETHODIMP
 Navigator::GetMozTime(nsISupports** aTime)
 {
   *aTime = nullptr;
@@ -1690,31 +1773,45 @@ Navigator::GetMozTime(nsISupports** aTim
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorCamera
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozCameras(nsISupports** aCameraManager)
 {
   if (!mCameraManager) {
+    NS_ENSURE_STATE(mWindow);
+    if (!nsDOMCameraManager::CheckPermission(mWindow)) {
+      *aCameraManager = nullptr;
+      return NS_OK;
+    }
+  }
+
+  ErrorResult rv;
+  NS_IF_ADDREF(*aCameraManager = static_cast<nsIObserver*>(GetMozCameras(rv)));
+  return rv.ErrorCode();
+}
+
+nsDOMCameraManager*
+Navigator::GetMozCameras(ErrorResult& aRv)
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the permission check here.
+  if (!mCameraManager) {
     if (!mWindow ||
         !mWindow->GetOuterWindow() ||
         mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
-      return NS_ERROR_NOT_AVAILABLE;
+      aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+      return nullptr;
     }
 
-    mCameraManager =
-      nsDOMCameraManager::CheckPermissionAndCreateInstance(mWindow);
-    NS_ENSURE_TRUE(mCameraManager, NS_OK);
+    mCameraManager = nsDOMCameraManager::CreateInstance(mWindow);
   }
 
-  nsCOMPtr<nsIObserver> cameraManager = mCameraManager.get();
-  cameraManager.forget(aCameraManager);
-
-  return NS_OK;
+  return mCameraManager;
 }
 
 size_t
 Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
@@ -1828,16 +1925,63 @@ Navigator::HasWakeLockSupport(JSContext*
 {
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   // No service means no wake lock support
   return !!pmService;
 }
 
 /* static */
+bool
+Navigator::HasSmsSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return win && SmsManager::CreationIsAllowed(win);
+}
+
+/* static */
+bool
+Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return HasMobileMessageSupport(win);
+}
+
+/* static */
+bool
+Navigator::HasMobileMessageSupport(nsPIDOMWindow* aWindow)
+{
+#ifndef MOZ_WEBSMS_BACKEND
+  return false;
+#endif
+
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.sms.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
+  NS_ENSURE_TRUE(aWindow, false);
+  NS_ENSURE_TRUE(aWindow->GetDocShell(), false);
+
+  if (!CheckPermission(aWindow, "sms")) {
+    return false;
+  }
+
+  return true;
+}
+
+/* static */
+bool
+Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return win && nsDOMCameraManager::CheckPermission(win);
+}
+
+/* static */
 already_AddRefed<nsPIDOMWindow>
 Navigator::GetWindowFromGlobal(JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindow> win =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
   MOZ_ASSERT(!win || win->IsInnerWindow());
   return win.forget();
 }
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -35,16 +35,17 @@
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsPIDOMWindow;
 class nsIDOMMozConnection;
 
 namespace mozilla {
 namespace dom {
 class Geolocation;
+class systemMessageCallback;
 }
 }
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "nsIDOMNavigatorUserMedia.h"
 #endif
 
 #ifdef MOZ_B2G_RIL
@@ -279,30 +280,63 @@ public:
   bool TaintEnabled()
   {
     return false;
   }
   void AddIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
   void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
   already_AddRefed<nsIDOMMozWakeLock> RequestWakeLock(const nsAString &aTopic,
                                                       ErrorResult& aRv);
+  nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
+                                       ErrorResult& aRv);
+  void GetDeviceStorages(const nsAString& aType,
+                         nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
+                         ErrorResult& aRv);
+  DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
+  bool MozIsLocallyAvailable(const nsAString& aURI, bool aWhenOffline,
+                             ErrorResult& aRv)
+  {
+    bool available = false;
+    aRv = MozIsLocallyAvailable(aURI, aWhenOffline, &available);
+    return available;
+  }
+  nsIDOMMozSmsManager* GetMozSms();
+  nsIDOMMozMobileMessageManager* GetMozMobileMessage();
+  nsIDOMMozConnection* GetMozConnection();
+  nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
+  void MozSetMessageHandler(const nsAString& aType,
+                            systemMessageCallback* aCallback,
+                            ErrorResult& aRv);
+  bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
+
 
   // WebIDL helper methods
   static bool HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */);
   static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
+  static bool HasDesktopNotificationSupport(JSContext* /* unused*/,
+                                            JSObject* /*unused */)
+  {
+    return HasDesktopNotificationSupport();
+  }
+  static bool HasSmsSupport(JSContext* /* unused */, JSObject* aGlobal);
+  static bool HasMobileMessageSupport(JSContext* /* unused */,
+                                      JSObject* aGlobal);
+  static bool HasCameraSupport(JSContext* /* unused */,
+                               JSObject* aGlobal);
   nsPIDOMWindow* GetParentObject() const
   {
     return GetWindow();
   }
 
 private:
   bool CheckPermission(const char* type);
   static bool CheckPermission(nsPIDOMWindow* aWindow, const char* aType);
+  static bool HasMobileMessageSupport(nsPIDOMWindow* aWindow);
   // GetWindowFromGlobal returns the inner window for this global, if
   // any, else null.
   static already_AddRefed<nsPIDOMWindow> GetWindowFromGlobal(JSObject* aGlobal);
 
   // Methods to common up the XPCOM and WebIDL implementations of
   // Add/RemoveIdleObserver.
   void AddIdleObserver(nsIIdleObserver& aIdleObserver);
   void RemoveIdleObserver(nsIIdleObserver& aIdleObserver);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1702,23 +1702,26 @@ addExternalIface('HitRegionOptions', nat
 addExternalIface('IDBDatabase', nativeType='nsIIDBDatabase')
 addExternalIface('IDBOpenDBRequest', nativeType='nsIIDBOpenDBRequest')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
 addExternalIface('MediaList')
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
+addExternalIface('MozConnection', headerFile='nsIDOMConnection.h')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
+addExternalIface('MozMobileMessageManager', headerFile='nsIDOMMobileMessageManager.h')
 addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
 addExternalIface('MozPowerManager', headerFile='nsIDOMPowerManager.h')
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
+addExternalIface('MozSmsManager', headerFile='nsIDOMSmsManager.h')
 addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject',
                  notflattened=True)
 addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',
                  headerFile='nsITreeColumns.h')
 addExternalIface('MozWakeLock', headerFile='nsIDOMWakeLock.h')
 addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
 addExternalIface('nsIControllers', nativeType='nsIControllers')
 addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -66,31 +66,37 @@ nsDOMCameraManager::nsDOMCameraManager(n
 nsDOMCameraManager::~nsDOMCameraManager()
 {
   /* destructor code */
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   obs->RemoveObserver(this, "xpcom-shutdown");
 }
 
-// static creator
-already_AddRefed<nsDOMCameraManager>
-nsDOMCameraManager::CheckPermissionAndCreateInstance(nsPIDOMWindow* aWindow)
+bool
+nsDOMCameraManager::CheckPermission(nsPIDOMWindow* aWindow)
 {
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, nullptr);
+  NS_ENSURE_TRUE(permMgr, false);
 
   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   permMgr->TestPermissionFromWindow(aWindow, "camera", &permission);
   if (permission != nsIPermissionManager::ALLOW_ACTION) {
     NS_WARNING("No permission to access camera");
-    return nullptr;
+    return false;
   }
 
+  return true;
+}
+
+// static creator
+already_AddRefed<nsDOMCameraManager>
+nsDOMCameraManager::CreateInstance(nsPIDOMWindow* aWindow)
+{
   // Initialize the shared active window tracker
   if (!sActiveWindowsInitialized) {
     sActiveWindows.Init();
     sActiveWindowsInitialized = true;
   }
 
   nsRefPtr<nsDOMCameraManager> cameraManager =
     new nsDOMCameraManager(aWindow);
--- a/dom/camera/DOMCameraManager.h
+++ b/dom/camera/DOMCameraManager.h
@@ -40,18 +40,19 @@ class nsDOMCameraManager MOZ_FINAL
   , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDOMCameraManager,
                                                          nsIObserver)
   NS_DECL_NSIOBSERVER
 
+  static bool CheckPermission(nsPIDOMWindow* aWindow);
   static already_AddRefed<nsDOMCameraManager>
-    CheckPermissionAndCreateInstance(nsPIDOMWindow* aWindow);
+    CreateInstance(nsPIDOMWindow* aWindow);
   static bool IsWindowStillActive(uint64_t aWindowId);
 
   void Register(mozilla::nsDOMCameraControl* aDOMCameraControl);
   void OnNavigation(uint64_t aWindowId);
 
   nsresult GetNumberOfCameras(int32_t& aDeviceCount);
   nsresult GetCameraName(uint32_t aDeviceNum, nsCString& aDeviceName);
 
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1090,19 +1090,19 @@ MediaManager::GetUserMedia(bool aPrivile
     // Stream from default device from WebRTC backend.
     gUMRunnable = new GetUserMediaRunnable(
       audio, video, picture, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs
                                            );
   }
 
 #ifdef MOZ_B2G_CAMERA
   if (mCameraManager == nullptr) {
-    mCameraManager = nsDOMCameraManager::CheckPermissionAndCreateInstance(aWindow);
-    if (!mCameraManager) {
-      aPrivileged = false;
+    aPrivileged = nsDOMCameraManager::CheckPermission(aWindow);
+    if (aPrivileged) {
+      mCameraManager = nsDOMCameraManager::CreateInstance(aWindow);
     }
   }
 #endif
 
 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
   if (picture) {
     // ShowFilePickerForMimeType() must run on the Main Thread! (on Android)
     NS_DispatchToMainThread(gUMRunnable);
--- a/dom/mobilemessage/src/SmsManager.cpp
+++ b/dom/mobilemessage/src/SmsManager.cpp
@@ -49,51 +49,59 @@ NS_IMPL_RELEASE_INHERITED(SmsManager, ns
 
 NS_IMPL_EVENT_HANDLER(SmsManager, received)
 NS_IMPL_EVENT_HANDLER(SmsManager, sending)
 NS_IMPL_EVENT_HANDLER(SmsManager, sent)
 NS_IMPL_EVENT_HANDLER(SmsManager, failed)
 NS_IMPL_EVENT_HANDLER(SmsManager, deliverysuccess)
 NS_IMPL_EVENT_HANDLER(SmsManager, deliveryerror)
 
-/* static */already_AddRefed<SmsManager>
-SmsManager::CreateInstanceIfAllowed(nsPIDOMWindow* aWindow)
+/* static */
+bool
+SmsManager::CreationIsAllowed(nsPIDOMWindow* aWindow)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
 #ifndef MOZ_WEBSMS_BACKEND
-  return nullptr;
+  return false;
 #endif
 
   // First of all, the general pref has to be turned on.
   bool enabled = false;
   Preferences::GetBool("dom.sms.enabled", &enabled);
-  NS_ENSURE_TRUE(enabled, nullptr);
+  NS_ENSURE_TRUE(enabled, false);
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, nullptr);
+  NS_ENSURE_TRUE(permMgr, false);
 
   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   permMgr->TestPermissionFromWindow(aWindow, "sms", &permission);
 
   if (permission != nsIPermissionManager::ALLOW_ACTION) {
-    return nullptr;
+    return false;
   }
 
   // Check the Sms Service:
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(smsService, nullptr);
+  NS_ENSURE_TRUE(smsService, false);
 
   bool result = false;
   smsService->HasSupport(&result);
   if (!result) {
-    return nullptr;
+    return false;
   }
 
+  return true;
+}
+
+// static
+already_AddRefed<SmsManager>
+SmsManager::CreateInstance(nsPIDOMWindow* aWindow)
+{
   nsRefPtr<SmsManager> smsMgr = new SmsManager();
   smsMgr->Init(aWindow);
 
   return smsMgr.forget();
 }
 
 void
 SmsManager::Init(nsPIDOMWindow *aWindow)
--- a/dom/mobilemessage/src/SmsManager.h
+++ b/dom/mobilemessage/src/SmsManager.h
@@ -22,17 +22,20 @@ class SmsManager : public nsDOMEventTarg
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMMOZSMSMANAGER
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
 
   static already_AddRefed<SmsManager>
-  CreateInstanceIfAllowed(nsPIDOMWindow *aWindow);
+  CreateInstance(nsPIDOMWindow *aWindow);
+
+  static bool
+  CreationIsAllowed(nsPIDOMWindow *aWindow);
 
   void Init(nsPIDOMWindow *aWindow);
   void Shutdown();
 
 private:
   /**
    * Internal Send() method used to send one message.
    */
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -4,16 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
  * http://www.w3.org/TR/tracking-dnt/
  * http://www.w3.org/TR/geolocation-API/#geolocation_interface
  * http://www.w3.org/TR/battery-status/#navigatorbattery-interface
  * http://www.w3.org/TR/vibration/#vibration-interface
+ * http://www.w3.org/2012/sysapps/runtime/#extension-to-the-navigator-interface-1
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface MozPowerManager;
 interface MozWakeLock;
@@ -197,8 +198,64 @@ partial interface Navigator {
    * unlock the lock via the object's |unlock| method.  The lock is released
    * automatically when its associated window is unloaded.
    *
    * @param aTopic resource name
    */
   [Throws, Func="Navigator::HasWakeLockSupport"]
   MozWakeLock requestWakeLock(DOMString aTopic);
 };
+
+// nsIDOMNavigatorDeviceStorage
+partial interface Navigator {
+  [Throws, Pref="device.storage.enabled"]
+  DeviceStorage? getDeviceStorage(DOMString type);
+  [Throws, Pref="device.storage.enabled"]
+  sequence<DeviceStorage> getDeviceStorages(DOMString type);
+};
+
+// nsIDOMNavigatorDesktopNotification
+partial interface Navigator {
+  [Throws, Func="Navigator::HasDesktopNotificationSupport"]
+  readonly attribute DesktopNotificationCenter mozNotification;
+};
+
+// nsIDOMClientInformation
+partial interface Navigator {
+  [Throws]
+  boolean mozIsLocallyAvailable(DOMString uri, boolean whenOffline);
+};
+
+// nsIDOMMozNavigatorSms
+interface MozSmsManager;
+partial interface Navigator {
+  [Func="Navigator::HasSmsSupport"]
+  readonly attribute MozSmsManager? mozSms;
+};
+
+// nsIDOMMozNavigatorMobileMessage
+interface MozMobileMessageManager;
+partial interface Navigator {
+  [Func="Navigator::HasMobileMessageSupport"]
+  readonly attribute MozMobileMessageManager? mozMobileMessage;
+};
+
+// nsIDOMMozNavigatorNetwork
+interface MozConnection;
+partial interface Navigator {
+  readonly attribute MozConnection? mozConnection;
+};
+
+// nsIDOMNavigatorCamera
+partial interface Navigator {
+  [Throws, Func="Navigator::HasCameraSupport"]
+  readonly attribute CameraManager mozCameras;
+};
+
+// nsIDOMNavigatorSystemMessages and sort of maybe
+// http://www.w3.org/2012/sysapps/runtime/#extension-to-the-navigator-interface-1
+callback systemMessageCallback = void (optional object message);
+partial interface Navigator {
+  [Throws, Pref="dom.sysmsg.enabled"]
+  void    mozSetMessageHandler (DOMString type, systemMessageCallback? callback);
+  [Throws, Pref="dom.sysmsg.enabled"]
+  boolean mozHasPendingMessage (DOMString type);
+};