summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-25 04:54:58 +0000
committerkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-25 04:54:58 +0000
commit686914fd35156ceb47291b61e4bf50cc53c3079b (patch)
treeeb0e3ed6284d20a19933999bc77d54ab875a56d5
parentc0d305c40f7f2df5b2d96f36750e32a830da7f4d (diff)
downloadchromium_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
-rw-r--r--chrome/browser/extensions/api/messaging/extension_message_port.cc12
-rw-r--r--chrome/browser/extensions/api/messaging/extension_message_port.h7
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.cc138
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.h13
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.cc15
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.h16
-rw-r--r--chrome/common/extensions/api/runtime.json5
-rw-r--r--chrome/common/extensions/extension_messages.h41
-rw-r--r--chrome/renderer/chrome_mock_render_thread.cc3
-rw-r--r--chrome/renderer/chrome_mock_render_thread.h6
-rw-r--r--chrome/renderer/extensions/dispatcher.cc14
-rw-r--r--chrome/renderer/extensions/dispatcher.h7
-rw-r--r--chrome/renderer/extensions/extension_helper.cc13
-rw-r--r--chrome/renderer/extensions/extension_helper.h12
-rw-r--r--chrome/renderer/extensions/miscellaneous_bindings.cc34
-rw-r--r--chrome/renderer/extensions/miscellaneous_bindings.h6
-rw-r--r--chrome/renderer/extensions/runtime_custom_bindings.cc15
-rw-r--r--chrome/renderer/resources/extensions/miscellaneous_bindings.js49
-rw-r--r--chrome/renderer/resources/extensions/test_custom_bindings.js5
-rw-r--r--chrome/test/data/extensions/api_test/messaging/connect/page.js1
-rw-r--r--chrome/test/data/extensions/api_test/messaging/connect/test.js21
-rw-r--r--chrome/test/data/extensions/platform_apps/messaging/app1/manifest.json1
-rw-r--r--chrome/test/data/extensions/platform_apps/messaging/app2/background.js3
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