2 * Copyright (C) 2012 Mozilla Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
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
{
45 explicit GonkPermissionChecker(int32_t pid
)
47 , mCanUseCamera(false)
52 static already_AddRefed
<GonkPermissionChecker
> Inspect(int32_t pid
)
54 nsRefPtr
<GonkPermissionChecker
> that
= new GonkPermissionChecker(pid
);
55 nsCOMPtr
<nsIThread
> mainThread
= do_GetMainThread();
56 MOZ_ASSERT(mainThread
);
57 SyncRunnable::DispatchToThread(mainThread
, that
);
70 GonkPermissionChecker::Run()
72 MOZ_ASSERT(NS_IsMainThread());
74 // Find our ContentParent.
75 dom::ContentParent
*contentParent
= nullptr;
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
];
87 ALOGE("pid=%d denied: can't find ContentParent", mPid
);
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();
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;
112 GonkPermissionService::checkPermission(const String16
& permission
, int32_t pid
,
115 // root can do anything.
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") {
128 // No other permissions apply to non-app processes.
130 ALOGE("%s for pid=%d,uid=%d denied: not an app",
131 String8(permission
).string(), pid
, uid
);
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
);
143 // Users granted the permission through a prompt dialog.
144 // Before permission managment of gUM is done, app cannot remember the
146 PermissionGrant
permGrant(perm8
.string(), pid
);
147 if (nsTArray
<PermissionGrant
>::NoIndex
!= mGrantArray
.IndexOf(permGrant
)) {
148 mGrantArray
.RemoveElement(permGrant
);
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();
158 ALOGE("%s for pid=%d,uid=%d denied: not granted by user or app manifest",
159 String8(permission
).string(), pid
, uid
);
164 static GonkPermissionService
* gGonkPermissionService
= NULL
;
168 GonkPermissionService::instantiate()
170 defaultServiceManager()->addService(String16(getServiceName()),
175 GonkPermissionService
*
176 GonkPermissionService::GetInstance()
178 if (!gGonkPermissionService
) {
179 gGonkPermissionService
= new GonkPermissionService();
181 return gGonkPermissionService
;
185 GonkPermissionService::addGrantInfo(const char* permission
, int32_t pid
)
187 mGrantArray
.AppendElement(PermissionGrant(permission
, pid
));