diff --git a/widget/gonk/GonkPermission.cpp b/widget/gonk/GonkPermission.cpp new file mode 100644 index 000000000000..faa0f15b1a66 --- /dev/null +++ b/widget/gonk/GonkPermission.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "GonkPermission.h" + +#undef LOG +#include +#define ALOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args) + +using namespace android; +using namespace mozilla; + +bool +GonkPermissionService::checkPermission(const String16& permission, int32_t pid, + int32_t uid) +{ + if (0 == uid) + return true; + + // Camera/audio record permissions are only for apps with the + // "camera" permission. These apps are also the only apps granted + // the AID_SDCARD_RW supplemental group (bug 785592) + + if (uid < AID_APP) { + ALOGE("%s for pid=%d,uid=%d denied: not an app", + String8(permission).string(), pid, uid); + return false; + } + + String8 perm8(permission); + + if (perm8 != "android.permission.CAMERA" && + perm8 != "android.permission.RECORD_AUDIO") { + ALOGE("%s for pid=%d,uid=%d denied: unsupported permission", + String8(permission).string(), pid, uid); + return false; + } + + // Users granted the permission through a prompt dialog. + // Before permission managment of gUM is done, app cannot remember the + // permission. + PermissionGrant permGrant(perm8.string(), pid); + if (nsTArray::NoIndex != mGrantArray.IndexOf(permGrant)) { + mGrantArray.RemoveElement(permGrant); + return true; + } + + char filename[32]; + snprintf(filename, sizeof(filename), "/proc/%d/status", pid); + FILE *f = fopen(filename, "r"); + if (!f) { + ALOGE("%s for pid=%d,uid=%d denied: unable to open %s", + String8(permission).string(), pid, uid, filename); + return false; + } + + char line[80]; + while (fgets(line, sizeof(line), f)) { + char *save; + char *name = strtok_r(line, "\t", &save); + if (!name) + continue; + + if (strcmp(name, "Groups:")) + continue; + char *group; + while ((group = strtok_r(NULL, " \n", &save))) { + #define _STR(x) #x + #define STR(x) _STR(x) + if (!strcmp(group, STR(AID_SDCARD_RW))) { + fclose(f); + return true; + } + } + break; + } + fclose(f); + + ALOGE("%s for pid=%d,uid=%d denied: missing group", + String8(permission).string(), pid, uid); + return false; +} + +static GonkPermissionService* gGonkPermissionService = NULL; + +/* static */ +void +GonkPermissionService::instantiate() +{ + defaultServiceManager()->addService(String16(getServiceName()), + GetInstance()); +} + +/* static */ +GonkPermissionService* +GonkPermissionService::GetInstance() +{ + if (!gGonkPermissionService) { + gGonkPermissionService = new GonkPermissionService(); + } + return gGonkPermissionService; +} + +void +GonkPermissionService::addGrantInfo(const char* permission, int32_t pid) +{ + mGrantArray.AppendElement(PermissionGrant(permission, pid)); +} diff --git a/widget/gonk/GonkPermission.h b/widget/gonk/GonkPermission.h new file mode 100644 index 000000000000..5e40b2a2779a --- /dev/null +++ b/widget/gonk/GonkPermission.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef GONKPERMISSION_H +#define GONKPERMISSION_H + +#include +#include "nsString.h" +#include "nsTArray.h" + +namespace mozilla { +class PermissionGrant +{ +public: + PermissionGrant(const char* perm, int32_t p) : mPid(p) + { + mPermission.Assign(perm); + } + + PermissionGrant(const nsACString& permission, int32_t pid) : mPid(pid), + mPermission(permission) + { + } + + bool operator==(const PermissionGrant& other) const + { + return (mPid == other.pid() && mPermission.Equals(other.permission())); + } + + int32_t pid() const + { + return mPid; + } + + const nsACString& permission() const + { + return mPermission; + } + +private: + int32_t mPid; + nsCString mPermission; +}; + +class PermissionGrant; + +class GonkPermissionService : + public android::BinderService, + public android::BnPermissionController +{ +public: + virtual ~GonkPermissionService() {} + static GonkPermissionService* GetInstance(); + static const char *getServiceName() { + return "permission"; + } + + static void instantiate(); + + virtual android::status_t dump(int fd, const android::Vector& args) { + return android::NO_ERROR; + } + virtual bool checkPermission(const android::String16& permission, int32_t pid, + int32_t uid); + + void addGrantInfo(const char* permission, int32_t pid); +private: + GonkPermissionService(): android::BnPermissionController() {} + nsTArray mGrantArray; +}; +} // namespace mozilla +#endif // GONKPERMISSION_H diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build index 17bfac5c551e..22948131ea22 100644 --- a/widget/gonk/moz.build +++ b/widget/gonk/moz.build @@ -15,6 +15,7 @@ # limitations under the License. EXPORTS += [ + 'GonkPermission.h', 'OrientationObserver.h', ] @@ -46,6 +47,7 @@ SOURCES += [ 'Framebuffer.cpp', 'GfxInfo.cpp', 'GonkMemoryPressureMonitoring.cpp', + 'GonkPermission.cpp', 'HwcComposer2D.cpp', 'HwcUtils.cpp', 'nsAppShell.cpp', diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index 28569ad98295..c58da872b63f 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -29,6 +29,7 @@ #include #include "base/basictypes.h" +#include "GonkPermission.h" #include "nscore.h" #ifdef MOZ_OMX_DECODER #include "MediaResourceManagerService.h" @@ -750,6 +751,7 @@ nsAppShell::Init() #if ANDROID_VERSION >= 18 android::FakeSurfaceComposer::instantiate(); #endif + GonkPermissionService::instantiate(); } nsCOMPtr obsServ = GetObserverService();