widget/gonk/GonkPermission.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial