summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 21:17:49 +0000
committermpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 21:17:49 +0000
commit4b5d64ff3d7d95247ed4f078d8bf585a1726794d (patch)
tree050a523a5bbccf28ade0814b38bcc9bee187cd04 /chrome
parent912445b6db66140aecb3bc822075a6e9bb9d7e33 (diff)
downloadchromium_src-4b5d64ff3d7d95247ed4f078d8bf585a1726794d.zip
chromium_src-4b5d64ff3d7d95247ed4f078d8bf585a1726794d.tar.gz
chromium_src-4b5d64ff3d7d95247ed4f078d8bf585a1726794d.tar.bz2
Pass down the opener tab when a message channel is opened to an extension.
Also did a bunch of cleanup of ExtensionMessageService. I converted it to primarily UI-thread habitation, with one function that needs to be on the IO thread so it can handle a synchronous IPC message. TEST=N/A Review URL: http://codereview.chromium.org/99261 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15097 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rwxr-xr-xchrome/browser/extensions/extension_message_service.cc164
-rwxr-xr-xchrome/browser/extensions/extension_message_service.h73
-rw-r--r--chrome/browser/extensions/extension_messages_unittest.cc7
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc67
-rw-r--r--chrome/browser/extensions/extension_tabs_module.h5
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc18
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc16
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
-rw-r--r--chrome/chrome.gyp1
-rw-r--r--chrome/common/render_messages_internal.h17
-rw-r--r--chrome/renderer/extensions/bindings_utils.cc23
-rwxr-xr-xchrome/renderer/extensions/bindings_utils.h6
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc13
-rwxr-xr-xchrome/renderer/extensions/renderer_extension_bindings.cc29
-rwxr-xr-xchrome/renderer/extensions/renderer_extension_bindings.h7
-rw-r--r--chrome/renderer/mock_render_thread.cc2
-rw-r--r--chrome/renderer/mock_render_thread.h3
-rw-r--r--chrome/renderer/render_thread.cc7
-rw-r--r--chrome/renderer/render_thread.h2
-rw-r--r--chrome/renderer/renderer.vcproj4
-rwxr-xr-xchrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js6
-rw-r--r--chrome/test/data/extensions/good/extension1/1/toolstrip1.html2
-rw-r--r--chrome/test/render_view_test.cc2
25 files changed, 281 insertions, 200 deletions
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 4e9daba..95dd221 100755
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -4,14 +4,18 @@
#include "chrome/browser/extensions/extension_message_service.h"
+#include "base/json_writer.h"
#include "base/singleton.h"
#include "base/values.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/extensions/extension.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/stl_util-inl.h"
@@ -59,12 +63,35 @@ ExtensionMessageService* ExtensionMessageService::GetInstance(
}
ExtensionMessageService::ExtensionMessageService()
- : next_port_id_(0), observing_renderer_shutdown_(false) {
+ : ui_loop_(NULL), initialized_(false), next_port_id_(0) {
+}
+
+void ExtensionMessageService::Init() {
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
+
+ if (initialized_)
+ return;
+ initialized_ = true;
+
+ ui_loop_ = MessageLoop::current();
+
+ // Note: we never stop observing because we live longer than
+ // NotificationService.
+ NotificationService::current()->AddObserver(this,
+ NotificationType::RENDERER_PROCESS_TERMINATED,
+ NotificationService::AllSources());
+ NotificationService::current()->AddObserver(this,
+ NotificationType::RENDERER_PROCESS_CRASHED,
+ NotificationService::AllSources());
}
void ExtensionMessageService::RegisterExtension(
const std::string& extension_id, int render_process_id) {
- DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
+
+ // Make sure we're initialized.
+ Init();
+
AutoLock lock(process_ids_lock_);
DCHECK(process_ids_.find(extension_id) == process_ids_.end() ||
process_ids_[extension_id] == render_process_id);
@@ -73,24 +100,23 @@ void ExtensionMessageService::RegisterExtension(
void ExtensionMessageService::AddEventListener(std::string event_name,
int render_process_id) {
- DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
- AutoLock lock(listener_lock_);
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
DCHECK(listeners_[event_name].count(render_process_id) == 0);
listeners_[event_name].insert(render_process_id);
}
void ExtensionMessageService::RemoveEventListener(std::string event_name,
int render_process_id) {
- DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
- AutoLock lock(listener_lock_);
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
DCHECK(listeners_[event_name].count(render_process_id) == 1);
listeners_[event_name].erase(render_process_id);
}
int ExtensionMessageService::OpenChannelToExtension(
- const std::string& extension_id, ResourceMessageFilter* source) {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::IO));
+ int routing_id, const std::string& extension_id,
+ ResourceMessageFilter* source) {
+ DCHECK_EQ(MessageLoop::current(),
+ ChromeThread::GetMessageLoop(ChromeThread::IO));
// Lookup the targeted extension process.
int process_id;
@@ -103,13 +129,10 @@ int ExtensionMessageService::OpenChannelToExtension(
process_id = process_id_it->second;
}
- RendererMap::iterator renderer = renderers_.find(process_id);
- if (renderer == renderers_.end())
- return -1;
-
- ResourceMessageFilter* dest = renderer->second;
+ DCHECK(initialized_);
// Create a channel ID for both sides of the channel.
+ // TODO(mpcomplete): what happens when this wraps?
int port1_id = next_port_id_++;
int port2_id = next_port_id_++;
DCHECK(IS_PORT1_ID(port1_id));
@@ -117,22 +140,45 @@ int ExtensionMessageService::OpenChannelToExtension(
DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id);
DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id));
+ ui_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ExtensionMessageService::OpenChannelOnUIThread,
+ routing_id, port1_id, source->GetProcessId(), port2_id, process_id));
+
+ return port2_id;
+}
+
+void ExtensionMessageService::OpenChannelOnUIThread(
+ int source_routing_id, int source_port_id, int source_process_id,
+ int dest_port_id, int dest_process_id) {
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
+
MessageChannel channel;
- channel.port1 = source;
- channel.port2 = dest;
- channels_[GET_CHANNEL_ID(port1_id)] = channel;
+ channel.port1 = RenderProcessHost::FromID(source_process_id);
+ channel.port2 = RenderProcessHost::FromID(dest_process_id);
+ if (!channel.port1 || !channel.port2) {
+ // One of the processes could have been closed while posting this task.
+ return;
+ }
+
+ channels_[GET_CHANNEL_ID(source_port_id)] = channel;
+
+ std::string tab_json = "null";
+ WebContents* contents = tab_util::GetWebContentsByID(source_process_id,
+ source_routing_id);
+ if (contents) {
+ DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue(contents);
+ JSONWriter::Write(tab_value, false, &tab_json);
+ }
// Send each process the id for the opposite port.
- dest->Send(new ViewMsg_ExtensionHandleConnect(port1_id));
- return port2_id;
+ channel.port2->Send(new ViewMsg_ExtensionHandleConnect(source_port_id,
+ tab_json));
}
void ExtensionMessageService::PostMessageFromRenderer(
- int port_id, const std::string& message, ResourceMessageFilter* source) {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::IO));
+ int port_id, const std::string& message) {
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
- // Look up the channel by port1's ID.
MessageChannelMap::iterator iter =
channels_.find(GET_CHANNEL_ID(port_id));
if (iter == channels_.end())
@@ -140,14 +186,8 @@ void ExtensionMessageService::PostMessageFromRenderer(
MessageChannel& channel = iter->second;
// Figure out which port the ID corresponds to.
- ResourceMessageFilter* dest = NULL;
- if (IS_PORT1_ID(port_id)) {
- dest = channel.port1;
- DCHECK(source == channel.port2);
- } else {
- dest = channel.port2;
- DCHECK(source == channel.port1);
- }
+ RenderProcessHost* dest =
+ IS_PORT1_ID(port_id) ? channel.port1 : channel.port2;
int source_port_id = GET_OPPOSITE_PORT_ID(port_id);
dest->Send(new ViewMsg_ExtensionHandleMessage(message, source_port_id));
@@ -155,60 +195,38 @@ void ExtensionMessageService::PostMessageFromRenderer(
void ExtensionMessageService::DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args) {
- std::set<int> pids;
- {
- AutoLock lock(listener_lock_);
- pids = listeners_[event_name];
- if (pids.empty())
- return;
- }
- MessageLoop* io_thread = ChromeThread::GetMessageLoop(ChromeThread::IO);
- if (MessageLoop::current() != io_thread) {
- // Do the actual work on the IO thread.
- io_thread->PostTask(FROM_HERE, NewRunnableMethod(this,
- &ExtensionMessageService::DispatchEventToRenderers,
- event_name, event_args));
- return;
- }
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
+
+ std::set<int>& pids = listeners_[event_name];
// Send the event only to renderers that are listening for it.
for (std::set<int>::iterator pid = pids.begin(); pid != pids.end(); ++pid) {
- RendererMap::iterator renderer = renderers_.find(*pid);
- if (renderer == renderers_.end())
+ RenderProcessHost* renderer = RenderProcessHost::FromID(*pid);
+ if (!renderer)
continue;
- ResourceMessageFilter* filter = renderer->second;
- filter->Send(new ViewMsg_ExtensionHandleEvent(event_name, event_args));
- }
-}
-
-void ExtensionMessageService::RendererReady(ResourceMessageFilter* renderer) {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::IO));
-
- DCHECK(renderers_.find(renderer->GetProcessId()) == renderers_.end());
- renderers_[renderer->GetProcessId()] = renderer;
- renderers_unique_.insert(renderer);
-
- if (!observing_renderer_shutdown_) {
- observing_renderer_shutdown_ = true;
- NotificationService::current()->AddObserver(
- this,
- NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN,
- NotificationService::AllSources());
+ renderer->Send(new ViewMsg_ExtensionHandleEvent(event_name, event_args));
}
}
void ExtensionMessageService::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::IO));
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
- DCHECK(type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN);
- ResourceMessageFilter* renderer = Source<ResourceMessageFilter>(source).ptr();
+ DCHECK(type.value == NotificationType::RENDERER_PROCESS_TERMINATED ||
+ type.value == NotificationType::RENDERER_PROCESS_CRASHED);
+ RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr();
- renderers_.erase(renderer->GetProcessId());
- renderers_unique_.erase(renderer);
+ {
+ AutoLock lock(process_ids_lock_);
+ for (ProcessIDMap::iterator it = process_ids_.begin();
+ it != process_ids_.end(); ) {
+ ProcessIDMap::iterator current = it++;
+ if (current->second == renderer->pid()) {
+ process_ids_.erase(current);
+ }
+ }
+ }
// Close any channels that share this renderer.
// TODO(mpcomplete): should we notify the other side of the port?
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index 52b1682..343c632 100755
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -12,8 +12,8 @@
#include "base/lock.h"
#include "chrome/common/notification_observer.h"
-class ExtensionView;
-class ListValue;
+class MessageLoop;
+class RenderProcessHost;
class ResourceMessageFilter;
class URLRequestContext;
@@ -44,33 +44,33 @@ class ExtensionMessageService : public NotificationObserver {
void AddEventListener(std::string event_name, int render_process_id);
void RemoveEventListener(std::string event_name, int render_process_id);
- // --- IO thread only:
-
- // Given an extension's ID, opens a channel between the given renderer "port"
- // and that extension. Returns a channel ID to be used for posting messages
- // between the processes, or -1 if the extension doesn't exist.
- int OpenChannelToExtension(const std::string& extension_id,
- ResourceMessageFilter* source);
-
// Sends a message from a renderer to the given port.
- void PostMessageFromRenderer(int port_id, const std::string& message,
- ResourceMessageFilter* source);
+ // TODO(mpcomplete): include the source tab.
+ void PostMessageFromRenderer(int port_id, const std::string& message);
- // Called to let us know that a renderer has been started.
- void RendererReady(ResourceMessageFilter* renderer);
+ // Send an event to every registered extension renderer.
+ void DispatchEventToRenderers(
+ const std::string& event_name, const std::string& event_args);
// NotificationObserver interface.
void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
- // --- UI or IO thread:
+ // --- IO thread only:
- // Send an event to every registered extension renderer.
- void DispatchEventToRenderers(
- const std::string& event_name, const std::string& event_args);
+ // Given an extension's ID, opens a channel between the given renderer "port"
+ // and that extension. Returns a channel ID to be used for posting messages
+ // between the processes, or -1 if the extension doesn't exist.
+ // This runs on the IO thread so that it can be used in a synchronous IPC
+ // message.
+ int OpenChannelToExtension(int routing_id, const std::string& extension_id,
+ ResourceMessageFilter* source);
private:
+ // The UI message loop, used for posting tasks.
+ MessageLoop* ui_loop_;
+
// A map of extension ID to the render_process_id that the extension lives in.
typedef std::map<std::string, int> ProcessIDMap;
ProcessIDMap process_ids_;
@@ -85,36 +85,35 @@ class ExtensionMessageService : public NotificationObserver {
typedef std::map<std::string, std::set<int> > ListenerMap;
ListenerMap listeners_;
- // Protects listeners_ map, since it can be accessed from either the IO or
- // UI thread. Be careful not to hold this lock when calling external code
- // (especially sending messages) to avoid deadlock.
- Lock listener_lock_;
+ // --- UI thread only:
- // --- IO thread only:
+ // UI-thread specific initialization. Does nothing if called more than once.
+ void Init();
- // The connection between two renderers.
+ // Handles channel creation and notifies the destination that a channel was
+ // opened.
+ void OpenChannelOnUIThread(int source_routing_id,
+ int source_port_id, int source_process_id,
+ int dest_port_id, int dest_process_id);
+
+ // The connection between two renderers. It is possible that both ports
+ // refer to the same renderer.
struct MessageChannel {
- ResourceMessageFilter* port1;
- ResourceMessageFilter* port2;
+ RenderProcessHost* port1;
+ RenderProcessHost* port2;
};
// A map of channel ID to its channel object.
typedef std::map<int, MessageChannel> MessageChannelMap;
MessageChannelMap channels_;
- // For generating unique channel IDs.
- int next_port_id_;
-
- // A map of render_process_id to its corresponding message filter, which we
- // use for sending messages.
- typedef std::map<int, ResourceMessageFilter*> RendererMap;
- RendererMap renderers_;
+ // True if Init has been called.
+ bool initialized_;
- // A unique list of renderers that we are aware of.
- std::set<ResourceMessageFilter*> renderers_unique_;
+ // --- IO thread only:
- // Set to true when we start observing this notification.
- bool observing_renderer_shutdown_;
+ // For generating unique channel IDs.
+ int next_port_id_;
DISALLOW_COPY_AND_ASSIGN(ExtensionMessageService);
};
diff --git a/chrome/browser/extensions/extension_messages_unittest.cc b/chrome/browser/extensions/extension_messages_unittest.cc
index 1ef9f43..606c301 100644
--- a/chrome/browser/extensions/extension_messages_unittest.cc
+++ b/chrome/browser/extensions/extension_messages_unittest.cc
@@ -59,7 +59,7 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) {
ExecuteJavaScript(
"chromium.self.onConnect.addListener(function (port) {"
" port.onMessage.addListener(doOnMessage);"
- " port.postMessage({message: 'onconnect'});"
+ " port.postMessage({message: 'onconnect from ' + port.tab.url});"
"});"
"function doOnMessage(msg, port) {"
" alert('got: ' + msg.val);"
@@ -69,7 +69,8 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) {
// Simulate a new connection being opened.
const int kPortId = 0;
- RendererExtensionBindings::HandleConnect(kPortId);
+ RendererExtensionBindings::HandleConnect(kPortId,
+ "{\"url\":\"foo://bar\"}");
// Verify that we handled the new connection by posting a message.
const IPC::Message* post_msg =
@@ -78,7 +79,7 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) {
ASSERT_TRUE(post_msg);
ViewHostMsg_ExtensionPostMessage::Param post_params;
ViewHostMsg_ExtensionPostMessage::Read(post_msg, &post_params);
- EXPECT_EQ("{\"message\":\"onconnect\"}", post_params.b);
+ EXPECT_EQ("{\"message\":\"onconnect from foo://bar\"}", post_params.b);
// Now simulate getting a message back from the channel opener.
render_thread_.sink().ClearMessages();
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 069110e..41663dd 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -21,8 +21,6 @@
// Forward declare static helper functions defined below.
static DictionaryValue* CreateWindowValue(Browser* browser);
static ListValue* CreateTabList(Browser* browser);
-static DictionaryValue* CreateTabValue(TabStripModel* tab_strip_model,
- int tab_index);
static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
int* tab_index);
@@ -39,6 +37,42 @@ int ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) {
return tab_contents->controller().window_id().id();
}
+DictionaryValue* ExtensionTabUtil::CreateTabValue(
+ const TabContents* contents) {
+ // Find the tab strip and index of this guy.
+ for (BrowserList::const_iterator it = BrowserList::begin();
+ it != BrowserList::end(); ++it) {
+ TabStripModel* tab_strip = (*it)->tabstrip_model();
+ int tab_index = tab_strip->GetIndexOfTabContents(contents);
+ if (tab_index != -1) {
+ return ExtensionTabUtil::CreateTabValue(contents, tab_strip, tab_index);
+ }
+ }
+
+ // Couldn't find it. This can happen if the tab is being dragged.
+ return ExtensionTabUtil::CreateTabValue(contents, NULL, -1);
+}
+
+DictionaryValue* ExtensionTabUtil::CreateTabValue(
+ const TabContents* contents, TabStripModel* tab_strip, int tab_index) {
+ DictionaryValue* result = new DictionaryValue();
+ result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents));
+ result->SetInteger(L"index", tab_index);
+ result->SetInteger(L"windowId", ExtensionTabUtil::GetWindowIdOfTab(contents));
+ result->SetString(L"url", contents->GetURL().spec());
+ result->SetString(L"title", UTF16ToWide(contents->GetTitle()));
+ result->SetBoolean(L"selected",
+ tab_strip && tab_index == tab_strip->selected_index());
+
+ NavigationEntry* entry = contents->controller().GetActiveEntry();
+ if (entry) {
+ if (entry->favicon().is_valid())
+ result->SetString(L"favIconUrl", entry->favicon().url().spec());
+ }
+
+ return result;
+}
+
bool GetWindowsFunction::RunImpl() {
std::set<int> window_ids;
@@ -220,7 +254,7 @@ bool CreateTabFunction::RunImpl() {
// Return data about the newly created tab.
if (has_callback())
- result_.reset(CreateTabValue(tab_strip, index));
+ result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip, index));
return true;
}
@@ -239,7 +273,8 @@ bool GetTabFunction::RunImpl() {
if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
return false;
- result_.reset(CreateTabValue(tab_strip, tab_index));
+ result_.reset(ExtensionTabUtil::CreateTabValue(
+ tab_strip->GetTabContentsAt(tab_index), tab_strip, tab_index));
return true;
}
@@ -366,33 +401,13 @@ static ListValue* CreateTabList(Browser* browser) {
ListValue *tab_list = new ListValue();
TabStripModel* tab_strip = browser->tabstrip_model();
for (int i = 0; i < tab_strip->count(); ++i) {
- tab_list->Append(CreateTabValue(tab_strip, i));
+ tab_list->Append(ExtensionTabUtil::CreateTabValue(
+ tab_strip->GetTabContentsAt(i), tab_strip, i));
}
return tab_list;
}
-static DictionaryValue* CreateTabValue(TabStripModel* tab_strip,
- int tab_index) {
- TabContents* contents = tab_strip->GetTabContentsAt(tab_index);
-
- DictionaryValue* result = new DictionaryValue();
- result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents));
- result->SetInteger(L"index", tab_index);
- result->SetInteger(L"windowId", ExtensionTabUtil::GetWindowIdOfTab(contents));
- result->SetString(L"url", contents->GetURL().spec());
- result->SetString(L"title", UTF16ToWide(contents->GetTitle()));
- result->SetBoolean(L"selected", tab_index == tab_strip->selected_index());
-
- NavigationEntry* entry = contents->controller().GetActiveEntry();
- if (entry) {
- if (entry->favicon().is_valid())
- result->SetString(L"favIconUrl", entry->favicon().url().spec());
- }
-
- return result;
-}
-
static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
int* tab_index) {
for (int i = 0; i < tab_strip->count(); ++i) {
diff --git a/chrome/browser/extensions/extension_tabs_module.h b/chrome/browser/extensions/extension_tabs_module.h
index 90c8647..c139f6a 100644
--- a/chrome/browser/extensions/extension_tabs_module.h
+++ b/chrome/browser/extensions/extension_tabs_module.h
@@ -8,13 +8,18 @@
#include "chrome/browser/extensions/extension_function.h"
class Browser;
+class DictionaryValue;
class TabContents;
+class TabStripModel;
class ExtensionTabUtil {
public:
static int GetWindowId(const Browser* browser);
static int GetTabId(const TabContents* tab_contents);
static int GetWindowIdOfTab(const TabContents* tab_contents);
+ static DictionaryValue* CreateTabValue(const TabContents* tab_contents);
+ static DictionaryValue* CreateTabValue(
+ const TabContents* tab_contents, TabStripModel* tab_strip, int tab_index);
};
class GetWindowsFunction : public SyncExtensionFunction {
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 3646358..c3d7aeb 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -15,8 +15,9 @@
#include "chrome/browser/cross_site_request_manager.h"
#include "chrome/browser/debugger/debugger_wrapper.h"
#include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/profile.h"
+#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/renderer_security_policy.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
@@ -26,13 +27,13 @@
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/common/bindings_policy.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/resource_bundle.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/resource_bundle.h"
#include "chrome/common/result_codes.h"
-#include "chrome/common/url_constants.h"
#include "chrome/common/thumbnail_score.h"
+#include "chrome/common/url_constants.h"
#include "net/base/net_util.h"
#include "skia/include/SkBitmap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
@@ -775,6 +776,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_PasteFromSelectionClipboard,
OnMsgPasteFromSelectionClipboard)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage,
+ OnExtensionPostMessage)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg))
IPC_END_MESSAGE_MAP_EX()
@@ -1368,3 +1371,10 @@ void RenderViewHost::SendExtensionResponse(int callback_id,
const std::string& response) {
Send(new ViewMsg_ExtensionResponse(routing_id(), callback_id, response));
}
+
+void RenderViewHost::OnExtensionPostMessage(
+ int port_id, const std::string& message) {
+ URLRequestContext* context = process()->profile()->GetRequestContext();
+ ExtensionMessageService::GetInstance(context)->
+ PostMessageFromRenderer(port_id, message);
+}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 0125b50..b86b5f5 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -543,6 +543,7 @@ class RenderViewHost : public RenderWidgetHost {
void OnExtensionRequest(const std::string& name, const std::string& args,
int callback_id);
+ void OnExtensionPostMessage(int port_id, const std::string& message);
// Helper function to send a navigation message. If a cross-site request is
// in progress, we may be suspended while waiting for the onbeforeunload
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 804042f..3fc0602 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -193,10 +193,6 @@ void ResourceMessageFilter::OnChannelConnected(int32 peer_pid) {
// Hook AudioRendererHost to this object after channel is connected so it can
// this object for sending messages.
audio_renderer_host_->IPCChannelConnected(render_process_id_, handle(), this);
-
- // Ditto for the ExtensionMessageService.
- ExtensionMessageService::GetInstance(request_context_.get())->
- RendererReady(this);
}
// Called on the IPC thread:
@@ -299,8 +295,6 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension,
OnOpenChannelToExtension)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage,
- OnExtensionPostMessage)
IPC_MESSAGE_UNHANDLED(
handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -829,13 +823,7 @@ void ResourceMessageFilter::OnFreeTransportDIB(
#endif
void ResourceMessageFilter::OnOpenChannelToExtension(
- const std::string& extension_id, int* port_id) {
+ int routing_id, const std::string& extension_id, int* port_id) {
*port_id = ExtensionMessageService::GetInstance(request_context_.get())->
- OpenChannelToExtension(extension_id, this);
-}
-
-void ResourceMessageFilter::OnExtensionPostMessage(
- int port_id, const std::string& message) {
- ExtensionMessageService::GetInstance(request_context_.get())->
- PostMessageFromRenderer(port_id, message, this);
+ OpenChannelToExtension(routing_id, extension_id, this);
}
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 74181bf..e16ac8d 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -202,8 +202,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
TransportDIB::Handle* result);
void OnFreeTransportDIB(TransportDIB::Id dib_id);
- void OnOpenChannelToExtension(const std::string& extension_id, int* port_id);
- void OnExtensionPostMessage(int port_id, const std::string& message);
+ void OnOpenChannelToExtension(int routing_id,
+ const std::string& extension_id, int* port_id);
#if defined(OS_LINUX)
void SendDelayedReply(IPC::Message* reply_msg);
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 60f250e..3279f60 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1589,6 +1589,7 @@
# short term I'd like the build to work.
'renderer/automation/dom_automation_controller.cc',
'renderer/automation/dom_automation_controller.h',
+ 'renderer/extensions/bindings_utils.cc',
'renderer/extensions/bindings_utils.h',
'renderer/extensions/event_bindings.cc',
'renderer/extensions/event_bindings.h',
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 66f64b4..776fd44d 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -535,9 +535,11 @@ IPC_BEGIN_MESSAGES(View)
// Tell the extension process about a new channel that has been opened from a
// renderer. source_port_id identifies the port that the extension can
- // respond to.
- IPC_MESSAGE_CONTROL1(ViewMsg_ExtensionHandleConnect,
- int /* source_port_id */)
+ // respond to. tab_json is a JSON value for the tab that opened the
+ // connection, if any.
+ IPC_MESSAGE_CONTROL2(ViewMsg_ExtensionHandleConnect,
+ int /* source_port_id */,
+ std::string /* tab_json */)
// Send a javascript message to a renderer from the given port.
IPC_MESSAGE_CONTROL2(ViewMsg_ExtensionHandleMessage,
@@ -1339,15 +1341,16 @@ IPC_BEGIN_MESSAGES(ViewHost)
// Get a port handle to a currently-running extension process for the
// extension with the given ID. If no such extension is found, -1 is
// returned. The handle can be used for sending messages to the extension.
- IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_OpenChannelToExtension,
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_OpenChannelToExtension,
+ int /* routing_id */,
std::string /* extension_id */,
int /* port_id */)
// Send a message to an extension process. The handle is the value returned
// by ViewHostMsg_OpenChannelToExtension.
- IPC_MESSAGE_CONTROL2(ViewHostMsg_ExtensionPostMessage,
- int /* port_id */,
- std::string /* message */)
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_ExtensionPostMessage,
+ int /* port_id */,
+ std::string /* message */)
// Message to show a popup menu using native cocoa controls (Mac only).
IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
diff --git a/chrome/renderer/extensions/bindings_utils.cc b/chrome/renderer/extensions/bindings_utils.cc
new file mode 100644
index 0000000..ee4688d
--- /dev/null
+++ b/chrome/renderer/extensions/bindings_utils.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2009 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.
+
+#include "chrome/renderer/extensions/bindings_utils.h"
+
+#include "chrome/renderer/render_view.h"
+#include "webkit/glue/webframe.h"
+
+RenderView* GetActiveRenderView() {
+ WebFrame* webframe = WebFrame::RetrieveActiveFrame();
+ DCHECK(webframe) << "GetActiveRenderView called when not in a V8 context.";
+ if (!webframe)
+ return NULL;
+
+ WebView* webview = webframe->GetView();
+ if (!webview)
+ return NULL; // can happen during closing
+
+ RenderView* renderview = static_cast<RenderView*>(webview->GetDelegate());
+ DCHECK(renderview) << "Encountered a WebView without a WebViewDelegate";
+ return renderview;
+}
diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h
index 9e7d213..84fb32f 100755
--- a/chrome/renderer/extensions/bindings_utils.h
+++ b/chrome/renderer/extensions/bindings_utils.h
@@ -10,6 +10,8 @@
#include <string>
+class RenderView;
+
template<int kResourceId>
struct StringResourceTemplate {
StringResourceTemplate()
@@ -25,4 +27,8 @@ const char* GetStringResource() {
Singleton< StringResourceTemplate<kResourceId> >::get()->resource.c_str();
}
+// Returns the active RenderView, based on which V8 context is active. It is
+// an error to call this when not in a V8 context.
+RenderView* GetActiveRenderView();
+
#endif // CHROME_RENDERER_EXTENSIONS_BINDINGS_UTILS_H_
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index fcf9710..1c1ac79 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -70,16 +70,9 @@ class ExtensionImpl : public v8::Extension {
static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) {
WebFrame* webframe = WebFrame::RetrieveActiveFrame();
- DCHECK(webframe) << "There should be an active frame since we just got "
- "a native function called.";
- if (!webframe) return v8::Undefined();
-
- WebView* webview = webframe->GetView();
- if (!webview) return v8::Undefined(); // can happen during closing
-
- RenderView* renderview = static_cast<RenderView*>(webview->GetDelegate());
- DCHECK(renderview) << "Encountered a WebView without a WebViewDelegate";
- if (!renderview) return v8::Undefined();
+ RenderView* renderview = GetActiveRenderView();
+ if (!webframe || !renderview)
+ return v8::Undefined();
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsInt32())
return v8::Undefined();
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc
index 63214d73..28b5c47 100755
--- a/chrome/renderer/extensions/renderer_extension_bindings.cc
+++ b/chrome/renderer/extensions/renderer_extension_bindings.cc
@@ -10,6 +10,7 @@
#include "chrome/renderer/extensions/bindings_utils.h"
#include "chrome/renderer/extensions/event_bindings.h"
#include "chrome/renderer/render_thread.h"
+#include "chrome/renderer/render_view.h"
#include "grit/renderer_resources.h"
// Message passing API example (in a content script):
@@ -24,9 +25,6 @@
namespace {
-// We use the generic interface so that unit tests can inject a mock.
-RenderThreadBase* render_thread_ = NULL;
-
const char* kExtensionDeps[] = { EventBindings::kName };
class ExtensionImpl : public v8::Extension {
@@ -51,11 +49,15 @@ class ExtensionImpl : public v8::Extension {
// Creates a new messaging channel to the given extension.
static v8::Handle<v8::Value> OpenChannelToExtension(
const v8::Arguments& args) {
+ RenderView* renderview = GetActiveRenderView();
+ if (!renderview)
+ return v8::Undefined();
+
if (args.Length() >= 1 && args[0]->IsString()) {
std::string id = *v8::String::Utf8Value(args[0]->ToString());
int port_id = -1;
- render_thread_->Send(
- new ViewHostMsg_OpenChannelToExtension(id, &port_id));
+ renderview->Send(new ViewHostMsg_OpenChannelToExtension(
+ renderview->routing_id(), id, &port_id));
return v8::Integer::New(port_id);
}
return v8::Undefined();
@@ -63,11 +65,15 @@ class ExtensionImpl : public v8::Extension {
// Sends a message along the given channel.
static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) {
+ RenderView* renderview = GetActiveRenderView();
+ if (!renderview)
+ return v8::Undefined();
+
if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) {
int port_id = args[0]->Int32Value();
std::string message = *v8::String::Utf8Value(args[1]->ToString());
- render_thread_->Send(
- new ViewHostMsg_ExtensionPostMessage(port_id, message));
+ renderview->Send(new ViewHostMsg_ExtensionPostMessage(
+ renderview->routing_id(), port_id, message));
}
return v8::Undefined();
}
@@ -78,15 +84,16 @@ class ExtensionImpl : public v8::Extension {
const char* RendererExtensionBindings::kName =
"chrome/RendererExtensionBindings";
-v8::Extension* RendererExtensionBindings::Get(RenderThreadBase* render_thread) {
- render_thread_ = render_thread;
+v8::Extension* RendererExtensionBindings::Get() {
return new ExtensionImpl();
}
-void RendererExtensionBindings::HandleConnect(int port_id) {
+void RendererExtensionBindings::HandleConnect(int port_id,
+ const std::string& tab_json) {
v8::HandleScope handle_scope;
- v8::Handle<v8::Value> argv[1];
+ v8::Handle<v8::Value> argv[2];
argv[0] = v8::Integer::New(port_id);
+ argv[1] = v8::String::New(tab_json.c_str());
EventBindings::CallFunction("chromium.Port.dispatchOnConnect_",
arraysize(argv), argv);
}
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h
index 374dfb6..ad370af 100755
--- a/chrome/renderer/extensions/renderer_extension_bindings.h
+++ b/chrome/renderer/extensions/renderer_extension_bindings.h
@@ -19,11 +19,12 @@ class RendererExtensionBindings {
static const char* kName;
// Creates an instance of the extension.
- static v8::Extension* Get(RenderThreadBase* render_thread);
+ static v8::Extension* Get();
// Notify any listeners that a message channel has been opened to this
- // process.
- static void HandleConnect(int port_id);
+ // process. |tab_json| is the info for the tab that initiated this
+ // connection, or "null" if the initiator was not a tab.
+ static void HandleConnect(int port_id, const std::string& tab_json);
// Dispatch the given message sent on this channel.
static void HandleMessage(const std::string& message, int port_id);
diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc
index b133238..7812b31 100644
--- a/chrome/renderer/mock_render_thread.cc
+++ b/chrome/renderer/mock_render_thread.cc
@@ -92,7 +92,7 @@ void MockRenderThread::OnMsgCreateWidget(int opener_id,
}
void MockRenderThread::OnMsgOpenChannelToExtension(
- const std::string& extension_id, int* channel_id) {
+ int routing_id, const std::string& extension_id, int* channel_id) {
*channel_id = 0;
}
diff --git a/chrome/renderer/mock_render_thread.h b/chrome/renderer/mock_render_thread.h
index f88543b..e4f2403 100644
--- a/chrome/renderer/mock_render_thread.h
+++ b/chrome/renderer/mock_render_thread.h
@@ -74,7 +74,8 @@ class MockRenderThread : public RenderThreadBase {
int* route_id);
// The callee expects to be returned a valid channel_id.
- void OnMsgOpenChannelToExtension(const std::string& extension_id,
+ void OnMsgOpenChannelToExtension(int routing_id,
+ const std::string& extension_id,
int* channel_id);
// The RenderView expects default print settings.
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 26836ca..afe3f38 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -314,7 +314,7 @@ void RenderThread::EnsureWebKitInitialized() {
WebKit::registerExtension(JsonJsV8Extension::Get());
WebKit::registerExtension(JsonSchemaJsV8Extension::Get());
WebKit::registerExtension(EventBindings::Get());
- WebKit::registerExtension(RendererExtensionBindings::Get(this));
+ WebKit::registerExtension(RendererExtensionBindings::Get());
}
if (command_line.HasSwitch(switches::kPlaybackMode) ||
@@ -328,8 +328,9 @@ void RenderThread::EnsureWebKitInitialized() {
}
}
-void RenderThread::OnExtensionHandleConnect(int port_id) {
- RendererExtensionBindings::HandleConnect(port_id);
+void RenderThread::OnExtensionHandleConnect(int port_id,
+ const std::string& tab_json) {
+ RendererExtensionBindings::HandleConnect(port_id, tab_json);
}
void RenderThread::OnExtensionHandleMessage(const std::string& message,
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index d50fd96..24b4574 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -127,7 +127,7 @@ class RenderThread : public RenderThreadBase,
// Send all histograms to browser.
void OnGetRendererHistograms();
- void OnExtensionHandleConnect(int channel_id);
+ void OnExtensionHandleConnect(int channel_id, const std::string& tab_json);
void OnExtensionHandleMessage(const std::string& message, int channel_id);
void OnExtensionHandleEvent(const std::string event_name,
const std::string event_data);
diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj
index d0c9de4..249f133 100644
--- a/chrome/renderer/renderer.vcproj
+++ b/chrome/renderer/renderer.vcproj
@@ -193,6 +193,10 @@
Name="extensions"
>
<File
+ RelativePath=".\extensions\bindings_utils.cc"
+ >
+ </File>
+ <File
RelativePath=".\extensions\bindings_utils.h"
>
</File>
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index c59e98c..beb23b7 100755
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. -->
+without changes to the corresponding grd file. 1 -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index 19518db..11494e3 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -30,8 +30,12 @@ var chromium = chromium || {};
chromium.Port.ports_ = {};
// Called by native code when a channel has been opened to this context.
- chromium.Port.dispatchOnConnect_ = function(portId) {
+ chromium.Port.dispatchOnConnect_ = function(portId, tab) {
var port = new chromium.Port(portId);
+ if (tab) {
+ tab = goog.json.parse(tab);
+ }
+ port.tab = tab;
chromium.Event.dispatch_("channel-connect", [port]);
};
diff --git a/chrome/test/data/extensions/good/extension1/1/toolstrip1.html b/chrome/test/data/extensions/good/extension1/1/toolstrip1.html
index fa244f8..d36de21 100644
--- a/chrome/test/data/extensions/good/extension1/1/toolstrip1.html
+++ b/chrome/test/data/extensions/good/extension1/1/toolstrip1.html
@@ -22,7 +22,7 @@ body {
chromium.onconnect.addListener(function (port) {
port.onmessage.addListener(doOnMessage);
- port.postMessage('extension onconnect');
+ port.postMessage('extension onconnect: ' + port.tab.url);
});
function doOnMessage(msg, port) {
diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc
index 81d7347..583fff6 100644
--- a/chrome/test/render_view_test.cc
+++ b/chrome/test/render_view_test.cc
@@ -58,7 +58,7 @@ void RenderViewTest::SetUp() {
WebKit::registerExtension(JsonSchemaJsV8Extension::Get());
WebKit::registerExtension(EventBindings::Get());
WebKit::registerExtension(ExtensionProcessBindings::Get());
- WebKit::registerExtension(RendererExtensionBindings::Get(&render_thread_));
+ WebKit::registerExtension(RendererExtensionBindings::Get());
EventBindings::SetRenderThread(&render_thread_);
// TODO(aa): Should some of this go to some other inheriting class?