diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 14:43:02 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 14:43:02 +0000 |
commit | 173e5e807c62bb789ad46598e46367e019180568 (patch) | |
tree | f7d90e64a28b55e2e8417a2ab8ad997392c5836a /chrome | |
parent | c0a9f12a2dbb98ff17d9fd02b250c5deeeed9a85 (diff) | |
download | chromium_src-173e5e807c62bb789ad46598e46367e019180568.zip chromium_src-173e5e807c62bb789ad46598e46367e019180568.tar.gz chromium_src-173e5e807c62bb789ad46598e46367e019180568.tar.bz2 |
Reland 44348 Add support for restricting broadcasting events to extensions based on host permissions
BUG=38398
TEST=none
TBR=jochen@chromium.org
Review URL: http://codereview.chromium.org/1642005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44351 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
35 files changed, 227 insertions, 65 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 1aac1b1..e6a0360 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -2202,7 +2202,7 @@ bool AutomationProvider::InterceptBrowserEventMessageFromExternalHost( if (profile()->GetExtensionMessageService()) { profile()->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile()->IsOffTheRecord()); + event_name, json_args, profile()->IsOffTheRecord(), GURL()); } return true; diff --git a/chrome/browser/automation/extension_port_container.cc b/chrome/browser/automation/extension_port_container.cc index e167e7e..e93f42c 100644 --- a/chrome/browser/automation/extension_port_container.cc +++ b/chrome/browser/automation/extension_port_container.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -114,7 +114,8 @@ bool ExtensionPortContainer::Send(IPC::Message *message) { void ExtensionPortContainer::OnExtensionMessageInvoke( const std::string& function_name, const ListValue& args, - bool requires_incognito_access) { + bool requires_incognito_access, + const GURL& event_url) { 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 b74709d..8fd8299 100644 --- a/chrome/browser/automation/extension_port_container.h +++ b/chrome/browser/automation/extension_port_container.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,6 +13,7 @@ class AutomationProvider; class ExtensionMessageService; +class GURL; class ListValue; class MessageLoop; class RenderViewHost; @@ -64,7 +65,8 @@ class ExtensionPortContainer : public IPC::Message::Sender { void OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url); 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 c4380d5..d2a05ea 100644 --- a/chrome/browser/debugger/extension_ports_remote_service.cc +++ b/chrome/browser/debugger/extension_ports_remote_service.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -243,7 +243,8 @@ bool ExtensionPortsRemoteService::Send(IPC::Message *message) { void ExtensionPortsRemoteService::OnExtensionMessageInvoke( const std::string& function_name, const ListValue& args, - bool requires_incognito_access) { + bool requires_incognito_access, + const GURL& event_url) { 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 3a9e53b..6067f44 100644 --- a/chrome/browser/debugger/extension_ports_remote_service.h +++ b/chrome/browser/debugger/extension_ports_remote_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -21,6 +21,7 @@ class DevToolsProtocolHandler; class DevToolsRemoteMessage; class DictionaryValue; +class GURL; class ListValue; class Value; @@ -75,7 +76,8 @@ class ExtensionPortsRemoteService : public DevToolsRemoteListener, // Handles a message from the ExtensionMessageService. void OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url); // 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_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc index 3b6a28f..aebdda2 100644 --- a/chrome/browser/extensions/extension_accessibility_api.cc +++ b/chrome/browser/extensions/extension_accessibility_api.cc @@ -176,7 +176,7 @@ void ExtensionAccessibilityEventRouter::DispatchEvent( const std::string& json_args) { if (enabled_ && profile && profile->GetExtensionMessageService()) { profile->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile->IsOffTheRecord()); + event_name, json_args, profile->IsOffTheRecord(), GURL()); } } diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc index d057731..9b577a8 100644 --- a/chrome/browser/extensions/extension_bookmark_manager_api.cc +++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc @@ -156,7 +156,7 @@ void ExtensionBookmarkManagerEventRouter::DispatchEvent(const char* event_name, std::string json_args; base::JSONWriter::Write(args, false, &json_args); profile_->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile_->IsOffTheRecord()); + event_name, json_args, profile_->IsOffTheRecord(), GURL()); } void ExtensionBookmarkManagerEventRouter::DispatchDragEvent( diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc index 6a8cd08..629ae76 100644 --- a/chrome/browser/extensions/extension_bookmarks_module.cc +++ b/chrome/browser/extensions/extension_bookmarks_module.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -95,7 +95,7 @@ void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile, const std::string json_args) { if (profile->GetExtensionMessageService()) { profile->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile->IsOffTheRecord()); + event_name, json_args, profile->IsOffTheRecord(), GURL()); } } diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc index 9b379bc..52d26da 100644 --- a/chrome/browser/extensions/extension_browser_event_router.cc +++ b/chrome/browser/extensions/extension_browser_event_router.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -89,7 +89,7 @@ static void DispatchEvent(Profile* profile, const std::string json_args) { if (profile->GetExtensionMessageService()) { profile->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile->IsOffTheRecord()); + event_name, json_args, profile->IsOffTheRecord(), GURL()); } } diff --git a/chrome/browser/extensions/extension_devtools_bridge.cc b/chrome/browser/extensions/extension_devtools_bridge.cc index a6399d8..d452c04 100644 --- a/chrome/browser/extensions/extension_devtools_bridge.cc +++ b/chrome/browser/extensions/extension_devtools_bridge.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -65,7 +65,7 @@ void ExtensionDevToolsBridge::InspectedTabClosing() { // event in extensions. std::string json("[{}]"); profile_->GetExtensionMessageService()->DispatchEventToRenderers( - on_tab_close_event_name_, json, profile_->IsOffTheRecord()); + on_tab_close_event_name_, json, profile_->IsOffTheRecord(), GURL()); // This may result in this object being destroyed. extension_devtools_manager_->BridgeClosingForTab(tab_id_); @@ -88,7 +88,7 @@ void ExtensionDevToolsBridge::OnRpcMessage(const DevToolsMessageData& data) { && data.method_name == kApuPageEventMessageName) { std::string json = StringPrintf("[%s]", data.arguments[0].c_str()); profile_->GetExtensionMessageService()->DispatchEventToRenderers( - on_page_event_name_, json, profile_->IsOffTheRecord()); + on_page_event_name_, json, profile_->IsOffTheRecord(), GURL()); } } diff --git a/chrome/browser/extensions/extension_history_api.cc b/chrome/browser/extensions/extension_history_api.cc index 1614a80..400c163 100644 --- a/chrome/browser/extensions/extension_history_api.cc +++ b/chrome/browser/extensions/extension_history_api.cc @@ -143,7 +143,7 @@ void ExtensionHistoryEventRouter::DispatchEvent(Profile* profile, const std::string& json_args) { if (profile && profile->GetExtensionMessageService()) { profile->GetExtensionMessageService()->DispatchEventToRenderers( - event_name, json_args, profile->IsOffTheRecord()); + event_name, json_args, profile->IsOffTheRecord(), GURL()); } } diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc index 688e4be..949993f 100644 --- a/chrome/browser/extensions/extension_idle_api.cc +++ b/chrome/browser/extensions/extension_idle_api.cc @@ -152,5 +152,6 @@ void ExtensionIdleEventRouter::OnIdleStateChange(Profile* profile, profile->GetExtensionMessageService()->DispatchEventToRenderers( keys::kOnStateChanged, json_args, - profile->IsOffTheRecord()); + profile->IsOffTheRecord(), + GURL()); } diff --git a/chrome/browser/extensions/extension_menu_manager.cc b/chrome/browser/extensions/extension_menu_manager.cc index 809085e..bbf9909 100644 --- a/chrome/browser/extensions/extension_menu_manager.cc +++ b/chrome/browser/extensions/extension_menu_manager.cc @@ -316,7 +316,7 @@ void ExtensionMenuManager::ExecuteCommand(Profile* profile, base::JSONWriter::Write(&args, false, &json_args); std::string event_name = "contextMenu/" + item->extension_id(); service->DispatchEventToRenderers(event_name, json_args, - profile->IsOffTheRecord()); + profile->IsOffTheRecord(), GURL()); } void ExtensionMenuManager::Observe(NotificationType type, diff --git a/chrome/browser/extensions/extension_menu_manager_unittest.cc b/chrome/browser/extensions/extension_menu_manager_unittest.cc index e81fc04..bdc282e 100644 --- a/chrome/browser/extensions/extension_menu_manager_unittest.cc +++ b/chrome/browser/extensions/extension_menu_manager_unittest.cc @@ -201,9 +201,10 @@ class MockExtensionMessageService : public ExtensionMessageService { explicit MockExtensionMessageService(Profile* profile) : ExtensionMessageService(profile) {} - MOCK_METHOD3(DispatchEventToRenderers, void(const std::string& event_name, + MOCK_METHOD4(DispatchEventToRenderers, void(const std::string& event_name, const std::string& event_args, - bool has_incognito_data)); + bool has_incognito_data, + const GURL& event_url)); private: DISALLOW_COPY_AND_ASSIGN(MockExtensionMessageService); @@ -254,7 +255,8 @@ TEST_F(ExtensionMenuManagerTest, ExecuteCommand) { std::string expected_event_name = "contextMenu/" + item->extension_id(); EXPECT_CALL(*mock_message_service.get(), DispatchEventToRenderers(expected_event_name, _, - profile.IsOffTheRecord())) + profile.IsOffTheRecord(), + GURL())) .Times(1) .WillOnce(SaveArg<1>(&event_args)); diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc index 2586151..731e7b8 100644 --- a/chrome/browser/extensions/extension_message_service.cc +++ b/chrome/browser/extensions/extension_message_service.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -70,7 +70,7 @@ static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, args.Set(4, Value::CreateStringValue(target_extension_id)); CHECK(port.sender); port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, - ExtensionMessageService::kDispatchOnConnect, args, false)); + ExtensionMessageService::kDispatchOnConnect, args, false, GURL())); } static void DispatchOnDisconnect( @@ -78,7 +78,7 @@ static void DispatchOnDisconnect( ListValue args; args.Set(0, Value::CreateIntegerValue(source_port_id)); port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, - ExtensionMessageService::kDispatchOnDisconnect, args, false)); + ExtensionMessageService::kDispatchOnDisconnect, args, false, GURL())); } static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, @@ -87,18 +87,20 @@ static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, 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, false)); + ExtensionMessageService::kDispatchOnMessage, args, false, GURL())); } static void DispatchEvent(const ExtensionMessageService::MessagePort& port, const std::string& event_name, const std::string& event_args, - bool has_incognito_data) { + bool has_incognito_data, + const GURL& event_url) { ListValue args; args.Set(0, Value::CreateStringValue(event_name)); args.Set(1, Value::CreateStringValue(event_args)); port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, - ExtensionMessageService::kDispatchEvent, args, has_incognito_data)); + ExtensionMessageService::kDispatchEvent, args, has_incognito_data, + event_url)); } } // namespace @@ -456,7 +458,7 @@ void ExtensionMessageService::PostMessageFromRenderer( void ExtensionMessageService::DispatchEventToRenderers( const std::string& event_name, const std::string& event_args, - bool has_incognito_data) { + bool has_incognito_data, const GURL& event_url) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); std::set<int>& pids = listeners_[event_name]; @@ -472,7 +474,8 @@ void ExtensionMessageService::DispatchEventToRenderers( continue; } - DispatchEvent(renderer, event_name, event_args, has_incognito_data); + DispatchEvent( + renderer, event_name, event_args, has_incognito_data, event_url); } } diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h index 7d7540e..c205bb9 100644 --- a/chrome/browser/extensions/extension_message_service.h +++ b/chrome/browser/extensions/extension_message_service.h @@ -16,6 +16,7 @@ #include "chrome/browser/extensions/extension_devtools_manager.h" #include "ipc/ipc_message.h" +class GURL; class MessageLoop; class Profile; class RenderProcessHost; @@ -80,10 +81,13 @@ class ExtensionMessageService // Sends a message from a renderer to the given port. void PostMessageFromRenderer(int port_id, const std::string& message); - // Send an event to every registered extension renderer. + // Send an event to every registered extension renderer. If + // |has_incognito_data| is true, the event is only sent to extension with the + // permission to access incognito data. If |event_url| is not empty, the + // event is only sent to extension with host permissions for this url. virtual void DispatchEventToRenderers( const std::string& event_name, const std::string& event_args, - bool has_incognito_data); + bool has_incognito_data, const GURL& event_url); // Given an extension ID, opens a channel between the given // automation "port" or DevTools service and that extension. the diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc index e2e969f..cc412d9 100644 --- a/chrome/browser/extensions/extension_messages_apitest.cc +++ b/chrome/browser/extensions/extension_messages_apitest.cc @@ -3,6 +3,50 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/extensions/extension_message_service.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_registrar.h" + +namespace { + +class MessageSender : public NotificationObserver { + public: + MessageSender() { + registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING, + NotificationService::AllSources()); + } + + private: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + ExtensionMessageService* message_service = + Source<Profile>(source).ptr()->GetExtensionMessageService(); + + // Sends four messages to the extension. All but the third message sent + // from the origin http://b.com/ are supposed to arrive. + message_service->DispatchEventToRenderers("test.onMessage", + "[{\"lastMessage\":false,\"data\":\"no restriction\"}]", + Source<Profile>(source).ptr()->IsOffTheRecord(), + GURL()); + message_service->DispatchEventToRenderers("test.onMessage", + "[{\"lastMessage\":false,\"data\":\"http://a.com/\"}]", + Source<Profile>(source).ptr()->IsOffTheRecord(), + GURL("http://a.com/")); + message_service->DispatchEventToRenderers("test.onMessage", + "[{\"lastMessage\":false,\"data\":\"http://b.com/\"}]", + Source<Profile>(source).ptr()->IsOffTheRecord(), + GURL("http://b.com/")); + message_service->DispatchEventToRenderers("test.onMessage", + "[{\"lastMessage\":true,\"data\":\"last message\"}]", + Source<Profile>(source).ptr()->IsOffTheRecord(), + GURL()); + } + + NotificationRegistrar registrar_; +}; + +} // namespace // Tests that message passing between extensions and content scripts works. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Messaging) { @@ -20,3 +64,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingExternal) { ASSERT_TRUE(RunExtensionTest("messaging/connect_external")) << message_; } + +// Tests that messages with event_urls are only passed to extensions with +// appropriate permissions. +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingEventURL) { + MessageSender sender; + ASSERT_TRUE(RunExtensionTest("messaging/event_url")) << message_; +} diff --git a/chrome/browser/extensions/extension_messages_unittest.cc b/chrome/browser/extensions/extension_messages_unittest.cc index 5d06654..b90e92f 100644 --- a/chrome/browser/extensions/extension_messages_unittest.cc +++ b/chrome/browser/extensions/extension_messages_unittest.cc @@ -18,14 +18,15 @@ 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, false); + ExtensionMessageService::kDispatchOnConnect, args, NULL, false, GURL()); } static void DispatchOnDisconnect(int source_port_id) { ListValue args; args.Set(0, Value::CreateIntegerValue(source_port_id)); RendererExtensionBindings::Invoke( - ExtensionMessageService::kDispatchOnDisconnect, args, NULL, false); + ExtensionMessageService::kDispatchOnDisconnect, args, NULL, false, + GURL()); } static void DispatchOnMessage(const std::string& message, int source_port_id) { @@ -33,7 +34,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, false); + ExtensionMessageService::kDispatchOnMessage, args, NULL, false, GURL()); } // Tests that the bindings for opening a channel to an extension and sending diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc index f73dc7f..a6f85f2 100644 --- a/chrome/browser/extensions/extension_popup_api.cc +++ b/chrome/browser/extensions/extension_popup_api.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -353,5 +353,6 @@ void PopupEventRouter::OnPopupClosed(Profile* profile, profile->GetExtensionMessageService()->DispatchEventToRenderers( full_event_name, base::JSONWriter::kEmptyArray, - profile->IsOffTheRecord()); + profile->IsOffTheRecord(), + GURL()); } diff --git a/chrome/browser/extensions/extension_toolstrip_api.cc b/chrome/browser/extensions/extension_toolstrip_api.cc index a858150..3732c68 100644 --- a/chrome/browser/extensions/extension_toolstrip_api.cc +++ b/chrome/browser/extensions/extension_toolstrip_api.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -145,7 +145,7 @@ void ToolstripEventRouter::DispatchEvent(Profile *profile, base::JSONWriter::Write(&json, false, &json_args); std::string full_event_name = StringPrintf(event_name, routing_id); profile->GetExtensionMessageService()->DispatchEventToRenderers( - full_event_name, json_args, profile->IsOffTheRecord()); + full_event_name, json_args, profile->IsOffTheRecord(), GURL()); } } diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index 30b3f12..51434bc 100755 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -2710,7 +2710,24 @@ ] } ], - "events": [] + "events": [ + { + "name": "onMessage", + "type": "function", + "unprivileged": true, + "description": "Used to test sending messages to extensions.", + "parameters": [ + { + "type": "object", + "name": "info", + "properties": { + "data": { "type": "string", "description": "Additional information." }, + "lastMessage": { "type": "boolean", "description": "True if this was the last message for this test" } + } + } + ] + } + ] }, { "namespace": "experimental.clipboard", diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 2e8b5bf..0ec3183 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -885,6 +885,11 @@ void Extension::DecodeIconFromPath(const FilePath& icon_path, result->swap(decoded); } +GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) { + return GURL(std::string(chrome::kExtensionScheme) + + chrome::kStandardSchemeSeparator + extension_id + "/"); +} + bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, std::string* error) { if (source.HasKey(keys::kPublicKey)) { @@ -912,8 +917,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, manifest_value_.reset(static_cast<DictionaryValue*>(source.DeepCopy())); // Initialize the URL. - extension_url_ = GURL(std::string(chrome::kExtensionScheme) + - chrome::kStandardSchemeSeparator + id_ + "/"); + extension_url_ = Extension::GetBaseURLFromExtensionId(id_); // Initialize version. std::string version_str; diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index 7d6ac39..6cc385c 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -203,6 +203,9 @@ class Extension { Icons icon_size, scoped_ptr<SkBitmap>* result); + // Returns the base extension url for a given |extension_id|. + static GURL GetBaseURLFromExtensionId(const std::string& extension_id); + // Initialize the extension from a parsed manifest. // Usually, the id of an extension is generated by the "key" property of // its manifest, but if |require_key| is |false|, a temporary ID will be diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index a1028b2..bbfd9d1 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -716,10 +716,11 @@ 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_ROUTED3(ViewMsg_ExtensionMessageInvoke, + IPC_MESSAGE_ROUTED4(ViewMsg_ExtensionMessageInvoke, std::string /* function_name */, ListValue /* args */, - bool /* requires incognito access */) + bool /* requires incognito access */, + GURL /* event URL */) // 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 f1dfa19..3e5c72b 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,9 +13,12 @@ #include "chrome/renderer/extensions/js_only_v8_extensions.h" #include "chrome/renderer/render_thread.h" #include "chrome/renderer/render_view.h" +#include "googleurl/src/gurl.h" #include "grit/renderer_resources.h" #include "third_party/WebKit/WebKit/chromium/public/WebDataSource.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURL.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" using bindings_utils::CallFunctionInContext; @@ -27,7 +30,10 @@ using bindings_utils::GetStringResource; using bindings_utils::ExtensionBase; using bindings_utils::GetPendingRequestMap; using bindings_utils::PendingRequestMap; +using WebKit::WebDataSource; using WebKit::WebFrame; +using WebKit::WebSecurityOrigin; +using WebKit::WebURL; static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, void*); @@ -131,9 +137,23 @@ 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)); + bool requires_incognito_access, + const GURL& event_url) { + v8::Context::Scope context_scope(context->context); + + bool incognito_permissions_ok = (!requires_incognito_access || + ExtensionProcessBindings::HasIncognitoEnabled(context->extension_id)); + if (!incognito_permissions_ok) + return false; + + RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); + bool url_permissions_ok = (!event_url.is_valid() || + (renderview && + GURL(renderview->webview()->mainFrame()->url()).SchemeIs( + chrome::kExtensionScheme) && + renderview->webview()->mainFrame()->securityOrigin().canRequest( + event_url))); + return url_permissions_ok; } } // namespace @@ -225,7 +245,7 @@ void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) { // Figure out the frame's URL. If the frame is loading, use its provisional // URL, since we get this notification before commit. - WebKit::WebDataSource* ds = frame->provisionalDataSource(); + WebDataSource* ds = frame->provisionalDataSource(); if (!ds) ds = frame->dataSource(); GURL url = ds->request().url(); @@ -299,7 +319,8 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) { void EventBindings::CallFunction(const std::string& function_name, int argc, v8::Handle<v8::Value>* argv, RenderView* render_view, - bool requires_incognito_access) { + bool requires_incognito_access, + const GURL& event_url) { // 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. @@ -313,8 +334,11 @@ void EventBindings::CallFunction(const std::string& function_name, if ((*it)->context.IsEmpty()) continue; - if (!HasSufficientPermissions(it->get(), requires_incognito_access)) + if (!HasSufficientPermissions(it->get(), + requires_incognito_access, + event_url)) { continue; + } v8::Handle<v8::Value> retval = CallFunctionInContext((*it)->context, function_name, argc, argv); diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h index 74edb68..dd396ee 100644 --- a/chrome/renderer/extensions/event_bindings.h +++ b/chrome/renderer/extensions/event_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ #include "v8/include/v8.h" +class GURL; class RenderThreadBase; class RenderView; @@ -40,7 +41,8 @@ class EventBindings { static void CallFunction(const std::string& function_name, int argc, v8::Handle<v8::Value>* argv, RenderView* render_view, - bool requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url); }; #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 3232237..fe8abcd 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -87,7 +87,7 @@ static PermissionsMap* GetPermissionsMap(const std::string& extension_id) { return &Singleton<SingletonData>()->permissions_[extension_id]; } -static std::map<std::string, bool>* GetIncognitoEnabledMap() { +static IncognitoEnabledMap* GetIncognitoEnabledMap() { return &Singleton<SingletonData>()->incognito_enabled_map_; } diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index d393089..6c43944 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -299,12 +299,14 @@ v8::Extension* RendererExtensionBindings::Get() { void RendererExtensionBindings::Invoke(const std::string& function_name, const ListValue& args, RenderView* renderview, - bool requires_incognito_access) { + bool requires_incognito_access, + const GURL& event_url) { v8::HandleScope handle_scope; std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args); EventBindings::CallFunction(function_name, argv.size(), &argv[0], renderview, - requires_incognito_access); + requires_incognito_access, + event_url); } diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h index 04233f6..3e70e8f 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.h +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -9,6 +9,7 @@ #include <string> +class GURL; class ListValue; class RenderView; @@ -24,7 +25,8 @@ class RendererExtensionBindings { // Call the given javascript function with the specified arguments. static void Invoke(const std::string& function_name, const ListValue& args, - RenderView* renderview, bool requires_incognito_access); + RenderView* renderview, bool requires_incognito_access, + const GURL& event_url); }; #endif // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 3a0385a..fc243d8 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -917,8 +917,10 @@ void RenderThread::ScheduleIdleHandler(double initial_delay_s) { void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access) { - RendererExtensionBindings::Invoke(function_name, args, NULL, requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url) { + RendererExtensionBindings::Invoke( + function_name, args, NULL, requires_incognito_access, event_url); // 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 2294e05..3c45dd5 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -226,7 +226,8 @@ class RenderThread : public RenderThreadBase, void OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url); void OnPurgeMemory(); void OnPurgePluginListCache(bool reload_pages); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 39e6ec6..a16a735 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -4298,9 +4298,10 @@ void RenderView::InjectToolstripCSS() { void RenderView::OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access) { + bool requires_incognito_access, + const GURL& event_url) { RendererExtensionBindings::Invoke( - function_name, args, this, requires_incognito_access); + function_name, args, this, requires_incognito_access, event_url); } // Dump all load time histograms. diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index c3a0190..9545245 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -727,7 +727,8 @@ class RenderView : public RenderWidget, void OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args, - bool requires_incognito_access); + bool requires_incognito_access, + const GURL& event_url); void OnMoveOrResizeStarted(); diff --git a/chrome/test/data/extensions/api_test/messaging/event_url/manifest.json b/chrome/test/data/extensions/api_test/messaging/event_url/manifest.json new file mode 100644 index 0000000..1fd201f --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/event_url/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "event_url", + "version": "1.0", + "description": "Tests messages which require permissions.", + "permissions": ["http://a.com/"], + "background_page": "test.html" +} diff --git a/chrome/test/data/extensions/api_test/messaging/event_url/test.html b/chrome/test/data/extensions/api_test/messaging/event_url/test.html new file mode 100644 index 0000000..fc0bc51 --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/event_url/test.html @@ -0,0 +1,26 @@ +<script> +var messages = []; + +function messageReceived(data) { + messages.push(data); +} + +function evaluateMessages() { + if (messages.length != 3) + chrome.test.notifyFail("Got " + messages.length + " messages instead of 3"); + else if (messages[0] != "no restriction" || + messages[1] != "http://a.com/" || + messages[2] != "last message") + chrome.test.notifyFail("Got wrong messages: " + messages[0] + ", " + + messages[1] + ", " + messages[2]); + else + chrome.test.notifyPass(); +} + + +chrome.test.onMessage.addListener(function (info) { + messageReceived(info.data); + if (info.lastMessage) + evaluateMessages(); +}); +</script> |