summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-07 18:58:19 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-07 18:58:19 +0000
commit35506359934707a1dc47e0b26684a145835dd9c3 (patch)
treea4c148fec23792743e3f5f024c852f6d668f173d /chrome
parentd4d9025c103adaa1b89b130ed229e61947ec40cc (diff)
downloadchromium_src-35506359934707a1dc47e0b26684a145835dd9c3.zip
chromium_src-35506359934707a1dc47e0b26684a145835dd9c3.tar.gz
chromium_src-35506359934707a1dc47e0b26684a145835dd9c3.tar.bz2
Add module-level permissions to extensions.
This first pass is fairly simple. If a permission is not specified in the manifest, the corresponding module will not be exposed to script. For example, without specifying the "tabs" permission, chrome.tabs and chrome.windows will not be available. BUG=12140 TEST=no Review URL: http://codereview.chromium.org/164039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22745 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc12
-rw-r--r--chrome/browser/extensions/extension_host.cc6
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc2
-rw-r--r--chrome/browser/extensions/extensions_ui.cc2
-rw-r--r--chrome/common/common_resources.grd4
-rw-r--r--chrome/common/extensions/extension.cc75
-rw-r--r--chrome/common/extensions/extension.h16
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/renderer/extensions/event_bindings.cc12
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc116
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.h14
-rw-r--r--chrome/renderer/render_thread.cc8
-rw-r--r--chrome/renderer/render_thread.h2
-rw-r--r--chrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js4
-rw-r--r--chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json2
-rw-r--r--chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/manifest.json1
-rw-r--r--chrome/test/data/extensions/uitest/event_sink/manifest.json3
-rw-r--r--chrome/test/data/extensions/uitest/roundtrip_api_call/manifest.json3
-rw-r--r--chrome/test/data/extensions/uitest/simple_api_call/manifest.json3
-rw-r--r--chrome/test/render_view_test.cc6
21 files changed, 246 insertions, 53 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 5d03e1f..e9ddef4 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/common/render_messages.h"
#include "chrome/common/result_codes.h"
#include "chrome/common/url_constants.h"
@@ -198,7 +199,10 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
ALLOW_THIS_IN_INITIALIZER_LIST(peer_(new Peer(this))) {
// TODO(erikkay) should we do something for these errors in Release?
DCHECK(url.SchemeIs(chrome::kExtensionScheme));
- DCHECK(profile()->GetExtensionsService()->GetExtensionByURL(url));
+
+ Extension* extension =
+ profile()->GetExtensionsService()->GetExtensionByURL(url);
+ DCHECK(extension);
all_instances()->insert(this);
@@ -206,6 +210,12 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
ExtensionProcessManager* epm = profile()->GetExtensionProcessManager();
epm->RegisterExtensionProcess(extension_id(),
render_view_host->process()->pid());
+
+ // Update the extension permissions. Doing this each time we create an EFD
+ // ensures that new processes are informed of permissions for newly installed
+ // extensions.
+ render_view_host->Send(new ViewMsg_Extension_SetPermissions(
+ extension->id(), extension->api_permissions()));
}
ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index ee81c39..898aeaa 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -386,4 +386,10 @@ Browser* ExtensionHost::GetBrowser() {
}
void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) {
+ // TODO(mpcomplete): This is duplicated in DidNavigate, which means that
+ // we'll create 2 EFDs for the first navigation. We should try to find a
+ // better way to unify them.
+ // See http://code.google.com/p/chromium/issues/detail?id=18240
+ extension_function_dispatcher_.reset(
+ new ExtensionFunctionDispatcher(render_view_host, this, url_));
}
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index 33d81d2..0356ed6 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -520,7 +520,7 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) {
.AppendASCII("script3.js")
.value()),
NormalizeSeperators(scripts[1].js_scripts()[0].path().value()));
- const std::vector<URLPattern> permissions = extension->permissions();
+ const std::vector<URLPattern> permissions = extension->host_permissions();
ASSERT_EQ(2u, permissions.size());
EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString());
EXPECT_EQ("https://*.google.com/*", permissions[1].GetAsString());
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index 57cdae0..849fc8f 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -207,7 +207,7 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
// Add permissions
ListValue *permission_list = new ListValue;
- std::vector<URLPattern> permissions = extension->permissions();
+ std::vector<URLPattern> permissions = extension->host_permissions();
for (std::vector<URLPattern>::iterator permission = permissions.begin();
permission != permissions.end(); ++permission) {
permission_list->Append(Value::CreateStringValue(
diff --git a/chrome/common/common_resources.grd b/chrome/common/common_resources.grd
index 5ea8f3c..933d414 100644
--- a/chrome/common/common_resources.grd
+++ b/chrome/common/common_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. rw -->
+without changes to the corresponding grd file. mp4 -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/common_resources.h" type="rc_header">
@@ -16,4 +16,4 @@ without changes to the corresponding grd file. rw -->
<include name="IDR_EXTENSION_API_JSON" file="extensions\api\extension_api.json" type="BINDATA" />
</includes>
</release>
-</grit> \ No newline at end of file
+</grit>
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 719f61c..17fb867 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -31,26 +31,37 @@ namespace values = extension_manifest_values;
namespace errors = extension_manifest_errors;
namespace {
- const int kPEMOutputColumns = 65;
+const int kPEMOutputColumns = 65;
+
+// KEY MARKERS
+const char kKeyBeginHeaderMarker[] = "-----BEGIN";
+const char kKeyBeginFooterMarker[] = "-----END";
+const char kKeyInfoEndMarker[] = "KEY-----";
+const char kPublic[] = "PUBLIC";
+const char kPrivate[] = "PRIVATE";
+
+const int kRSAKeySize = 1024;
+
+// Converts a normal hexadecimal string into the alphabet used by extensions.
+// We use the characters 'a'-'p' instead of '0'-'f' to avoid ever having a
+// completely numeric host, since some software interprets that as an IP
+// address.
+static void ConvertHexadecimalToIDAlphabet(std::string* id) {
+ for (size_t i = 0; i < id->size(); ++i)
+ (*id)[i] = HexStringToInt(id->substr(i, 1)) + 'a';
+}
- // KEY MARKERS
- const char kKeyBeginHeaderMarker[] = "-----BEGIN";
- const char kKeyBeginFooterMarker[] = "-----END";
- const char kKeyInfoEndMarker[] = "KEY-----";
- const char kPublic[] = "PUBLIC";
- const char kPrivate[] = "PRIVATE";
+// Returns true if the given string is an API permission (see kPermissionNames).
+static bool IsAPIPermission(const std::string& str) {
+ for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
+ if (str == Extension::kPermissionNames[i])
+ return true;
+ }
- const int kRSAKeySize = 1024;
+ return false;
+}
- // Converts a normal hexadecimal string into the alphabet used by extensions.
- // We use the characters 'a'-'p' instead of '0'-'f' to avoid ever having a
- // completely numeric host, since some software interprets that as an IP
- // address.
- static void ConvertHexadecimalToIDAlphabet(std::string* id) {
- for (size_t i = 0; i < id->size(); ++i)
- (*id)[i] = HexStringToInt(id->substr(i, 1)) + 'a';
- }
-};
+} // namespace
// static
int Extension::id_counter_ = 0;
@@ -85,6 +96,13 @@ const int Extension::kIconSizes[] = {
EXTENSION_ICON_BITTY
};
+const char* Extension::kPermissionNames[] = {
+ "tabs",
+ "bookmarks",
+};
+const size_t Extension::kNumPermissions =
+ arraysize(Extension::kPermissionNames);
+
Extension::~Extension() {
for (PageActionMap::iterator i = page_actions_.begin();
i != page_actions_.end(); ++i)
@@ -852,28 +870,35 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
// Initialize the permissions (optional).
if (source.HasKey(keys::kPermissions)) {
- ListValue* hosts = NULL;
- if (!source.GetList(keys::kPermissions, &hosts)) {
+ ListValue* permissions = NULL;
+ if (!source.GetList(keys::kPermissions, &permissions)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidPermissions, "");
return false;
}
- if (hosts->GetSize() == 0) {
+ if (permissions->GetSize() == 0) {
ExtensionErrorReporter::GetInstance()->ReportError(
errors::kInvalidPermissionCountWarning, false);
}
- for (size_t i = 0; i < hosts->GetSize(); ++i) {
- std::string host_str;
- if (!hosts->GetString(i, &host_str)) {
+ for (size_t i = 0; i < permissions->GetSize(); ++i) {
+ std::string permission_str;
+ if (!permissions->GetString(i, &permission_str)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidPermission, IntToString(i));
return false;
}
+ // Check if it's a module permission. If so, enable that permission.
+ if (IsAPIPermission(permission_str)) {
+ api_permissions_.push_back(permission_str);
+ continue;
+ }
+
+ // Otherwise, it's a host pattern permission.
URLPattern pattern;
- if (!pattern.Parse(host_str)) {
+ if (!pattern.Parse(permission_str)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidPermission, IntToString(i));
return false;
@@ -887,7 +912,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
return false;
}
- permissions_.push_back(pattern);
+ host_permissions_.push_back(pattern);
}
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 550fbba..7969e96 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -58,6 +58,10 @@ class Extension {
// Icon sizes used by the extension system.
static const int kIconSizes[];
+ // Each permission is a module that the extension is permitted to use.
+ static const char* kPermissionNames[];
+ static const size_t kNumPermissions;
+
// An NPAPI plugin included in the extension.
struct PluginInfo {
FilePath path; // Path to the plugin.
@@ -172,7 +176,12 @@ class Extension {
const std::vector<PluginInfo>& plugins() const { return plugins_; }
const GURL& background_url() const { return background_url_; }
const std::vector<ToolstripInfo>& toolstrips() const { return toolstrips_; }
- const std::vector<URLPattern>& permissions() const { return permissions_; }
+ const std::vector<URLPattern>& host_permissions() const {
+ return host_permissions_;
+ }
+ const std::vector<std::string>& api_permissions() const {
+ return api_permissions_;
+ }
const GURL& update_url() const { return update_url_; }
const std::map<int, std::string>& icons() { return icons_; }
@@ -293,8 +302,11 @@ class Extension {
// Whether the extension is a theme - if it is, certain things are disabled.
bool is_theme_;
+ // The set of module-level APIs this extension can use.
+ std::vector<std::string> api_permissions_;
+
// The sites this extension has permission to talk to (using XHR, etc).
- std::vector<URLPattern> permissions_;
+ std::vector<URLPattern> host_permissions_;
// The paths to the icons the extension contains mapped by their width.
std::map<int, std::string> icons_;
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 5894bdc..22cd1c0 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -589,6 +589,12 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetFunctionNames,
std::vector<std::string>)
+ // Tell the renderer process which permissions the given extension has. See
+ // Extension::Permissions for which elements correspond to which permissions.
+ IPC_MESSAGE_CONTROL2(ViewMsg_Extension_SetPermissions,
+ std::string /* extension_id */,
+ std::vector<std::string> /* permissions */)
+
// Tell the renderer process all known page action ids for a particular
// extension.
IPC_MESSAGE_CONTROL2(ViewMsg_Extension_UpdatePageActions,
diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index b44fe82..d771580 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.cc
@@ -76,10 +76,20 @@ class ExtensionImpl : public ExtensionBase {
if (args[0]->IsString()) {
std::string event_name(*v8::String::AsciiValue(args[0]));
- if (EventIncrementListenerCount(event_name) == 1) {
+ bool has_permission =
+ ExtensionProcessBindings::CurrentContextHasPermission(event_name);
+
+ // Increment the count even if the caller doesn't have permission, so that
+ // refcounts stay balanced.
+ if (EventIncrementListenerCount(event_name) == 1 && has_permission) {
EventBindings::GetRenderThread()->Send(
new ViewHostMsg_ExtensionAddListener(event_name));
}
+
+ if (!has_permission) {
+ return ExtensionProcessBindings::ThrowPermissionDeniedException(
+ event_name);
+ }
}
return v8::Undefined();
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 131b9a0..09a1311 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
+}
diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h
index 1ce6b47..dd212c5 100644
--- a/chrome/renderer/extensions/extension_process_bindings.h
+++ b/chrome/renderer/extensions/extension_process_bindings.h
@@ -26,6 +26,20 @@ class ExtensionProcessBindings {
// Sets the page action ids for a particular extension.
static void SetPageActions(const std::string& extension_id,
const std::vector<std::string>& page_actions);
+
+ // Sets the permissions for a particular extension.
+ static void SetPermissions(const std::string& extension_id,
+ const std::vector<std::string>& permissions);
+
+ // Check if the extension in the currently running context has permission to
+ // access the given extension function. Must be called with a valid V8
+ // context in scope.
+ static bool CurrentContextHasPermission(const std::string& function_name);
+
+ // Throw a V8 exception indicating that permission to access function_name was
+ // denied. Must be called with a valid V8 context in scope.
+ static v8::Handle<v8::Value> ThrowPermissionDeniedException(
+ const std::string& function_name);
};
#endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 3571f6d..ecddc2de2 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -202,6 +202,12 @@ void RenderThread::OnPageActionsUpdated(
ExtensionProcessBindings::SetPageActions(extension_id, page_actions);
}
+void RenderThread::OnExtensionSetPermissions(
+ const std::string& extension_id,
+ const std::vector<std::string>& permissions) {
+ ExtensionProcessBindings::SetPermissions(extension_id, permissions);
+}
+
void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
// App cache messages are handled by a delegate.
if (app_cache_dispatcher_->OnMessageReceived(msg))
@@ -233,6 +239,8 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
OnPurgePluginListCache)
IPC_MESSAGE_HANDLER(ViewMsg_Extension_UpdatePageActions,
OnPageActionsUpdated)
+ IPC_MESSAGE_HANDLER(ViewMsg_Extension_SetPermissions,
+ OnExtensionSetPermissions)
IPC_END_MESSAGE_MAP()
}
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index d9cd1fb..f90a6a9 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -126,6 +126,8 @@ class RenderThread : public RenderThreadBase,
void OnSetExtensionFunctionNames(const std::vector<std::string>& names);
void OnPageActionsUpdated(const std::string& extension_id,
const std::vector<std::string>& page_actions);
+ void OnExtensionSetPermissions(const std::string& extension_id,
+ const std::vector<std::string>& permissions);
void OnSetNextPageID(int32 next_page_id);
void OnSetCSSColors(const std::vector<CSSColors::CSSColorMapping>& colors);
void OnCreateNewView(gfx::NativeViewId parent_hwnd,
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index 5ec2309..8be37f6 100644
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. rw -->
+without changes to the corresponding grd file. mp3 -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 7218d03..1e33cb9 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -14,7 +14,7 @@ var chrome = chrome || {};
(function() {
native function GetExtensionAPIDefinition();
native function StartRequest();
- native function GetCurrentPageActions();
+ native function GetCurrentPageActions(extensionId);
native function GetViews();
native function GetChromeHidden();
native function GetNextRequestId();
@@ -186,7 +186,7 @@ var chrome = chrome || {};
// Page action events send (pageActionId, {tabId, tabUrl}).
function setupPageActionEvents(extensionId) {
- var pageActions = GetCurrentPageActions();
+ var pageActions = GetCurrentPageActions(extensionId);
var eventName = "";
for (var i = 0; i < pageActions.length; ++i) {
eventName = extensionId + "/" + pageActions[i];
diff --git a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json
index c1cf5b3..03acc6b 100644
--- a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json
+++ b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json
@@ -14,7 +14,7 @@
},
"toolstrip2.html"
],
- "permissions": ["http://*.google.com/*", "https://*.google.com/*"],
+ "permissions": ["tabs", "http://*.google.com/*", "https://*.google.com/*"],
"content_scripts": [
{
"matches": ["file://*", "http://*.google.com/*", "https://*.google.com/*"],
diff --git a/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/manifest.json b/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/manifest.json
index 6cb06ff..08721e8 100644
--- a/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/manifest.json
+++ b/chrome/test/data/extensions/good/Extensions/bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0/manifest.json
@@ -3,6 +3,7 @@
"version": "1.0",
"name": "My extension 3",
"toolstrips": ["toolstrip.html"],
+ "permissions": ["tabs"],
"content_scripts": [
{
"matches": ["file://*"],
diff --git a/chrome/test/data/extensions/uitest/event_sink/manifest.json b/chrome/test/data/extensions/uitest/event_sink/manifest.json
index 830243d..859aa8f 100644
--- a/chrome/test/data/extensions/uitest/event_sink/manifest.json
+++ b/chrome/test/data/extensions/uitest/event_sink/manifest.json
@@ -1,5 +1,6 @@
{
"version": "1.0.0.0",
"name": "Browser Event Sink Test Extension",
- "description": "An extension UITest for testing the sending of browser events."
+ "description": "An extension UITest for testing the sending of browser events.",
+ "permissions": ["tabs", "bookmarks"]
}
diff --git a/chrome/test/data/extensions/uitest/roundtrip_api_call/manifest.json b/chrome/test/data/extensions/uitest/roundtrip_api_call/manifest.json
index 5acde49..67f9e13 100644
--- a/chrome/test/data/extensions/uitest/roundtrip_api_call/manifest.json
+++ b/chrome/test/data/extensions/uitest/roundtrip_api_call/manifest.json
@@ -2,5 +2,6 @@
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4RIIi/YbLZ6dRpdQnWfrQuo2vunkuPJpD9HNvZQ3J5aylSw7Y8ghzom793CbTJK1ZI254yZtkaWZJWOBhPKCaaRac+qfpRN1spl42vpyMn1OrGQm1pwZT6rDpCyIVIx/k2o4puMsQHNUIqxXPu3Oj+KSVdCIGOmabMhz765UjhwIDAQAB",
"version": "1.0.0.0",
"name": "Roundtrip ApiCall Test Extension",
- "description": "An extension for an extension UITest."
+ "description": "An extension for an extension UITest.",
+ "permissions": ["tabs"]
}
diff --git a/chrome/test/data/extensions/uitest/simple_api_call/manifest.json b/chrome/test/data/extensions/uitest/simple_api_call/manifest.json
index b302c0e..1918c59 100644
--- a/chrome/test/data/extensions/uitest/simple_api_call/manifest.json
+++ b/chrome/test/data/extensions/uitest/simple_api_call/manifest.json
@@ -2,5 +2,6 @@
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsaVmPYFjlYABY7y8sEVB5i3/stDIXU8i3bBeQYeaXOg+Jr1vEhaSgKTy3zMY4m3+cnKI7Z/bMpYohS4pQTcwIXS1kEB6taCUUWgm2315zxSH+gUFRyfzBDlS8LZ9tRirFGj8o0R2YQobHgSPyf04Phq4AeMmGSygEJkfGO+Wt8wIDAQAB",
"version": "1.0.0.0",
"name": "ApiCall Test Extension",
- "description": "An extension for an extension UITest."
+ "description": "An extension for an extension UITest.",
+ "permissions": ["tabs"]
}
diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc
index b223f88..dbc61a7 100644
--- a/chrome/test/render_view_test.cc
+++ b/chrome/test/render_view_test.cc
@@ -5,6 +5,7 @@
#include "chrome/test/render_view_test.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/common/extensions/extension.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/renderer_preferences.h"
@@ -80,6 +81,11 @@ void RenderViewTest::SetUp() {
ExtensionFunctionDispatcher::GetAllFunctionNames(&names);
ExtensionProcessBindings::SetFunctionNames(names);
+ std::vector<std::string> permissions(
+ Extension::kPermissionNames,
+ Extension::kPermissionNames + Extension::kNumPermissions);
+ ExtensionProcessBindings::SetPermissions("", permissions);
+
mock_process_.reset(new MockProcess());
render_thread_.set_routing_id(kRouteId);