widget/gonk/GonkPermission.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright (C) 2012 Mozilla Foundation
     3  *
     4  * Licensed under the Apache License, Version 2.0 (the "License");
     5  * you may not use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.
    15  */
    17 #include <binder/IPCThreadState.h>
    18 #include <binder/ProcessState.h>
    19 #include <binder/IServiceManager.h>
    20 #include <binder/IPermissionController.h>
    21 #include <private/android_filesystem_config.h>
    22 #include "GonkPermission.h"
    24 #include "mozilla/dom/ContentParent.h"
    25 #include "mozilla/dom/TabParent.h"
    26 #include "mozilla/SyncRunnable.h"
    27 #include "nsIAppsService.h"
    28 #include "mozIApplication.h"
    29 #include "nsThreadUtils.h"
    31 #undef LOG
    32 #include <android/log.h>
    33 #define ALOGE(args...)  __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args)
    35 using namespace android;
    36 using namespace mozilla;
    38 // Checking permissions needs to happen on the main thread, but the
    39 // binder callback is called on a special binder thread, so we use
    40 // this runnable for that.
    41 class GonkPermissionChecker : public nsRunnable {
    42   int32_t mPid;
    43   bool mCanUseCamera;
    45   explicit GonkPermissionChecker(int32_t pid)
    46     : mPid(pid)
    47     , mCanUseCamera(false)
    48   {
    49   }
    51 public:
    52   static already_AddRefed<GonkPermissionChecker> Inspect(int32_t pid)
    53   {
    54     nsRefPtr<GonkPermissionChecker> that = new GonkPermissionChecker(pid);
    55     nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
    56     MOZ_ASSERT(mainThread);
    57     SyncRunnable::DispatchToThread(mainThread, that);
    58     return that.forget();
    59   }
    61   bool CanUseCamera()
    62   {
    63     return mCanUseCamera;
    64   }
    66   NS_IMETHOD Run();
    67 };
    69 NS_IMETHODIMP
    70 GonkPermissionChecker::Run()
    71 {
    72   MOZ_ASSERT(NS_IsMainThread());
    74   // Find our ContentParent.
    75   dom::ContentParent *contentParent = nullptr;
    76   {
    77     nsTArray<dom::ContentParent*> parents;
    78     dom::ContentParent::GetAll(parents);
    79     for (uint32_t i = 0; i < parents.Length(); ++i) {
    80       if (parents[i]->Pid() == mPid) {
    81 	contentParent = parents[i];
    82 	break;
    83       }
    84     }
    85   }
    86   if (!contentParent) {
    87     ALOGE("pid=%d denied: can't find ContentParent", mPid);
    88     return NS_OK;
    89   }
    91   // Now iterate its apps...
    92   for (uint32_t i = 0; i < contentParent->ManagedPBrowserParent().Length(); i++) {
    93     dom::TabParent *tabParent =
    94       static_cast<dom::TabParent*>(contentParent->ManagedPBrowserParent()[i]);
    95     nsCOMPtr<mozIApplication> mozApp = tabParent->GetOwnOrContainingApp();
    96     if (!mozApp) {
    97       continue;
    98     }
   100     // ...and check if any of them has camera access.
   101     bool appCanUseCamera;
   102     nsresult rv = mozApp->HasPermission("camera", &appCanUseCamera);
   103     if (NS_SUCCEEDED(rv) && appCanUseCamera) {
   104       mCanUseCamera = true;
   105       return NS_OK;
   106     }
   107   }
   108   return NS_OK;
   109 }
   111 bool
   112 GonkPermissionService::checkPermission(const String16& permission, int32_t pid,
   113                                      int32_t uid)
   114 {
   115   // root can do anything.
   116   if (0 == uid) {
   117     return true;
   118   }
   120   String8 perm8(permission);
   122   // Some ril implementations need android.permission.MODIFY_AUDIO_SETTINGS
   123   if (uid == AID_RADIO &&
   124       perm8 == "android.permission.MODIFY_AUDIO_SETTINGS") {
   125     return true;
   126   }
   128   // No other permissions apply to non-app processes.
   129   if (uid < AID_APP) {
   130     ALOGE("%s for pid=%d,uid=%d denied: not an app",
   131       String8(permission).string(), pid, uid);
   132     return false;
   133   }
   135   // Only these permissions can be granted to apps through this service.
   136   if (perm8 != "android.permission.CAMERA" &&
   137     perm8 != "android.permission.RECORD_AUDIO") {
   138     ALOGE("%s for pid=%d,uid=%d denied: unsupported permission",
   139       String8(permission).string(), pid, uid);
   140     return false;
   141   }
   143   // Users granted the permission through a prompt dialog.
   144   // Before permission managment of gUM is done, app cannot remember the
   145   // permission.
   146   PermissionGrant permGrant(perm8.string(), pid);
   147   if (nsTArray<PermissionGrant>::NoIndex != mGrantArray.IndexOf(permGrant)) {
   148     mGrantArray.RemoveElement(permGrant);
   149     return true;
   150   }
   152   // Camera/audio record permissions are allowed for apps with the
   153   // "camera" permission.
   154   nsRefPtr<GonkPermissionChecker> checker =
   155     GonkPermissionChecker::Inspect(pid);
   156   bool canUseCamera = checker->CanUseCamera();
   157   if (!canUseCamera) {
   158     ALOGE("%s for pid=%d,uid=%d denied: not granted by user or app manifest",
   159       String8(permission).string(), pid, uid);
   160   }
   161   return canUseCamera;
   162 }
   164 static GonkPermissionService* gGonkPermissionService = NULL;
   166 /* static */
   167 void
   168 GonkPermissionService::instantiate()
   169 {
   170   defaultServiceManager()->addService(String16(getServiceName()),
   171     GetInstance());
   172 }
   174 /* static */
   175 GonkPermissionService*
   176 GonkPermissionService::GetInstance()
   177 {
   178   if (!gGonkPermissionService) {
   179     gGonkPermissionService = new GonkPermissionService();
   180   }
   181   return gGonkPermissionService;
   182 }
   184 void
   185 GonkPermissionService::addGrantInfo(const char* permission, int32_t pid)
   186 {
   187   mGrantArray.AppendElement(PermissionGrant(permission, pid));
   188 }

mercurial