diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 08:40:49 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 08:40:49 +0000 |
commit | d725947e8a370c790794a66fd36d349b7b33b8b8 (patch) | |
tree | a4e71071b7efee3341da93b451989b95ba8f8920 /chrome | |
parent | c83658c33bdf286c7d4cf8f766616e297624daec (diff) | |
download | chromium_src-d725947e8a370c790794a66fd36d349b7b33b8b8.zip chromium_src-d725947e8a370c790794a66fd36d349b7b33b8b8.tar.gz chromium_src-d725947e8a370c790794a66fd36d349b7b33b8b8.tar.bz2 |
Enforce extension permissions in C++ (instead of Javascript).
BUG=38920
TEST=ExtensionApiTest.Incognito
Review URL: http://codereview.chromium.org/1148009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42441 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
19 files changed, 72 insertions, 57 deletions
diff --git a/chrome/browser/automation/extension_port_container.cc b/chrome/browser/automation/extension_port_container.cc index 1fd4b70..e167e7e 100644 --- a/chrome/browser/automation/extension_port_container.cc +++ b/chrome/browser/automation/extension_port_container.cc @@ -112,7 +112,9 @@ bool ExtensionPortContainer::Send(IPC::Message *message) { } void ExtensionPortContainer::OnExtensionMessageInvoke( - const std::string& function_name, const ListValue& args) { + const std::string& function_name, + const ListValue& args, + bool requires_incognito_access) { if (function_name == ExtensionMessageService::kDispatchOnMessage) { DCHECK_EQ(args.GetSize(), 2u); diff --git a/chrome/browser/automation/extension_port_container.h b/chrome/browser/automation/extension_port_container.h index a9d61ef..b74709d 100644 --- a/chrome/browser/automation/extension_port_container.h +++ b/chrome/browser/automation/extension_port_container.h @@ -63,7 +63,8 @@ class ExtensionPortContainer : public IPC::Message::Sender { void SendConnectionResponse(int connection_id, int port_id); void OnExtensionMessageInvoke(const std::string& function_name, - const ListValue& args); + const ListValue& args, + bool requires_incognito_access); void OnExtensionHandleMessage(const std::string& message, int source_port_id); void OnExtensionPortDisconnected(int source_port_id); diff --git a/chrome/browser/debugger/extension_ports_remote_service.cc b/chrome/browser/debugger/extension_ports_remote_service.cc index df549fd..c4380d5 100644 --- a/chrome/browser/debugger/extension_ports_remote_service.cc +++ b/chrome/browser/debugger/extension_ports_remote_service.cc @@ -241,7 +241,9 @@ bool ExtensionPortsRemoteService::Send(IPC::Message *message) { } void ExtensionPortsRemoteService::OnExtensionMessageInvoke( - const std::string& function_name, const ListValue& args) { + const std::string& function_name, + const ListValue& args, + bool requires_incognito_access) { if (function_name == ExtensionMessageService::kDispatchOnMessage) { DCHECK_EQ(args.GetSize(), 2u); std::string message; diff --git a/chrome/browser/debugger/extension_ports_remote_service.h b/chrome/browser/debugger/extension_ports_remote_service.h index 005905c..3a9e53b 100644 --- a/chrome/browser/debugger/extension_ports_remote_service.h +++ b/chrome/browser/debugger/extension_ports_remote_service.h @@ -73,8 +73,9 @@ class ExtensionPortsRemoteService : public DevToolsRemoteListener, const std::string& destination); // Handles a message from the ExtensionMessageService. - void OnExtensionMessageInvoke( - const std::string& function_name, const ListValue& args); + void OnExtensionMessageInvoke(const std::string& function_name, + const ListValue& args, + bool requires_incognito_access); // Handles a message sent from an extension through the // ExtensionMessageService, to be passed to the external client. void OnExtensionMessage(const std::string& message, int port_id); diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc index 45b5304..2586151 100644 --- a/chrome/browser/extensions/extension_message_service.cc +++ b/chrome/browser/extensions/extension_message_service.cc @@ -69,16 +69,16 @@ static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, args.Set(3, Value::CreateStringValue(source_extension_id)); args.Set(4, Value::CreateStringValue(target_extension_id)); CHECK(port.sender); - port.sender->Send(new ViewMsg_ExtensionMessageInvoke( - port.routing_id, ExtensionMessageService::kDispatchOnConnect, args)); + port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, + ExtensionMessageService::kDispatchOnConnect, args, false)); } static void DispatchOnDisconnect( const ExtensionMessageService::MessagePort& port, int source_port_id) { ListValue args; args.Set(0, Value::CreateIntegerValue(source_port_id)); - port.sender->Send(new ViewMsg_ExtensionMessageInvoke( - port.routing_id, ExtensionMessageService::kDispatchOnDisconnect, args)); + port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, + ExtensionMessageService::kDispatchOnDisconnect, args, false)); } static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, @@ -86,8 +86,8 @@ static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, ListValue args; args.Set(0, Value::CreateStringValue(message)); args.Set(1, Value::CreateIntegerValue(source_port_id)); - port.sender->Send(new ViewMsg_ExtensionMessageInvoke( - port.routing_id, ExtensionMessageService::kDispatchOnMessage, args)); + port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, + ExtensionMessageService::kDispatchOnMessage, args, false)); } static void DispatchEvent(const ExtensionMessageService::MessagePort& port, @@ -97,9 +97,8 @@ static void DispatchEvent(const ExtensionMessageService::MessagePort& port, ListValue args; args.Set(0, Value::CreateStringValue(event_name)); args.Set(1, Value::CreateStringValue(event_args)); - args.Set(2, Value::CreateBooleanValue(has_incognito_data)); - port.sender->Send(new ViewMsg_ExtensionMessageInvoke( - port.routing_id, ExtensionMessageService::kDispatchEvent, args)); + port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, + ExtensionMessageService::kDispatchEvent, args, has_incognito_data)); } } // namespace diff --git a/chrome/browser/extensions/extension_messages_unittest.cc b/chrome/browser/extensions/extension_messages_unittest.cc index 98d4db0..5d06654 100644 --- a/chrome/browser/extensions/extension_messages_unittest.cc +++ b/chrome/browser/extensions/extension_messages_unittest.cc @@ -18,14 +18,14 @@ static void DispatchOnConnect(int source_port_id, const std::string& name, args.Set(3, Value::CreateStringValue("")); // extension ID is empty for tests args.Set(4, Value::CreateStringValue("")); // extension ID is empty for tests RendererExtensionBindings::Invoke( - ExtensionMessageService::kDispatchOnConnect, args, NULL); + ExtensionMessageService::kDispatchOnConnect, args, NULL, false); } static void DispatchOnDisconnect(int source_port_id) { ListValue args; args.Set(0, Value::CreateIntegerValue(source_port_id)); RendererExtensionBindings::Invoke( - ExtensionMessageService::kDispatchOnDisconnect, args, NULL); + ExtensionMessageService::kDispatchOnDisconnect, args, NULL, false); } static void DispatchOnMessage(const std::string& message, int source_port_id) { @@ -33,7 +33,7 @@ static void DispatchOnMessage(const std::string& message, int source_port_id) { args.Set(0, Value::CreateStringValue(message)); args.Set(1, Value::CreateIntegerValue(source_port_id)); RendererExtensionBindings::Invoke( - ExtensionMessageService::kDispatchOnMessage, args, NULL); + ExtensionMessageService::kDispatchOnMessage, args, NULL, false); } // Tests that the bindings for opening a channel to an extension and sending diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index adac8b5..afc9a4c 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -707,9 +707,10 @@ IPC_BEGIN_MESSAGES(View) // target process. If routed, it will be restricted to the contexts that // are part of the target RenderView. // |args| is a list of primitive Value types that are passed to the function. - IPC_MESSAGE_ROUTED2(ViewMsg_ExtensionMessageInvoke, + IPC_MESSAGE_ROUTED3(ViewMsg_ExtensionMessageInvoke, std::string /* function_name */, - ListValue /* args */) + ListValue /* args */, + bool /* requires incognito access */) // Tell the renderer process all known extension function names. IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetFunctionNames, diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index a751785..f1dfa19 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -128,6 +128,14 @@ class ExtensionImpl : public ExtensionBase { } }; +// Returns true if the extension running in the given |context| has sufficient +// permissions to access the data. +static bool HasSufficientPermissions(ContextInfo* context, + bool requires_incognito_access) { + return (!requires_incognito_access || + ExtensionProcessBindings::HasIncognitoEnabled(context->extension_id)); +} + } // namespace const char* EventBindings::kName = "chrome/EventBindings"; @@ -290,7 +298,8 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) { // static void EventBindings::CallFunction(const std::string& function_name, int argc, v8::Handle<v8::Value>* argv, - RenderView* render_view) { + RenderView* render_view, + bool requires_incognito_access) { // We copy the context list, because calling into javascript may modify it // out from under us. We also guard against deleted contexts by checking if // they have been cleared first. @@ -300,8 +309,13 @@ void EventBindings::CallFunction(const std::string& function_name, it != contexts.end(); ++it) { if (render_view && render_view != (*it)->render_view) continue; + if ((*it)->context.IsEmpty()) continue; + + if (!HasSufficientPermissions(it->get(), requires_incognito_access)) + continue; + v8::Handle<v8::Value> retval = CallFunctionInContext((*it)->context, function_name, argc, argv); // In debug, the js will validate the event parameters and return a diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h index 736cb8a..74edb68 100644 --- a/chrome/renderer/extensions/event_bindings.h +++ b/chrome/renderer/extensions/event_bindings.h @@ -39,7 +39,8 @@ class EventBindings { // v8::Undefined(). A DCHECK is setup to break if it is otherwise. static void CallFunction(const std::string& function_name, int argc, v8::Handle<v8::Value>* argv, - RenderView* render_view); + RenderView* render_view, + bool requires_incognito_access); }; #endif // CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 694c276..78285b1 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -71,7 +71,7 @@ struct SingletonData { std::set<std::string> function_names_; PageActionIdMap page_action_ids_; ExtensionPermissionsMap permissions_; - std::map<std::string, bool> incognito_enabled_map_; + IncognitoEnabledMap incognito_enabled_map_; }; static std::set<std::string>* GetFunctionNameSet() { @@ -245,8 +245,6 @@ class ExtensionImpl : public ExtensionBase { return v8::FunctionTemplate::New(GetPopupParentWindow); } else if (name->Equals(v8::String::New("SetExtensionActionIcon"))) { return v8::FunctionTemplate::New(SetExtensionActionIcon); - } else if (name->Equals(v8::String::New("CanAccessIncognito"))) { - return v8::FunctionTemplate::New(CanAccessIncognito); } return ExtensionBase::GetNativeFunction(name); @@ -505,16 +503,6 @@ class ExtensionImpl : public ExtensionBase { return StartRequestCommon(args, dict); } - // Returns true if the extension can access incognito data. - static v8::Handle<v8::Value> CanAccessIncognito(const v8::Arguments& args) { - std::string extension_id = ExtensionIdForCurrentContext(); - if (extension_id.empty()) - return v8::False(); - - bool enabled = (*GetIncognitoEnabledMap())[extension_id]; - return v8::Boolean::New(enabled); - } - static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) { RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); if (!renderview) @@ -546,6 +534,12 @@ void ExtensionProcessBindings::SetIncognitoEnabled( } // static +bool ExtensionProcessBindings::HasIncognitoEnabled( + const std::string& extension_id) { + return (!extension_id.empty() && (*GetIncognitoEnabledMap())[extension_id]); +} + +// static void ExtensionProcessBindings::HandleResponse(int request_id, bool success, const std::string& response, const std::string& error) { diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h index 93c7d24..e95e737 100644 --- a/chrome/renderer/extensions/extension_process_bindings.h +++ b/chrome/renderer/extensions/extension_process_bindings.h @@ -50,6 +50,9 @@ class ExtensionProcessBindings { static void SetIncognitoEnabled(const std::string& extension_id, bool enabled); + // Checks whether incognito is enabled for a particular extension. + static bool HasIncognitoEnabled(const std::string& extension_id); + // 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. diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index 5e78932b..d393089 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -298,8 +298,13 @@ v8::Extension* RendererExtensionBindings::Get() { void RendererExtensionBindings::Invoke(const std::string& function_name, const ListValue& args, - RenderView* renderview) { + RenderView* renderview, + bool requires_incognito_access) { v8::HandleScope handle_scope; std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args); - EventBindings::CallFunction(function_name, argv.size(), &argv[0], renderview); + EventBindings::CallFunction(function_name, + argv.size(), + &argv[0], + renderview, + requires_incognito_access); } diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h index 89e903d..04233f6 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.h +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -24,7 +24,7 @@ class RendererExtensionBindings { // Call the given javascript function with the specified arguments. static void Invoke(const std::string& function_name, const ListValue& args, - RenderView* renderview); + RenderView* renderview, bool requires_incognito_access); }; #endif // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 6448cf5..ab97f2a 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -865,8 +865,9 @@ void RenderThread::ScheduleIdleHandler(double initial_delay_s) { } void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, - const ListValue& args) { - RendererExtensionBindings::Invoke(function_name, args, NULL); + const ListValue& args, + bool requires_incognito_access) { + RendererExtensionBindings::Invoke(function_name, args, NULL, requires_incognito_access); // Reset the idle handler each time there's any activity like event or message // dispatch, for which Invoke is the chokepoint. diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 504ecc5..fea7e41 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -208,7 +208,8 @@ class RenderThread : public RenderThreadBase, void OnGetV8HeapStats(); void OnExtensionMessageInvoke(const std::string& function_name, - const ListValue& args); + const ListValue& args, + bool requires_incognito_access); void OnPurgeMemory(); void OnPurgePluginListCache(bool reload_pages); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index c0d5b3f..fb2e70e 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -4109,8 +4109,10 @@ void RenderView::InjectToolstripCSS() { } void RenderView::OnExtensionMessageInvoke(const std::string& function_name, - const ListValue& args) { - RendererExtensionBindings::Invoke(function_name, args, this); + const ListValue& args, + bool requires_incognito_access) { + RendererExtensionBindings::Invoke( + function_name, args, this, requires_incognito_access); } // Dump all load time histograms. diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 3695545..0c4e660 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -714,7 +714,8 @@ class RenderView : public RenderWidget, void OnClearAccessibilityInfo(int acc_obj_id, bool clear_all); void OnExtensionMessageInvoke(const std::string& function_name, - const ListValue& args); + const ListValue& args, + bool requires_incognito_access); void OnMoveOrResizeStarted(); diff --git a/chrome/renderer/resources/event_bindings.js b/chrome/renderer/resources/event_bindings.js index 7ea6bbf..aaea01c 100644 --- a/chrome/renderer/resources/event_bindings.js +++ b/chrome/renderer/resources/event_bindings.js @@ -45,20 +45,12 @@ var chrome = chrome || {}; // An array of all attached event objects, used for detaching on unload. var allAttachedEvents = []; - // By default (for content scripts), this function returns false. Extension - // contexts override this to do the right thing. - chromeHidden.canAccessIncognito = function() { - return false; - } - chromeHidden.Event = {}; // Dispatches a named event with the given JSON array, which is deserialized // before dispatch. The JSON array is the list of arguments that will be // sent with the event callback. - chromeHidden.Event.dispatchJSON = function(name, args, hasIncognitoData) { - if (hasIncognitoData && !chromeHidden.canAccessIncognito()) - return; + chromeHidden.Event.dispatchJSON = function(name, args) { if (attachedNamedEvents[name]) { if (args) { args = JSON.parse(args); diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index 7e803b5..5d80919 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -18,17 +18,12 @@ var chrome = chrome || {}; native function GetPopupParentWindow(); native function GetPopupView(); native function SetExtensionActionIcon(); - native function CanAccessIncognito(); if (!chrome) chrome = {}; var chromeHidden = GetChromeHidden(); - chromeHidden.canAccessIncognito = function() { - return CanAccessIncognito(); - } - // Validate arguments. chromeHidden.validationTypes = []; chromeHidden.validate = function(args, schemas) { |