1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/GonkPermission.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,188 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 Mozilla Foundation 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#include <binder/IPCThreadState.h> 1.21 +#include <binder/ProcessState.h> 1.22 +#include <binder/IServiceManager.h> 1.23 +#include <binder/IPermissionController.h> 1.24 +#include <private/android_filesystem_config.h> 1.25 +#include "GonkPermission.h" 1.26 + 1.27 +#include "mozilla/dom/ContentParent.h" 1.28 +#include "mozilla/dom/TabParent.h" 1.29 +#include "mozilla/SyncRunnable.h" 1.30 +#include "nsIAppsService.h" 1.31 +#include "mozIApplication.h" 1.32 +#include "nsThreadUtils.h" 1.33 + 1.34 +#undef LOG 1.35 +#include <android/log.h> 1.36 +#define ALOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args) 1.37 + 1.38 +using namespace android; 1.39 +using namespace mozilla; 1.40 + 1.41 +// Checking permissions needs to happen on the main thread, but the 1.42 +// binder callback is called on a special binder thread, so we use 1.43 +// this runnable for that. 1.44 +class GonkPermissionChecker : public nsRunnable { 1.45 + int32_t mPid; 1.46 + bool mCanUseCamera; 1.47 + 1.48 + explicit GonkPermissionChecker(int32_t pid) 1.49 + : mPid(pid) 1.50 + , mCanUseCamera(false) 1.51 + { 1.52 + } 1.53 + 1.54 +public: 1.55 + static already_AddRefed<GonkPermissionChecker> Inspect(int32_t pid) 1.56 + { 1.57 + nsRefPtr<GonkPermissionChecker> that = new GonkPermissionChecker(pid); 1.58 + nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); 1.59 + MOZ_ASSERT(mainThread); 1.60 + SyncRunnable::DispatchToThread(mainThread, that); 1.61 + return that.forget(); 1.62 + } 1.63 + 1.64 + bool CanUseCamera() 1.65 + { 1.66 + return mCanUseCamera; 1.67 + } 1.68 + 1.69 + NS_IMETHOD Run(); 1.70 +}; 1.71 + 1.72 +NS_IMETHODIMP 1.73 +GonkPermissionChecker::Run() 1.74 +{ 1.75 + MOZ_ASSERT(NS_IsMainThread()); 1.76 + 1.77 + // Find our ContentParent. 1.78 + dom::ContentParent *contentParent = nullptr; 1.79 + { 1.80 + nsTArray<dom::ContentParent*> parents; 1.81 + dom::ContentParent::GetAll(parents); 1.82 + for (uint32_t i = 0; i < parents.Length(); ++i) { 1.83 + if (parents[i]->Pid() == mPid) { 1.84 + contentParent = parents[i]; 1.85 + break; 1.86 + } 1.87 + } 1.88 + } 1.89 + if (!contentParent) { 1.90 + ALOGE("pid=%d denied: can't find ContentParent", mPid); 1.91 + return NS_OK; 1.92 + } 1.93 + 1.94 + // Now iterate its apps... 1.95 + for (uint32_t i = 0; i < contentParent->ManagedPBrowserParent().Length(); i++) { 1.96 + dom::TabParent *tabParent = 1.97 + static_cast<dom::TabParent*>(contentParent->ManagedPBrowserParent()[i]); 1.98 + nsCOMPtr<mozIApplication> mozApp = tabParent->GetOwnOrContainingApp(); 1.99 + if (!mozApp) { 1.100 + continue; 1.101 + } 1.102 + 1.103 + // ...and check if any of them has camera access. 1.104 + bool appCanUseCamera; 1.105 + nsresult rv = mozApp->HasPermission("camera", &appCanUseCamera); 1.106 + if (NS_SUCCEEDED(rv) && appCanUseCamera) { 1.107 + mCanUseCamera = true; 1.108 + return NS_OK; 1.109 + } 1.110 + } 1.111 + return NS_OK; 1.112 +} 1.113 + 1.114 +bool 1.115 +GonkPermissionService::checkPermission(const String16& permission, int32_t pid, 1.116 + int32_t uid) 1.117 +{ 1.118 + // root can do anything. 1.119 + if (0 == uid) { 1.120 + return true; 1.121 + } 1.122 + 1.123 + String8 perm8(permission); 1.124 + 1.125 + // Some ril implementations need android.permission.MODIFY_AUDIO_SETTINGS 1.126 + if (uid == AID_RADIO && 1.127 + perm8 == "android.permission.MODIFY_AUDIO_SETTINGS") { 1.128 + return true; 1.129 + } 1.130 + 1.131 + // No other permissions apply to non-app processes. 1.132 + if (uid < AID_APP) { 1.133 + ALOGE("%s for pid=%d,uid=%d denied: not an app", 1.134 + String8(permission).string(), pid, uid); 1.135 + return false; 1.136 + } 1.137 + 1.138 + // Only these permissions can be granted to apps through this service. 1.139 + if (perm8 != "android.permission.CAMERA" && 1.140 + perm8 != "android.permission.RECORD_AUDIO") { 1.141 + ALOGE("%s for pid=%d,uid=%d denied: unsupported permission", 1.142 + String8(permission).string(), pid, uid); 1.143 + return false; 1.144 + } 1.145 + 1.146 + // Users granted the permission through a prompt dialog. 1.147 + // Before permission managment of gUM is done, app cannot remember the 1.148 + // permission. 1.149 + PermissionGrant permGrant(perm8.string(), pid); 1.150 + if (nsTArray<PermissionGrant>::NoIndex != mGrantArray.IndexOf(permGrant)) { 1.151 + mGrantArray.RemoveElement(permGrant); 1.152 + return true; 1.153 + } 1.154 + 1.155 + // Camera/audio record permissions are allowed for apps with the 1.156 + // "camera" permission. 1.157 + nsRefPtr<GonkPermissionChecker> checker = 1.158 + GonkPermissionChecker::Inspect(pid); 1.159 + bool canUseCamera = checker->CanUseCamera(); 1.160 + if (!canUseCamera) { 1.161 + ALOGE("%s for pid=%d,uid=%d denied: not granted by user or app manifest", 1.162 + String8(permission).string(), pid, uid); 1.163 + } 1.164 + return canUseCamera; 1.165 +} 1.166 + 1.167 +static GonkPermissionService* gGonkPermissionService = NULL; 1.168 + 1.169 +/* static */ 1.170 +void 1.171 +GonkPermissionService::instantiate() 1.172 +{ 1.173 + defaultServiceManager()->addService(String16(getServiceName()), 1.174 + GetInstance()); 1.175 +} 1.176 + 1.177 +/* static */ 1.178 +GonkPermissionService* 1.179 +GonkPermissionService::GetInstance() 1.180 +{ 1.181 + if (!gGonkPermissionService) { 1.182 + gGonkPermissionService = new GonkPermissionService(); 1.183 + } 1.184 + return gGonkPermissionService; 1.185 +} 1.186 + 1.187 +void 1.188 +GonkPermissionService::addGrantInfo(const char* permission, int32_t pid) 1.189 +{ 1.190 + mGrantArray.AppendElement(PermissionGrant(permission, pid)); 1.191 +}