diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-25 04:54:58 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-25 04:54:58 +0000 |
commit | 686914fd35156ceb47291b61e4bf50cc53c3079b (patch) | |
tree | eb0e3ed6284d20a19933999bc77d54ab875a56d5 | |
parent | c0d305c40f7f2df5b2d96f36750e32a830da7f4d (diff) | |
download | chromium_src-686914fd35156ceb47291b61e4bf50cc53c3079b.zip chromium_src-686914fd35156ceb47291b61e4bf50cc53c3079b.tar.gz chromium_src-686914fd35156ceb47291b61e4bf50cc53c3079b.tar.bz2 |
Fix a couple of bugs relating to sending Tab info with chrome.runtime.connect and
sendMessage: don't send it when the connection originates from an extension page,
and don't sent it regardless to platform apps. To compensate, send the URL down
separately.
BUG=55316,234384
Review URL: https://chromiumcodereview.appspot.com/14301016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196316 0039d316-1c4b-4281-b951-d872f2087c98
23 files changed, 252 insertions, 185 deletions
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.cc b/chrome/browser/extensions/api/messaging/extension_message_port.cc index f1510ef..e4782c7 100644 --- a/chrome/browser/extensions/api/messaging/extension_message_port.cc +++ b/chrome/browser/extensions/api/messaging/extension_message_port.cc @@ -26,12 +26,16 @@ ExtensionMessagePort::ExtensionMessagePort(content::RenderProcessHost* process, void ExtensionMessagePort::DispatchOnConnect( int dest_port_id, const std::string& channel_name, - const std::string& tab_json, + const base::DictionaryValue& source_tab, const std::string& source_extension_id, - const std::string& target_extension_id) { + const std::string& target_extension_id, + const GURL& source_url) { + ExtensionMsg_ExternalConnectionInfo info; + info.target_id = target_extension_id; + info.source_id = source_extension_id; + info.source_url = source_url; process_->Send(new ExtensionMsg_DispatchOnConnect( - routing_id_, dest_port_id, channel_name, - tab_json, source_extension_id, target_extension_id)); + routing_id_, dest_port_id, channel_name, source_tab, info)); } void ExtensionMessagePort::DispatchOnDisconnect( diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.h b/chrome/browser/extensions/api/messaging/extension_message_port.h index 3e8d5ed..ccf9b69 100644 --- a/chrome/browser/extensions/api/messaging/extension_message_port.h +++ b/chrome/browser/extensions/api/messaging/extension_message_port.h @@ -7,6 +7,8 @@ #include "chrome/browser/extensions/api/messaging/message_service.h" +class GURL; + namespace content { class RenderProcessHost; } // namespace content @@ -22,9 +24,10 @@ class ExtensionMessagePort : public MessageService::MessagePort { virtual void DispatchOnConnect( int dest_port_id, const std::string& channel_name, - const std::string& tab_json, + const base::DictionaryValue& source_tab, const std::string& source_extension_id, - const std::string& target_extension_id) OVERRIDE; + const std::string& target_extension_id, + const GURL& source_url) OVERRIDE; virtual void DispatchOnDisconnect(int source_port_id, const std::string& error_message) OVERRIDE; virtual void DispatchOnMessage(const std::string& message, diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc index e3075f9..22915cb 100644 --- a/chrome/browser/extensions/api/messaging/message_service.cc +++ b/chrome/browser/extensions/api/messaging/message_service.cc @@ -32,6 +32,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" +#include "googleurl/src/gurl.h" using content::SiteInstance; using content::WebContents; @@ -66,28 +67,36 @@ struct MessageService::MessageChannel { struct MessageService::OpenChannelParams { content::RenderProcessHost* source; - std::string tab_json; + DictionaryValue source_tab; scoped_ptr<MessagePort> receiver; int receiver_port_id; std::string source_extension_id; std::string target_extension_id; + GURL source_url; std::string channel_name; // Takes ownership of receiver. OpenChannelParams(content::RenderProcessHost* source, - const std::string& tab_json, + scoped_ptr<DictionaryValue> source_tab, MessagePort* receiver, int receiver_port_id, const std::string& source_extension_id, const std::string& target_extension_id, + const GURL& source_url, const std::string& channel_name) : source(source), - tab_json(tab_json), receiver(receiver), receiver_port_id(receiver_port_id), source_extension_id(source_extension_id), target_extension_id(target_extension_id), - channel_name(channel_name) {} + source_url(source_url), + channel_name(channel_name) { + if (source_tab) + this->source_tab.Swap(source_tab.get()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); }; namespace { @@ -152,6 +161,7 @@ void MessageService::OpenChannelToExtension( int source_process_id, int source_routing_id, int receiver_port_id, const std::string& source_extension_id, const std::string& target_extension_id, + const GURL& source_url, const std::string& channel_name) { content::RenderProcessHost* source = content::RenderProcessHost::FromID(source_process_id); @@ -159,6 +169,16 @@ void MessageService::OpenChannelToExtension( return; Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); + const Extension* target_extension = ExtensionSystem::Get(profile)-> + extension_service()->extensions()->GetByID(target_extension_id); + if (!target_extension) { + // Treat it as a disconnect. + ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string()); + port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), + kReceivingEndDoesntExistError); + return; + } + // Note: we use the source's profile here. If the source is an incognito // process, we will use the incognito EPM to find the right extension process, // which depends on whether the extension uses spanning or split mode. @@ -169,27 +189,33 @@ void MessageService::OpenChannelToExtension( source_process_id, source_routing_id); // Include info about the opener's tab (if it was a tab). - std::string tab_json = "null"; - if (source_contents) { - scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( - source_contents)); - base::JSONWriter::Write(tab_value.get(), &tab_json); + scoped_ptr<DictionaryValue> source_tab; + GURL source_url_for_tab; + + if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { + // Platform apps can be sent messages, but don't have a Tab concept. + if (!target_extension->is_platform_app()) + source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); + source_url_for_tab = source_url; } - OpenChannelParams* params = new OpenChannelParams(source, tab_json, receiver, + OpenChannelParams* params = new OpenChannelParams(source, + source_tab.Pass(), + receiver, receiver_port_id, source_extension_id, target_extension_id, + source_url_for_tab, channel_name); // The target might be a lazy background page. In that case, we have to check // if it is loaded and ready, and if not, queue up the task and load the // page. - if (MaybeAddPendingOpenChannelTask(profile, params)) { + if (MaybeAddPendingOpenChannelTask(profile, target_extension, params)) { return; } - OpenChannelImpl(scoped_ptr<OpenChannelParams>(params)); + OpenChannelImpl(make_scoped_ptr(params)); } void MessageService::OpenChannelToNativeApp( @@ -222,17 +248,6 @@ void MessageService::OpenChannelToNativeApp( return; } - WebContents* source_contents = tab_util::GetWebContentsByID( - source_process_id, source_routing_id); - - // Include info about the opener's tab (if it was a tab). - std::string tab_json = "null"; - if (source_contents) { - scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( - source_contents)); - base::JSONWriter::Write(tab_value.get(), &tab_json); - } - scoped_ptr<MessageChannel> channel(new MessageChannel()); channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, source_extension_id)); @@ -294,23 +309,16 @@ void MessageService::OpenChannelToTab( return; } - WebContents* source_contents = tab_util::GetWebContentsByID( - source_process_id, source_routing_id); - - // Include info about the opener's tab (if it was a tab). - std::string tab_json = "null"; - if (source_contents) { - scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( - source_contents)); - base::JSONWriter::Write(tab_value.get(), &tab_json); - } - - scoped_ptr<OpenChannelParams> params(new OpenChannelParams(source, tab_json, - receiver.release(), - receiver_port_id, - extension_id, - extension_id, - channel_name)); + scoped_ptr<OpenChannelParams> params(new OpenChannelParams( + source, + scoped_ptr<DictionaryValue>(), // Source tab doesn't make sense for + // opening to tabs. + receiver.release(), + receiver_port_id, + extension_id, + extension_id, + GURL(), // Source URL doesn't make sense for opening to tabs. + channel_name)); OpenChannelImpl(params.Pass()); } @@ -318,7 +326,7 @@ bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { if (!params->source) return false; // Closed while in flight. - if (!params->receiver.get() || !params->receiver->GetRenderProcessHost()) { + if (!params->receiver || !params->receiver->GetRenderProcessHost()) { // Treat it as a disconnect. ExtensionMessagePort port( params->source, MSG_ROUTING_CONTROL, std::string()); @@ -346,9 +354,11 @@ bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { // Send the connect event to the receiver. Give it the opener's port ID (the // opener has the opposite port ID). channel->receiver->DispatchOnConnect(params->receiver_port_id, - params->channel_name, params->tab_json, + params->channel_name, + params->source_tab, params->source_extension_id, - params->target_extension_id); + params->target_extension_id, + params->source_url); // Keep both ends of the channel alive until the channel is closed. channel->opener->IncrementLazyKeepaliveCount(); @@ -479,30 +489,28 @@ void MessageService::OnProcessClosed(content::RenderProcessHost* process) { bool MessageService::MaybeAddPendingOpenChannelTask( Profile* profile, + const Extension* extension, OpenChannelParams* params) { - ExtensionService* service = profile->GetExtensionService(); - const std::string& extension_id = params->target_extension_id; - const Extension* extension = service->extensions()->GetByID(extension_id); - if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) { - // If the extension uses spanning incognito mode, make sure we're always - // using the original profile since that is what the extension process - // will use. - if (!IncognitoInfo::IsSplitMode(extension)) - profile = profile->GetOriginalProfile(); - - if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { - pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = - PendingChannel(profile, extension_id); - scoped_ptr<OpenChannelParams> scoped_params(params); - lazy_background_task_queue_->AddPendingTask(profile, extension_id, - base::Bind(&MessageService::PendingOpenChannel, - weak_factory_.GetWeakPtr(), base::Passed(&scoped_params), - params->source->GetID())); - return true; - } - } + if (!BackgroundInfo::HasLazyBackgroundPage(extension)) + return false; + + // If the extension uses spanning incognito mode, make sure we're always + // using the original profile since that is what the extension process + // will use. + if (!IncognitoInfo::IsSplitMode(extension)) + profile = profile->GetOriginalProfile(); - return false; + if (!lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) + return false; + + pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = + PendingChannel(profile, extension->id()); + scoped_ptr<OpenChannelParams> scoped_params(params); + lazy_background_task_queue_->AddPendingTask(profile, extension->id(), + base::Bind(&MessageService::PendingOpenChannel, + weak_factory_.GetWeakPtr(), base::Passed(&scoped_params), + params->source->GetID())); + return true; } void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params, diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h index 8786ef1..adeb060 100644 --- a/chrome/browser/extensions/api/messaging/message_service.h +++ b/chrome/browser/extensions/api/messaging/message_service.h @@ -16,14 +16,20 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +class GURL; class Profile; +namespace base { +class DictionaryValue; +} + namespace content { class RenderProcessHost; class WebContents; } namespace extensions { +class Extension; class ExtensionHost; class LazyBackgroundTaskQueue; @@ -63,9 +69,10 @@ class MessageService : public content::NotificationObserver, // Notify the port that the channel has been opened. virtual void DispatchOnConnect(int dest_port_id, const std::string& channel_name, - const std::string& tab_json, + const base::DictionaryValue& source_tab, const std::string& source_extension_id, - const std::string& target_extension_id) {} + const std::string& target_extension_id, + const GURL& source_url) {} // Notify the port that the channel has been closed. If |error_message| is // non-empty, it indicates an error occurred while opening the connection. @@ -105,6 +112,7 @@ class MessageService : public content::NotificationObserver, int source_process_id, int source_routing_id, int receiver_port_id, const std::string& source_extension_id, const std::string& target_extension_id, + const GURL& source_url, const std::string& channel_name); // Same as above, but opens a channel to the tab with the given ID. Messages @@ -172,6 +180,7 @@ class MessageService : public content::NotificationObserver, // to open a channel. Returns true if a task was queued. // Takes ownership of |params| if true is returned. bool MaybeAddPendingOpenChannelTask(Profile* profile, + const Extension* extension, OpenChannelParams* params); // Callbacks for LazyBackgroundTaskQueue tasks. The queue passes in an diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc index f8524e9..0c59aac 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.cc +++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc @@ -374,30 +374,29 @@ void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated, } void ChromeRenderMessageFilter::OnOpenChannelToExtension( - int routing_id, const std::string& source_extension_id, - const std::string& target_extension_id, + int routing_id, + const ExtensionMsg_ExternalConnectionInfo& info, const std::string& channel_name, int* port_id) { int port2_id; extensions::MessageService::AllocatePortIdPair(port_id, &port2_id); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread, - this, render_process_id_, routing_id, port2_id, - source_extension_id, target_extension_id, channel_name)); + base::Bind( + &ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread, this, + render_process_id_, routing_id, port2_id, info, channel_name)); } void ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread( int source_process_id, int source_routing_id, int receiver_port_id, - const std::string& source_extension_id, - const std::string& target_extension_id, + const ExtensionMsg_ExternalConnectionInfo& info, const std::string& channel_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); extensions::ExtensionSystem::Get(profile_)->message_service()-> OpenChannelToExtension( source_process_id, source_routing_id, receiver_port_id, - source_extension_id, target_extension_id, channel_name); + info.source_id, info.target_id, info.source_url, channel_name); } void ChromeRenderMessageFilter::OnOpenChannelToNativeApp( diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h index 590de48..1c160c0 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.h +++ b/chrome/browser/renderer_host/chrome_render_message_filter.h @@ -20,6 +20,7 @@ class CookieSettings; struct ExtensionHostMsg_APIActionOrEvent_Params; struct ExtensionHostMsg_DOMAction_Params; struct ExtensionHostMsg_Request_Params; +struct ExtensionMsg_ExternalConnectionInfo; class ExtensionInfoMap; class GURL; @@ -100,15 +101,14 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter { void OnFPS(int routing_id, float fps); void OnV8HeapStats(int v8_memory_allocated, int v8_memory_used); void OnOpenChannelToExtension(int routing_id, - const std::string& source_extension_id, - const std::string& target_extension_id, + const ExtensionMsg_ExternalConnectionInfo& info, const std::string& channel_name, int* port_id); - void OpenChannelToExtensionOnUIThread(int source_process_id, - int source_routing_id, - int receiver_port_id, - const std::string& source_extension_id, - const std::string& target_extension_id, - const std::string& channel_name); + void OpenChannelToExtensionOnUIThread( + int source_process_id, + int source_routing_id, + int receiver_port_id, + const ExtensionMsg_ExternalConnectionInfo& info, + const std::string& channel_name); void OnOpenChannelToNativeApp(int routing_id, const std::string& source_extension_id, const std::string& native_app_name, diff --git a/chrome/common/extensions/api/runtime.json b/chrome/common/extensions/api/runtime.json index 0550849..5920cdc 100644 --- a/chrome/common/extensions/api/runtime.json +++ b/chrome/common/extensions/api/runtime.json @@ -30,8 +30,9 @@ "type": "object", "description": "An object containing information about the script context that sent a message or request.", "properties": { - "tab": {"$ref": "tabs.Tab", "optional": true, "description":"This property will <b>only</b> be present when the connection was opened from a tab or content script."}, - "id": {"type": "string", "description": "The ID of the extension/app that opened the connection."} + "tab": {"$ref": "tabs.Tab", "optional": true, "description": "The $ref:tabs.Tab which opened the connection, if any. This property will <strong>only</strong> be present when the connection was opened from a tab (including content scripts), and <strong>only</strong> if the receiver is an extension, not an app."}, + "id": {"type": "string", "description": "The ID of the extension or app that opened the connection."}, + "url": {"type": "string", "optional": true, "description": "The URL of the page or frame that opened the connection. This property will <strong>only</strong> be present when the connection was opened from a tab (including content scripts)."} } } ], diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h index 62af07a..5891240 100644 --- a/chrome/common/extensions/extension_messages.h +++ b/chrome/common/extensions/extension_messages.h @@ -122,6 +122,20 @@ IPC_STRUCT_BEGIN(ExtensionMsg_ExecuteCode_Params) IPC_STRUCT_MEMBER(bool, is_web_view) IPC_STRUCT_END() +// Struct containing the data for external connections to extensions. Used to +// handle the IPCs initiated by both connect() and onConnect(). +IPC_STRUCT_BEGIN(ExtensionMsg_ExternalConnectionInfo) + // The ID of the extension that is the target of the request. + IPC_STRUCT_MEMBER(std::string, target_id) + + // The ID of the extension that initiated the request. May be empty if it + // wasn't initiated by an extension. + IPC_STRUCT_MEMBER(std::string, source_id) + + // The URL of the frame that initiated the request. + IPC_STRUCT_MEMBER(GURL, source_url) +IPC_STRUCT_END() + IPC_STRUCT_TRAITS_BEGIN(WebApplicationInfo::IconInfo) IPC_STRUCT_TRAITS_MEMBER(url) IPC_STRUCT_TRAITS_MEMBER(width) @@ -396,12 +410,11 @@ IPC_MESSAGE_ROUTED2(ExtensionMsg_GetAppInstallStateResponse, int32 /* callback_id */) // Dispatch the Port.onConnect event for message channels. -IPC_MESSAGE_ROUTED5(ExtensionMsg_DispatchOnConnect, +IPC_MESSAGE_ROUTED4(ExtensionMsg_DispatchOnConnect, int /* target_port_id */, std::string /* channel_name */, - std::string /* tab_json */, - std::string /* source_extension_id */, - std::string /* target_extension_id */) + DictionaryValue /* source_tab */, + ExtensionMsg_ExternalConnectionInfo) // Deliver a message sent with ExtensionHostMsg_PostMessage. IPC_MESSAGE_ROUTED2(ExtensionMsg_DeliverMessage, @@ -491,10 +504,9 @@ IPC_MESSAGE_ROUTED0(ExtensionHostMsg_EventAck) // the given ID. This always returns a valid port ID which can be used for // sending messages. If an error occurred, the opener will be notified // asynchronously. -IPC_SYNC_MESSAGE_CONTROL4_1(ExtensionHostMsg_OpenChannelToExtension, +IPC_SYNC_MESSAGE_CONTROL3_1(ExtensionHostMsg_OpenChannelToExtension, int /* routing_id */, - std::string /* source_extension_id */, - std::string /* target_extension_id */, + ExtensionMsg_ExternalConnectionInfo, std::string /* channel_name */, int /* port_id */) @@ -531,14 +543,13 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ExtensionHostMsg_GetMessageBundle, SubstitutionMap /* message bundle */) // Sent from the renderer to the browser to return the script running result. -IPC_MESSAGE_ROUTED5(ExtensionHostMsg_ExecuteCodeFinished, - int /* request id */, - std::string /* error; empty implies success */, - int32 /* page_id the code executed on. - May be -1 if unsuccessful */, - GURL /* URL of the code executed on. - May be empty if unsuccessful. */, - ListValue /* result of the script */) +IPC_MESSAGE_ROUTED5( + ExtensionHostMsg_ExecuteCodeFinished, + int /* request id */, + std::string /* error; empty implies success */, + int32 /* page_id the code executed on. May be -1 if unsuccessful */, + GURL /* URL of the code executed on. May be empty if unsuccessful. */, + ListValue /* result of the script */) // Sent from the renderer to the browser to notify that content scripts are // running in the renderer that the IPC originated from. diff --git a/chrome/renderer/chrome_mock_render_thread.cc b/chrome/renderer/chrome_mock_render_thread.cc index 472c211..79d7361 100644 --- a/chrome/renderer/chrome_mock_render_thread.cc +++ b/chrome/renderer/chrome_mock_render_thread.cc @@ -68,8 +68,7 @@ bool ChromeMockRenderThread::OnMessageReceived(const IPC::Message& msg) { void ChromeMockRenderThread::OnOpenChannelToExtension( int routing_id, - const std::string& source_extension_id, - const std::string& target_extension_id, + const ExtensionMsg_ExternalConnectionInfo& info, const std::string& channel_name, int* port_id) { *port_id = 0; diff --git a/chrome/renderer/chrome_mock_render_thread.h b/chrome/renderer/chrome_mock_render_thread.h index c3b3c7a..49fe79f 100644 --- a/chrome/renderer/chrome_mock_render_thread.h +++ b/chrome/renderer/chrome_mock_render_thread.h @@ -15,6 +15,7 @@ class DictionaryValue; } class MockPrinter; +struct ExtensionMsg_ExternalConnectionInfo; struct PrintHostMsg_DidGetPreviewPageCount_Params; struct PrintHostMsg_DidPreviewPage_Params; struct PrintHostMsg_DidPrintPage_Params; @@ -52,9 +53,8 @@ class ChromeMockRenderThread : public content::MockRenderThread { // The callee expects to be returned a valid channel_id. void OnOpenChannelToExtension(int routing_id, - const std::string& extension_id, - const std::string& source_extension_id, - const std::string& target_extension_id, + const ExtensionMsg_ExternalConnectionInfo& info, + const std::string& channel_name, int* port_id); #if defined(OS_CHROMEOS) diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc index 3c0432b..adb6347 100644 --- a/chrome/renderer/extensions/dispatcher.cc +++ b/chrome/renderer/extensions/dispatcher.cc @@ -542,15 +542,15 @@ void Dispatcher::OnMessageInvoke(const std::string& extension_id, } } -void Dispatcher::OnDispatchOnConnect(int target_port_id, - const std::string& channel_name, - const std::string& tab_json, - const std::string& source_extension_id, - const std::string& target_extension_id) { +void Dispatcher::OnDispatchOnConnect( + int target_port_id, + const std::string& channel_name, + const base::DictionaryValue& source_tab, + const ExtensionMsg_ExternalConnectionInfo& info) { MiscellaneousBindings::DispatchOnConnect( v8_context_set_.GetAll(), - target_port_id, channel_name, tab_json, - source_extension_id, target_extension_id, + target_port_id, channel_name, source_tab, + info.source_id, info.target_id, info.source_url, NULL); // All render views. } diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h index d443000..0939b37 100644 --- a/chrome/renderer/extensions/dispatcher.h +++ b/chrome/renderer/extensions/dispatcher.h @@ -24,6 +24,7 @@ class GURL; class ModuleSystem; class URLPattern; +struct ExtensionMsg_ExternalConnectionInfo; struct ExtensionMsg_Loaded_Params; namespace WebKit { @@ -31,6 +32,7 @@ class WebFrame; } namespace base { +class DictionaryValue; class ListValue; } @@ -145,9 +147,8 @@ class Dispatcher : public content::RenderProcessObserver { bool user_gesture); void OnDispatchOnConnect(int target_port_id, const std::string& channel_name, - const std::string& tab_json, - const std::string& source_extension_id, - const std::string& target_extension_id); + const base::DictionaryValue& source_tab, + const ExtensionMsg_ExternalConnectionInfo& info); void OnDeliverMessage(int target_port_id, const std::string& message); void OnDispatchOnDisconnect(int port_id, const std::string& error_message); void OnSetFunctionNames(const std::vector<std::string>& names); diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc index ac456a8..ba6e972 100644 --- a/chrome/renderer/extensions/extension_helper.cc +++ b/chrome/renderer/extensions/extension_helper.cc @@ -33,10 +33,6 @@ #include "webkit/glue/image_resource_fetcher.h" #include "webkit/glue/resource_fetcher.h" -namespace base { -class ListValue; -} // namespace base - using content::ConsoleMessageLevel; using WebKit::WebConsoleMessage; using WebKit::WebDataSource; @@ -280,13 +276,12 @@ void ExtensionHelper::OnExtensionMessageInvoke(const std::string& extension_id, void ExtensionHelper::OnExtensionDispatchOnConnect( int target_port_id, const std::string& channel_name, - const std::string& tab_json, - const std::string& source_extension_id, - const std::string& target_extension_id) { + const base::DictionaryValue& source_tab, + const ExtensionMsg_ExternalConnectionInfo& info) { MiscellaneousBindings::DispatchOnConnect( dispatcher_->v8_context_set().GetAll(), - target_port_id, channel_name, tab_json, - source_extension_id, target_extension_id, + target_port_id, channel_name, source_tab, + info.source_id, info.target_id, info.source_url, render_view()); } diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h index 8d8620c..912aad8 100644 --- a/chrome/renderer/extensions/extension_helper.h +++ b/chrome/renderer/extensions/extension_helper.h @@ -19,9 +19,11 @@ class GURL; class SkBitmap; struct ExtensionMsg_ExecuteCode_Params; +struct ExtensionMsg_ExternalConnectionInfo; struct WebApplicationInfo; namespace base { +class DictionaryValue; class ListValue; } @@ -78,11 +80,11 @@ class ExtensionHelper const base::ListValue& args, const GURL& event_url, bool user_gesture); - void OnExtensionDispatchOnConnect(int target_port_id, - const std::string& channel_name, - const std::string& tab_json, - const std::string& source_extension_id, - const std::string& target_extension_id); + void OnExtensionDispatchOnConnect( + int target_port_id, + const std::string& channel_name, + const base::DictionaryValue& source_tab, + const ExtensionMsg_ExternalConnectionInfo& info); void OnExtensionDeliverMessage(int target_port_id, const std::string& message); void OnExtensionDispatchOnDisconnect(int port_id, diff --git a/chrome/renderer/extensions/miscellaneous_bindings.cc b/chrome/renderer/extensions/miscellaneous_bindings.cc index d998972..cf538c7 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.cc +++ b/chrome/renderer/extensions/miscellaneous_bindings.cc @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/bind.h" #include "base/lazy_instance.h" +#include "base/values.h" #include "chrome/common/extensions/extension_messages.h" #include "chrome/common/extensions/message_bundle.h" #include "chrome/common/url_constants.h" @@ -21,6 +22,7 @@ #include "chrome/renderer/extensions/scoped_persistent.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" +#include "content/public/renderer/v8_value_converter.h" #include "grit/renderer_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h" #include "v8/include/v8.h" @@ -36,6 +38,7 @@ // }); using content::RenderThread; +using content::V8ValueConverter; namespace { @@ -201,13 +204,17 @@ void MiscellaneousBindings::DispatchOnConnect( const ChromeV8ContextSet::ContextSet& contexts, int target_port_id, const std::string& channel_name, - const std::string& tab_json, + const base::DictionaryValue& source_tab, const std::string& source_extension_id, const std::string& target_extension_id, + const GURL& source_url, content::RenderView* restrict_to_render_view) { v8::HandleScope handle_scope; + scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); + bool port_created = false; + std::string source_url_spec = source_url.spec(); for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin(); it != contexts.end(); ++it) { @@ -216,20 +223,23 @@ void MiscellaneousBindings::DispatchOnConnect( continue; } - std::vector<v8::Handle<v8::Value> > arguments; - arguments.push_back(v8::Integer::New(target_port_id)); - arguments.push_back(v8::String::New(channel_name.c_str(), - channel_name.size())); - arguments.push_back(v8::String::New(tab_json.c_str(), - tab_json.size())); - arguments.push_back(v8::String::New(source_extension_id.c_str(), - source_extension_id.size())); - arguments.push_back(v8::String::New(target_extension_id.c_str(), - target_extension_id.size())); + v8::Handle<v8::Value> tab = v8::Null(); + if (!source_tab.empty()) + tab = converter->ToV8Value(&source_tab, (*it)->v8_context()); + + v8::Handle<v8::Value> arguments[] = { + v8::Integer::New(target_port_id), + v8::String::New(channel_name.c_str(), channel_name.size()), + tab, + v8::String::New(source_extension_id.c_str(), source_extension_id.size()), + v8::String::New(target_extension_id.c_str(), target_extension_id.size()), + v8::String::New(source_url_spec.c_str(), source_url_spec.size()) + }; + v8::Handle<v8::Value> retval; v8::TryCatch try_catch; if (!(*it)->CallChromeHiddenMethod("Port.dispatchOnConnect", - arguments.size(), &arguments[0], + arraysize(arguments), arguments, &retval)) { continue; } diff --git a/chrome/renderer/extensions/miscellaneous_bindings.h b/chrome/renderer/extensions/miscellaneous_bindings.h index 912d32d..33bb15e 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.h +++ b/chrome/renderer/extensions/miscellaneous_bindings.h @@ -9,6 +9,9 @@ #include "chrome/renderer/extensions/chrome_v8_context_set.h" +namespace base { +class DictionaryValue; +} namespace content { class RenderView; @@ -40,9 +43,10 @@ class MiscellaneousBindings { const ChromeV8ContextSet::ContextSet& contexts, int target_port_id, const std::string& channel_name, - const std::string& tab_json, + const base::DictionaryValue& source_tab, const std::string& source_extension_id, const std::string& target_extension_id, + const GURL& source_url, content::RenderView* restrict_to_render_view); // Delivers a message sent using content script messaging to some of the diff --git a/chrome/renderer/extensions/runtime_custom_bindings.cc b/chrome/renderer/extensions/runtime_custom_bindings.cc index 96139f3..b41f43c 100644 --- a/chrome/renderer/extensions/runtime_custom_bindings.cc +++ b/chrome/renderer/extensions/runtime_custom_bindings.cc @@ -14,6 +14,9 @@ #include "chrome/renderer/extensions/dispatcher.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/v8_value_converter.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" using content::V8ValueConverter; @@ -50,16 +53,14 @@ v8::Handle<v8::Value> RuntimeCustomBindings::OpenChannelToExtension( args[1]->IsString() && args[2]->IsString()); - std::string source_id = *v8::String::Utf8Value(args[0]->ToString()); - std::string target_id = *v8::String::Utf8Value(args[1]->ToString()); + ExtensionMsg_ExternalConnectionInfo info; + info.source_id = *v8::String::Utf8Value(args[0]->ToString()); + info.target_id = *v8::String::Utf8Value(args[1]->ToString()); + info.source_url = renderview->GetWebView()->mainFrame()->document().url(); std::string channel_name = *v8::String::Utf8Value(args[2]->ToString()); int port_id = -1; renderview->Send(new ExtensionHostMsg_OpenChannelToExtension( - renderview->GetRoutingID(), - source_id, - target_id, - channel_name, - &port_id)); + renderview->GetRoutingID(), info, channel_name, &port_id)); return v8::Integer::New(port_id); } diff --git a/chrome/renderer/resources/extensions/miscellaneous_bindings.js b/chrome/renderer/resources/extensions/miscellaneous_bindings.js index 33eb9d9..9a4937d 100644 --- a/chrome/renderer/resources/extensions/miscellaneous_bindings.js +++ b/chrome/renderer/resources/extensions/miscellaneous_bindings.js @@ -105,29 +105,33 @@ }; // Helper function for dispatchOnRequest. - function handleSendRequestError(isSendMessage, responseCallbackPreserved, - sourceExtensionId, targetExtensionId) { - var errorMsg; + function handleSendRequestError(isSendMessage, + responseCallbackPreserved, + sourceExtensionId, + targetExtensionId, + sourceUrl) { + var errorMsg = []; var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; if (isSendMessage && !responseCallbackPreserved) { - errorMsg = + errorMsg.push( "The chrome." + eventName + " listener must return true if you " + - "want to send a response after the listener returns "; + "want to send a response after the listener returns"); } else { - errorMsg = + errorMsg.push( "Cannot send a response more than once per chrome." + eventName + - " listener per document"; + " listener per document"); } - errorMsg += "(message was sent by extension " + sourceExtensionId; - if (sourceExtensionId != targetExtensionId) - errorMsg += " for extension " + targetExtensionId; - errorMsg += ")."; - lastError.set(eventName, errorMsg, null, chrome); + errorMsg.push("(message was sent by extension" + sourceExtensionId); + if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId) + errorMsg.push("for extension " + targetExtensionId); + if (sourceUrl != "") + errorMsg.push("for URL " + sourceUrl); + lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome); } // Helper function for dispatchOnConnect function dispatchOnRequest(portId, channelName, sender, - sourceExtensionId, targetExtensionId, + sourceExtensionId, targetExtensionId, sourceUrl, isExternal) { var isSendMessage = channelName == chromeHidden.kMessageChannel; var requestEvent = (isSendMessage ? @@ -182,16 +186,19 @@ "extension.onRequestExternal" : "extension.onRequest")); logActivity.LogEvent(targetExtensionId, eventName, - [sourceExtensionId]); + [sourceExtensionId, sourceUrl]); return true; } return false; } // Called by native code when a channel has been opened to this context. - chromeHidden.Port.dispatchOnConnect = function(portId, channelName, tab, + chromeHidden.Port.dispatchOnConnect = function(portId, + channelName, + sourceTab, sourceExtensionId, - targetExtensionId) { + targetExtensionId, + sourceUrl) { // Only create a new Port if someone is actually listening for a connection. // In addition to being an optimization, this also fixes a bug where if 2 // channels were opened to and from the same process, closing one would @@ -205,15 +212,17 @@ // the right event. var isExternal = sourceExtensionId != extensionId; - if (tab) - tab = json.parse(tab); - var sender = {tab: tab, id: sourceExtensionId}; + var sender = {id: sourceExtensionId}; + if (sourceUrl) + sender.url = sourceUrl; + if (sourceTab) + sender.tab = sourceTab; // Special case for sendRequest/onRequest and sendMessage/onMessage. if (channelName == chromeHidden.kRequestChannel || channelName == chromeHidden.kMessageChannel) { return dispatchOnRequest(portId, channelName, sender, - sourceExtensionId, targetExtensionId, + sourceExtensionId, targetExtensionId, sourceUrl, isExternal); } diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js index a878c06..d46d5eb 100644 --- a/chrome/renderer/resources/extensions/test_custom_bindings.js +++ b/chrome/renderer/resources/extensions/test_custom_bindings.js @@ -11,6 +11,7 @@ var chrome = requireNative('chrome').GetChrome(); var GetExtensionAPIDefinitions = requireNative('apiDefinitions').GetExtensionAPIDefinitions; var GetAvailability = requireNative('v8_context').GetAvailability; +var json = require('json'); binding.registerCustomHook(function(api) { var chromeTest = api.compiledApi; @@ -181,8 +182,8 @@ binding.registerCustomHook(function(api) { if (typeof(expected) == 'object') { if (!chromeTest.checkDeepEq(expected, actual)) { chromeTest.fail(error_msg + - "\nActual: " + JSON.stringify(actual) + - "\nExpected: " + JSON.stringify(expected)); + "\nActual: " + json.stringify(actual) + + "\nExpected: " + json.stringify(expected)); } return; } diff --git a/chrome/test/data/extensions/api_test/messaging/connect/page.js b/chrome/test/data/extensions/api_test/messaging/connect/page.js index 7d141f6..1e3a7e8 100644 --- a/chrome/test/data/extensions/api_test/messaging/connect/page.js +++ b/chrome/test/data/extensions/api_test/messaging/connect/page.js @@ -85,5 +85,6 @@ function testConnectFromTabError() { // For test sendMessage. chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { + chrome.test.assertEq({id: chrome.runtime.id}, sender); sendResponse({success: (request.step2 == 1)}); }); diff --git a/chrome/test/data/extensions/api_test/messaging/connect/test.js b/chrome/test/data/extensions/api_test/messaging/connect/test.js index 51d3baf..c79f489 100644 --- a/chrome/test/data/extensions/api_test/messaging/connect/test.js +++ b/chrome/test/data/extensions/api_test/messaging/connect/test.js @@ -28,9 +28,9 @@ chrome.test.getConfig(function(config) { chrome.tabs.create({ url: "http://localhost:PORT/files/extensions/test_file.html" .replace(/PORT/, config.testServer.port) - }, function(tab) { - chrome.tabs.onUpdated.addListener(function listener(tabid, info) { - if (tab.id == tabid && info.status == 'complete') { + }, function(newTab) { + chrome.tabs.onUpdated.addListener(function listener(_, info, tab) { + if (tab.id == newTab.id && info.status == 'complete') { chrome.test.log("Created tab: " + tab.url); chrome.tabs.onUpdated.removeListener(listener); testTab = tab; @@ -65,9 +65,11 @@ chrome.test.getConfig(function(config) { // Tests that postMessage from the tab and its response works. function postMessageFromTab() { chrome.runtime.onConnect.addListener(function(port) { - chrome.test.assertTrue(Boolean(port.sender.tab.url)); - chrome.test.assertTrue(Boolean(port.sender.tab.title)); - chrome.test.assertTrue(Boolean(port.sender.tab.id)); + chrome.test.assertEq({ + tab: testTab, + url: testTab.url, + id: chrome.runtime.id + }, port.sender); port.onMessage.addListener(function(msg) { chrome.test.assertTrue(msg.testPostMessageFromTab); port.postMessage({success: true, portName: port.name}); @@ -89,8 +91,11 @@ chrome.test.getConfig(function(config) { var doneListening = chrome.test.listenForever( chrome.runtime.onMessage, function(request, sender, sendResponse) { - chrome.test.assertTrue("url" in sender.tab, "no tab available."); - chrome.test.assertEq(sender.id, location.host); + chrome.test.assertEq({ + tab: testTab, + url: testTab.url, + id: chrome.runtime.id + }, sender); if (request.step == 1) { // Step 1: Page should send another request for step 2. chrome.test.log("sendMessageFromTab: got step 1"); diff --git a/chrome/test/data/extensions/platform_apps/messaging/app1/manifest.json b/chrome/test/data/extensions/platform_apps/messaging/app1/manifest.json index bb0beb6..7f332ca 100644 --- a/chrome/test/data/extensions/platform_apps/messaging/app1/manifest.json +++ b/chrome/test/data/extensions/platform_apps/messaging/app1/manifest.json @@ -1,4 +1,5 @@ { + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChIkos4QMuz7xmtnVIPCRZmcKzLyyvChW508KvpVWhdJZjnMShxVqH5QwrEzwtRhK1bTX/Y+7kmKGb9z49O//4KY/gFZQyiRNDnqv85L7fz7ceobLozwQWkhTFafYS39VMs00G0FvgQvEM1gO/Kg3eWVTFRUJCHHrMkO1De2Xd+wIDAQAB", "name": "Messaging Test App 1", "version": "0.5", "permissions": [ "app.runtime" ], diff --git a/chrome/test/data/extensions/platform_apps/messaging/app2/background.js b/chrome/test/data/extensions/platform_apps/messaging/app2/background.js index 3e5d2c0..07ef1ba 100644 --- a/chrome/test/data/extensions/platform_apps/messaging/app2/background.js +++ b/chrome/test/data/extensions/platform_apps/messaging/app2/background.js @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var otherId = 'ljhhihhmjomkjokmknellgbidphmahkh'; + chrome.runtime.onConnectExternal.addListener(function(port) { port.onMessage.addListener(function(msg) { if (msg == 'ok_to_disconnect') { @@ -13,6 +15,7 @@ chrome.runtime.onConnectExternal.addListener(function(port) { }); chrome.runtime.onMessageExternal.addListener(function(msg, sender, callback) { + chrome.test.assertEq({id: otherId}, sender); if (msg == 'hello') callback('hello_response'); else |