Bug 782456, part 2: Inherit privileges in apps that have permissions that require them. Sigh. r=jlebar
authorChris Jones <jones.chris.g@gmail.com>
Wed, 29 Aug 2012 09:24:48 -0300
changeset 105798 dd12dcbb264b3598f1e3673394e054882b08785b
parent 105797 8f22c4560de7c61a4e72c71cbefcce8c989aa349
child 105799 b0a07b59d5d250c507b1c34e7101b6ed65e39f66
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersjlebar
bugs782456
milestone18.0a1
Bug 782456, part 2: Inherit privileges in apps that have permissions that require them. Sigh. r=jlebar
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -184,17 +184,18 @@ ContentParent::PreallocateAppProcess()
     if (sPreallocateAppProcessTask) {
         // We were called directly while a delayed task was scheduled.
         sPreallocateAppProcessTask->Cancel();
         sPreallocateAppProcessTask = nullptr;
     }
 
     sPreallocatedAppProcess =
         new ContentParent(MAGIC_PREALLOCATED_APP_MANIFEST_URL,
-                          /*isBrowserElement=*/false);
+                          /*isBrowserElement=*/false,
+                          base::PRIVILEGES_DEFAULT);
     sPreallocatedAppProcess->Init();
 }
 
 /*static*/ void
 ContentParent::DelayedPreallocateAppProcess()
 {
     sPreallocateAppProcessTask = nullptr;
     if (!sPreallocatedAppProcess) {
@@ -270,16 +271,29 @@ ContentParent::GetNewOrUsed(bool aForBro
     nsRefPtr<ContentParent> p =
         new ContentParent(/* appManifestURL = */ EmptyString(),
                           aForBrowserElement);
     p->Init();
     gNonAppContentParents->AppendElement(p);
     return p;
 }
 
+static bool
+AppNeedsInheritedOSPrivileges(mozIApplication* aApp)
+{
+    bool needsInherit = false;
+    // FIXME/bug 785592: implement a CameraBridge so we don't have to
+    // hack around with OS permissions
+    if (NS_FAILED(aApp->HasPermission("camera", &needsInherit))) {
+        NS_WARNING("Unable to check permissions.  Breakage may follow.");
+        return false;
+    }
+    return needsInherit;
+}
+
 /*static*/ TabParent*
 ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
 {
     // We currently don't set the <app> ancestor for <browser> content
     // correctly.  This assertion is to notify the person who fixes
     // this code that they need to reevaluate places here where we may
     // make bad assumptions based on that bug.
     MOZ_ASSERT(!aApp || !aIsBrowserElement);
@@ -321,23 +335,30 @@ ContentParent::CreateBrowser(mozIApplica
     uint32_t appId;
     if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
         NS_ERROR("Failed to get local app ID");
         return nullptr;
     }
 
     nsRefPtr<ContentParent> p = gAppContentParents->Get(manifestURL);
     if (!p) {
-        p = MaybeTakePreallocatedAppProcess();
-        if (p) {
-            p->SetManifestFromPreallocated(manifestURL);
+        if (AppNeedsInheritedOSPrivileges(aApp)) {
+            p = new ContentParent(manifestURL, aIsBrowserElement,
+                                  base::PRIVILEGES_INHERIT);
+            p->Init();
         } else {
-            NS_WARNING("Unable to use pre-allocated app process");
-            p = new ContentParent(manifestURL, aIsBrowserElement);
-            p->Init();
+            p = MaybeTakePreallocatedAppProcess();
+            if (p) {
+                p->SetManifestFromPreallocated(manifestURL);
+            } else {
+                NS_WARNING("Unable to use pre-allocated app process");
+                p = new ContentParent(manifestURL, aIsBrowserElement,
+                                      base::PRIVILEGES_DEFAULT);
+                p->Init();
+            }
         }
         gAppContentParents->Put(manifestURL, p);
     }
 
     nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
     return static_cast<TabParent*>(
         // DeallocPBrowserParent() releases the ref we take here
         p->SendPBrowserConstructor(tp.forget().get(),
@@ -653,30 +674,34 @@ TestShellParent*
 ContentParent::GetTestShellSingleton()
 {
     if (!ManagedPTestShellParent().Length())
         return nullptr;
     return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
 }
 
 ContentParent::ContentParent(const nsAString& aAppManifestURL,
-                             bool aIsForBrowser)
-    : mGeolocationWatchID(-1)
+                             bool aIsForBrowser,
+                             ChildOSPrivileges aOSPrivileges)
+    : mSubprocess(nullptr)
+    , mOSPrivileges(aOSPrivileges)
+    , mGeolocationWatchID(-1)
     , mRunToCompletionDepth(0)
     , mShouldCallUnblockChild(false)
     , mIsAlive(true)
     , mSendPermissionUpdates(false)
     , mAppManifestURL(aAppManifestURL)
 {
     // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
     // PID along with the warning.
     nsDebugImpl::SetMultiprocessMode("Parent");
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-    mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
+    mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content,
+                                            aOSPrivileges);
 
     bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
     if (useOffMainThreadCompositing) {
         // We need the subprocess's ProcessHandle to create the
         // PCompositor channel below.  Block just until we have that.
         mSubprocess->LaunchAndWaitForProcessHandle();
     } else {
         mSubprocess->AsyncLaunch();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -112,31 +112,34 @@ public:
 
     BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
 protected:
     void OnChannelConnected(int32 pid);
     virtual void ActorDestroy(ActorDestroyReason why);
 
 private:
+    typedef base::ChildPrivileges ChildOSPrivileges;
+
     static nsDataHashtable<nsStringHashKey, ContentParent*> *gAppContentParents;
     static nsTArray<ContentParent*>* gNonAppContentParents;
     static nsTArray<ContentParent*>* gPrivateContent;
 
     static void PreallocateAppProcess();
     static void DelayedPreallocateAppProcess();
     static void ScheduleDelayedPreallocateAppProcess();
     static already_AddRefed<ContentParent> MaybeTakePreallocatedAppProcess();
 
     // Hide the raw constructor methods since we don't want client code
     // using them.
     using PContentParent::SendPBrowserConstructor;
     using PContentParent::SendPTestShellConstructor;
 
-    ContentParent(const nsAString& aAppManifestURL, bool aIsForBrowser);
+    ContentParent(const nsAString& aAppManifestURL, bool aIsForBrowser,
+                  ChildOSPrivileges aOSPrivileges = base::PRIVILEGES_DEFAULT);
     virtual ~ContentParent();
 
     void Init();
 
     // Transform a pre-allocated app process into a "real" app
     // process, for the specified manifest URL.
     void SetManifestFromPreallocated(const nsAString& aAppManifestURL);
 
@@ -277,16 +280,17 @@ private:
                                  const uint32_t& aFlags,
                                  const nsCString& aCategory);
 
     virtual bool RecvPrivateDocShellsExist(const bool& aExist);
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     GeckoChildProcessHost* mSubprocess;
+    ChildOSPrivileges mOSPrivileges;
 
     int32_t mGeolocationWatchID;
     int mRunToCompletionDepth;
     bool mShouldCallUnblockChild;
 
     // This is a cache of all of the memory reporters
     // registered in the child process.  To update this, one
     // can broadcast the topic "child-memory-reporter-request" using