| Index: chrome/renderer/extensions/extension_process_bindings.cc
|
| diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
|
| index 131b9a037e8ce64368179ae734190b2881a48f30..09a13119e68e0f8fc346fc44cb6742a6bbc03626 100644
|
| --- a/chrome/renderer/extensions/extension_process_bindings.cc
|
| +++ b/chrome/renderer/extensions/extension_process_bindings.cc
|
| @@ -5,6 +5,7 @@
|
| #include "chrome/renderer/extensions/extension_process_bindings.h"
|
|
|
| #include "base/singleton.h"
|
| +#include "chrome/common/extensions/extension.h"
|
| #include "chrome/common/render_messages.h"
|
| #include "chrome/common/url_constants.h"
|
| #include "chrome/renderer/extensions/bindings_utils.h"
|
| @@ -30,6 +31,12 @@ namespace {
|
| // A map of extension ID to vector of page action ids.
|
| typedef std::map< std::string, std::vector<std::string> > PageActionIdMap;
|
|
|
| +// A map of permission name to whether its enabled for this extension.
|
| +typedef std::map<std::string, bool> PermissionsMap;
|
| +
|
| +// A map of extension ID to permissions map.
|
| +typedef std::map<std::string, PermissionsMap> ExtensionPermissionsMap;
|
| +
|
| const char kExtensionName[] = "chrome/ExtensionProcessBindings";
|
| const char* kExtensionDeps[] = {
|
| BaseJsV8Extension::kName,
|
| @@ -41,6 +48,7 @@ const char* kExtensionDeps[] = {
|
| struct SingletonData {
|
| std::set<std::string> function_names_;
|
| PageActionIdMap page_action_ids_;
|
| + ExtensionPermissionsMap permissions_;
|
| };
|
|
|
| static std::set<std::string>* GetFunctionNameSet() {
|
| @@ -51,6 +59,10 @@ static PageActionIdMap* GetPageActionMap() {
|
| return &Singleton<SingletonData>()->page_action_ids_;
|
| }
|
|
|
| +static PermissionsMap* GetPermissionsMap(const std::string& extension_id) {
|
| + return &Singleton<SingletonData>()->permissions_[extension_id];
|
| +}
|
| +
|
| class ExtensionImpl : public ExtensionBase {
|
| public:
|
| ExtensionImpl() : ExtensionBase(
|
| @@ -64,6 +76,18 @@ class ExtensionImpl : public ExtensionBase {
|
| }
|
| }
|
|
|
| + // Note: do not call this function before or during the chromeHidden.onLoad
|
| + // event dispatch. The URL might not have been committed yet and might not
|
| + // be an extension URL.
|
| + static std::string ExtensionIdForCurrentContext() {
|
| + RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
|
| + DCHECK(renderview);
|
| + GURL url = renderview->webview()->GetMainFrame()->GetURL();
|
| + if (url.SchemeIs(chrome::kExtensionScheme))
|
| + return url.host();
|
| + return std::string();
|
| + }
|
| +
|
| virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
|
| v8::Handle<v8::String> name) {
|
| if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) {
|
| @@ -84,20 +108,13 @@ class ExtensionImpl : public ExtensionBase {
|
| }
|
|
|
| private:
|
| - static std::string ExtensionIdFromCurrentContext() {
|
| - RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
|
| - DCHECK(renderview);
|
| - GURL url = renderview->webview()->GetMainFrame()->GetURL();
|
| - return url.host();
|
| - }
|
| -
|
| static v8::Handle<v8::Value> GetExtensionAPIDefinition(
|
| const v8::Arguments& args) {
|
| return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>());
|
| }
|
|
|
| static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) {
|
| - std::string extension_id = ExtensionIdFromCurrentContext();
|
| + std::string extension_id = ExtensionIdForCurrentContext();
|
|
|
| ContextList contexts =
|
| bindings_utils::GetContextsForExtension(extension_id);
|
| @@ -145,11 +162,9 @@ class ExtensionImpl : public ExtensionBase {
|
|
|
| static v8::Handle<v8::Value> GetCurrentPageActions(
|
| const v8::Arguments& args) {
|
| - std::string extension_id = ExtensionIdFromCurrentContext();
|
| - PageActionIdMap* page_action_map =
|
| - GetPageActionMap();
|
| - PageActionIdMap::const_iterator it =
|
| - page_action_map->find(extension_id);
|
| + std::string extension_id = *v8::String::Utf8Value(args[0]->ToString());
|
| + PageActionIdMap* page_action_map = GetPageActionMap();
|
| + PageActionIdMap::const_iterator it = page_action_map->find(extension_id);
|
|
|
| std::vector<std::string> page_actions;
|
| size_t size = 0;
|
| @@ -187,6 +202,9 @@ class ExtensionImpl : public ExtensionBase {
|
| return v8::Undefined();
|
| }
|
|
|
| + if (!ExtensionProcessBindings::CurrentContextHasPermission(name))
|
| + return ExtensionProcessBindings::ThrowPermissionDeniedException(name);
|
| +
|
| std::string json_args = *v8::String::Utf8Value(args[1]);
|
| int request_id = args[2]->Int32Value();
|
| bool has_callback = args[3]->BooleanValue();
|
| @@ -249,3 +267,75 @@ void ExtensionProcessBindings::SetPageActions(
|
| page_action_map.erase(extension_id);
|
| }
|
| }
|
| +
|
| +// static
|
| +void ExtensionProcessBindings::SetPermissions(
|
| + const std::string& extension_id,
|
| + const std::vector<std::string>& permissions) {
|
| + PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
|
| +
|
| + // Default all permissions to false, then enable the ones in the vector.
|
| + for (size_t i = 0; i < Extension::kNumPermissions; ++i)
|
| + permissions_map[Extension::kPermissionNames[i]] = false;
|
| + for (size_t i = 0; i < permissions.size(); ++i)
|
| + permissions_map[permissions[i]] = true;
|
| +}
|
| +
|
| +// Given a name like "tabs.onConnect", return the permission name required
|
| +// to access that API ("tabs" in this example).
|
| +static std::string GetPermissionName(const std::string& function_name) {
|
| + size_t first_dot = function_name.find('.');
|
| + std::string permission_name = function_name.substr(0, first_dot);
|
| + if (permission_name == "windows")
|
| + return "tabs"; // windows and tabs are the same permission.
|
| + return permission_name;
|
| +}
|
| +
|
| +// static
|
| +bool ExtensionProcessBindings::CurrentContextHasPermission(
|
| + const std::string& function_name) {
|
| + std::string extension_id = ExtensionImpl::ExtensionIdForCurrentContext();
|
| + PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
|
| + std::string permission_name = GetPermissionName(function_name);
|
| + PermissionsMap::iterator it = permissions_map.find(permission_name);
|
| +
|
| + // We explicitly check if the permission entry is present and false, because
|
| + // some APIs do not have a required permission entry (ie, "chrome.self").
|
| + return (it == permissions_map.end() || it->second);
|
| +}
|
| +
|
| +// static
|
| +v8::Handle<v8::Value>
|
| + ExtensionProcessBindings::ThrowPermissionDeniedException(
|
| + const std::string& function_name) {
|
| + static const char kMessage[] =
|
| + "You do not have permission to use 'chrome.%s'. Be sure to declare"
|
| + " in your manifest what permissions you need.";
|
| + std::string permission_name = GetPermissionName(function_name);
|
| + std::string error_msg = StringPrintf(kMessage, permission_name.c_str());
|
| +
|
| +#if EXTENSION_TIME_TO_BREAK_API
|
| + return v8::ThrowException(v8::Exception::Error(
|
| + v8::String::New(error_msg.c_str())));
|
| +#else
|
| + // Call console.error for now.
|
| +
|
| + v8::HandleScope scope;
|
| +
|
| + v8::Local<v8::Value> console =
|
| + v8::Context::GetCurrent()->Global()->Get(v8::String::New("console"));
|
| + v8::Local<v8::Value> console_error;
|
| + if (!console.IsEmpty() && console->IsObject())
|
| + console_error = console->ToObject()->Get(v8::String::New("error"));
|
| + if (console_error.IsEmpty() || !console_error->IsFunction())
|
| + return v8::Undefined();
|
| +
|
| + v8::Local<v8::Function> function =
|
| + v8::Local<v8::Function>::Cast(console_error);
|
| + v8::Local<v8::Value> argv[] = { v8::String::New(error_msg.c_str()) };
|
| + if (!function.IsEmpty())
|
| + function->Call(console->ToObject(), arraysize(argv), argv);
|
| +
|
| + return v8::Undefined();
|
| +#endif
|
| +}
|
|
|