Bug 829030 - Accessing the desktop notification API in the browser and approving permission errors out - API does not work, r=sicking
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 14 Jan 2013 11:08:55 +0100
changeset 128625 7dce709a1a1d23633aece2809beb2302c0a9a2d0
parent 128624 5793475efa35689a35139dc424de4f68d6916192
child 128626 0b615d3bae9c26b1ec6faf48ee85942a0d752e3c
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs829030
milestone21.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 829030 - Accessing the desktop notification API in the browser and approving permission errors out - API does not work, r=sicking
b2g/chrome/content/shell.js
content/base/public/nsIMessageManager.idl
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
dom/ipc/AppProcessChecker.cpp
dom/ipc/AppProcessChecker.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -764,17 +764,17 @@ var AlertsHelper = {
                                                               alertListener,
                                                               name) {
     let uid = this.registerListener(null, alertListener);
     this.showNotification(imageUrl, title, text, textClickable, cookie,
                           uid, name, null);
   },
 
   receiveMessage: function alert_receiveMessage(aMessage) {
-    if (!aMessage.target.assertPermission("desktop-notification")) {
+    if (!aMessage.target.assertAppHasPermission("desktop-notification")) {
       Cu.reportError("Desktop-notification message " + aMessage.name +
                      " from a content process with no desktop-notification privileges.");
       return null;
     }
 
     let data = aMessage.data;
     let listener = {
       mm: aMessage.target,
--- a/content/base/public/nsIMessageManager.idl
+++ b/content/base/public/nsIMessageManager.idl
@@ -331,17 +331,17 @@ interface nsIFrameScriptLoader : nsISupp
   void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad);
 
   /**
    * Removes aURL from the list of scripts which support delayed load.
    */
   void removeDelayedFrameScript(in AString aURL);
 };
 
-[scriptable, builtinclass, uuid(e2ccdade-4c16-11e2-9ae0-23151c6d6e1d)]
+[scriptable, builtinclass, uuid(134ccbf0-5c08-11e2-bcfd-0800200c9a66)]
 interface nsIProcessChecker : nsISupports
 {
 
   /**
    * Return true iff the "remote" process has |aPermission|.  This is
    * intended to be used by JS implementations of cross-process DOM
    * APIs, like so
    *
@@ -377,9 +377,11 @@ interface nsIProcessChecker : nsISupport
    * then applying this manifest URL check doesn't add any security,
    * though it doesn't hurt anything either.
    *
    * Note: If the remote content process does *not* contain |aManifestURL|,
    * it will be killed as a precaution.
    */
   boolean assertContainApp(in DOMString aManifestURL);
 
+  boolean assertAppHasPermission(in DOMString aPermission);
+
 };
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -2296,16 +2296,23 @@ nsFrameLoader::CheckPermission(const nsA
 
 bool
 nsFrameLoader::CheckManifestURL(const nsAString& aManifestURL)
 {
   return AssertAppProcessManifestURL(GetRemoteBrowser(),
                                      NS_ConvertUTF16toUTF8(aManifestURL).get());
 }
 
+bool
+nsFrameLoader::CheckAppHasPermission(const nsAString& aPermission)
+{
+  return AssertAppHasPermission(GetRemoteBrowser(),
+                                NS_ConvertUTF16toUTF8(aPermission).get());
+}
+
 NS_IMETHODIMP
 nsFrameLoader::GetMessageManager(nsIMessageSender** aManager)
 {
   EnsureMessageManager();
   if (mMessageManager) {
     CallQueryInterface(mMessageManager, aManager);
   }
   return NS_OK;
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -185,16 +185,17 @@ public:
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoLoadFrameScript(const nsAString& aURL);
   virtual bool DoSendAsyncMessage(const nsAString& aMessage,
                                   const mozilla::dom::StructuredCloneData& aData);
   virtual bool CheckPermission(const nsAString& aPermission);
   virtual bool CheckManifestURL(const nsAString& aManifestURL);
+  virtual bool CheckAppHasPermission(const nsAString& aPermission);
 
   /**
    * Called from the layout frame associated with this frame loader;
    * this notifies us to hook up with the widget and view.
    */
   bool Show(int32_t marginWidth, int32_t marginHeight,
               int32_t scrollbarPrefX, int32_t scrollbarPrefY,
               nsSubDocumentFrame* frame);
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -441,16 +441,19 @@ nsFrameMessageManager::AssertProcessInte
   }
   switch (aType) {
     case PROCESS_CHECKER_PERMISSION:
       *aValid = mCallback->CheckPermission(aCapability);
       break;
     case PROCESS_CHECKER_MANIFEST_URL:
       *aValid = mCallback->CheckManifestURL(aCapability);
       break;
+    case ASSERT_APP_HAS_PERMISSION:
+      *aValid = mCallback->CheckAppHasPermission(aCapability);
+      break;
     default:
       break;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::AssertPermission(const nsAString& aPermission,
@@ -465,16 +468,25 @@ NS_IMETHODIMP
 nsFrameMessageManager::AssertContainApp(const nsAString& aManifestURL,
                                         bool* aHasManifestURL)
 {
   return AssertProcessInternal(PROCESS_CHECKER_MANIFEST_URL,
                                aManifestURL,
                                aHasManifestURL);
 }
 
+NS_IMETHODIMP
+nsFrameMessageManager::AssertAppHasPermission(const nsAString& aPermission,
+                                              bool* aHasPermission)
+{
+  return AssertProcessInternal(ASSERT_APP_HAS_PERMISSION,
+                               aPermission,
+                               aHasPermission);
+}
+
 class MMListenerRemover
 {
 public:
   MMListenerRemover(nsFrameMessageManager* aMM)
     : mWasHandlingMessage(aMM->mHandlingMessage)
     , mMM(aMM)
   {
     mMM->mHandlingMessage = true;
@@ -1129,16 +1141,22 @@ public:
     return true;
   }
 
   bool CheckManifestURL(const nsAString& aManifestURL)
   {
     // In a single-process scenario, the child always has all capabilities.
     return true;
   }
+
+  bool CheckAppHasPermission(const nsAString& aPermission)
+  {
+    // In a single-process scenario, the child always has all capabilities.
+    return true;
+  }
 };
 
 
 /**
  * Send messages to the parent process.
  */
 class ChildProcessMessageManagerCallback : public MessageManagerCallback
 {
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -66,16 +66,21 @@ public:
   {
     return false;
   }
 
   virtual bool CheckManifestURL(const nsAString& aManifestURL)
   {
     return false;
   }
+
+  virtual bool CheckAppHasPermission(const nsAString& aPermission)
+  {
+    return false;
+  }
 };
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
 
 class nsAXPCNativeCallContext;
 struct JSContext;
@@ -229,17 +234,18 @@ protected:
 public:
   static nsFrameMessageManager* sParentProcessManager;
   static nsFrameMessageManager* sChildProcessManager;
   static nsFrameMessageManager* sSameProcessParentManager;
   static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
 private:
   enum ProcessCheckerType {
     PROCESS_CHECKER_PERMISSION,
-    PROCESS_CHECKER_MANIFEST_URL
+    PROCESS_CHECKER_MANIFEST_URL,
+    ASSERT_APP_HAS_PERMISSION
   };
   nsresult AssertProcessInternal(ProcessCheckerType aType,
                                  const nsAString& aCapability,
                                  bool* aValid);
 };
 
 void
 ContentScriptErrorReporter(JSContext* aCx,
--- a/dom/ipc/AppProcessChecker.cpp
+++ b/dom/ipc/AppProcessChecker.cpp
@@ -30,18 +30,19 @@ AssertAppProcess(PBrowserParent* aActor,
 
   TabParent* tab = static_cast<TabParent*>(aActor);
   nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
   bool aValid = false;
 
   // isBrowser frames inherit their app descriptor to identify their
   // data storage, but they don't inherit the capability associated
   // with that descriptor.
-  if (app && !tab->IsBrowserElement()) {
+  if (app && (aType == ASSERT_APP_HAS_PERMISSION || !tab->IsBrowserElement())) {
     switch (aType) {
+      case ASSERT_APP_HAS_PERMISSION:
       case ASSERT_APP_PROCESS_PERMISSION:
         if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) {
           aValid = false;
         }
         break;
       case ASSERT_APP_PROCESS_MANIFEST_URL: {
         nsAutoString manifestURL;
         if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) &&
--- a/dom/ipc/AppProcessChecker.h
+++ b/dom/ipc/AppProcessChecker.h
@@ -16,17 +16,18 @@ class PContentParent;
 }
 
 namespace hal_sandbox {
 class PHalParent;
 }
 
 enum AssertAppProcessType {
   ASSERT_APP_PROCESS_PERMISSION,
-  ASSERT_APP_PROCESS_MANIFEST_URL
+  ASSERT_APP_PROCESS_MANIFEST_URL,
+  ASSERT_APP_HAS_PERMISSION
 };
 
 /**
  * Return true iff the specified browser has the specified capability.
  * If this returns false, the browser didn't have the capability and
  * will be killed.
  */
 bool
@@ -76,11 +77,23 @@ template<typename T>
 inline bool
 AssertAppProcessManifestURL(T* aActor,
                             const char* aManifestURL) {
   return AssertAppProcess(aActor,
                           ASSERT_APP_PROCESS_MANIFEST_URL,
                           aManifestURL);
 }
 
+/**
+ * Inline function for asserting the process's manifest URL.
+ */
+template<typename T>
+inline bool
+AssertAppHasPermission(T* aActor,
+                       const char* aPermission) {
+  return AssertAppProcess(aActor,
+                          ASSERT_APP_HAS_PERMISSION,
+                          aPermission);
+}
+
 } // namespace mozilla
 
 #endif // mozilla_AppProcessChecker_h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2329,10 +2329,16 @@ ContentParent::CheckPermission(const nsA
 }
 
 bool
 ContentParent::CheckManifestURL(const nsAString& aManifestURL)
 {
   return AssertAppProcessManifestURL(this, NS_ConvertUTF16toUTF8(aManifestURL).get());
 }
 
+bool
+ContentParent::CheckAppHasPermission(const nsAString& aPermission)
+{
+  return AssertAppHasPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -99,16 +99,17 @@ public:
 
     /**
      * MessageManagerCallback methods that we override.
      */
     virtual bool DoSendAsyncMessage(const nsAString& aMessage,
                                     const mozilla::dom::StructuredCloneData& aData);
     virtual bool CheckPermission(const nsAString& aPermission);
     virtual bool CheckManifestURL(const nsAString& aManifestURL);
+    virtual bool CheckAppHasPermission(const nsAString& aPermission);
 
     /** Notify that a tab is beginning its destruction sequence. */
     void NotifyTabDestroying(PBrowserParent* aTab);
     /** Notify that a tab was destroyed during normal operation. */
     void NotifyTabDestroyed(PBrowserParent* aTab,
                             bool aNotifiedDestroying);
 
     TestShellParent* CreateTestShell();