diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 19:26:35 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 19:26:35 +0000 |
commit | 0f605396ab522e1f2f48824c42bb784e9784d479 (patch) | |
tree | 062f717563b296a520791bd29c25fd21038b2920 /chrome/browser/extensions | |
parent | 609a1ec621cdcce03328b56e4b744ce9498b2177 (diff) | |
download | chromium_src-0f605396ab522e1f2f48824c42bb784e9784d479.zip chromium_src-0f605396ab522e1f2f48824c42bb784e9784d479.tar.gz chromium_src-0f605396ab522e1f2f48824c42bb784e9784d479.tar.bz2 |
Make the API to open a message channel symmetric, so it works the same whether opening from a tab or extension.
Also, move the callback handling back to extension_process_bindings, since I
didn't need it in event_bindings to implement this, and it didn't make sense
there anyway.
BUG=12461
TEST=no
Review URL: http://codereview.chromium.org/149237
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20296 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
6 files changed, 222 insertions, 162 deletions
diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc index b594477..0211b96 100644 --- a/chrome/browser/extensions/extension_browsertests_misc.cc +++ b/chrome/browser/extensions/extension_browsertests_misc.cc @@ -17,8 +17,29 @@ #include "chrome/browser/views/frame/browser_view.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension_error_reporter.h" +#include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" +#include "net/base/net_util.h" + +// Looks for an ExtensionHost whose URL has the given path component (including +// leading slash). Also verifies that the expected number of hosts are loaded. +static ExtensionHost* FindHostWithPath(ExtensionProcessManager* manager, + const std::string& path, + int expected_hosts) { + ExtensionHost* host = NULL; + int num_hosts = 0; + for (ExtensionProcessManager::const_iterator iter = manager->begin(); + iter != manager->end(); ++iter) { + if ((*iter)->GetURL().path() == path) { + EXPECT_FALSE(host); + host = *iter; + } + num_hosts++; + } + EXPECT_EQ(expected_hosts, num_hosts); + return host; +} // Tests that toolstrips initializes properly and can run basic extension js. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, Toolstrip) { @@ -31,17 +52,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, Toolstrip) { // extension has two toolstrips. Find the one that is hosting toolstrip1.html. ExtensionProcessManager* manager = browser()->profile()->GetExtensionProcessManager(); - ExtensionHost* host = NULL; - int num_hosts = 0; - for (ExtensionProcessManager::const_iterator iter = manager->begin(); - iter != manager->end(); ++iter) { - if ((*iter)->GetURL().path() == "/toolstrip1.html") { - ASSERT_FALSE(host); - host = *iter; - } - num_hosts++; - } - EXPECT_EQ(2, num_hosts); + ExtensionHost* host = FindHostWithPath(manager, "/toolstrip1.html", 2); // Tell it to run some JavaScript that tests that basic extension code works. bool result = false; @@ -105,3 +116,102 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TabContents) { L"testTabsAPI()", &result); EXPECT_TRUE(result); } + +// Tests that message passing between extensions and tabs works. +IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, MessagingExtensionTab) { + ASSERT_TRUE(LoadExtension( + test_data_dir_.AppendASCII("good").AppendASCII("Extensions") + .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa") + .AppendASCII("1.0"))); + + // Get the ExtensionHost that is hosting our background page. + ExtensionProcessManager* manager = + browser()->profile()->GetExtensionProcessManager(); + ExtensionHost* host = FindHostWithPath(manager, "/background.html", 1); + + // Load the tab that will communicate with our background page. + ui_test_utils::NavigateToURL( + browser(), + GURL("chrome-extension://bjafgdebaacbbbecmhlhpofkepfkgcpa/page.html")); + + // First test that tab->extension messaging works. + bool result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents()->render_view_host(), L"", + L"testPostMessageFromTab()", &result); + EXPECT_TRUE(result); + + // Now test extension->tab messaging, with disconnect events. + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testDisconnect()", &result); + EXPECT_TRUE(result); + + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testPostMessage()", &result); + EXPECT_TRUE(result); + + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testDisconnectOnClose()", &result); + EXPECT_TRUE(result); +} + +// TODO(mpcomplete): reenable this when content script messaging is fixed: +// http://code.google.com/p/chromium/issues/detail?id=16228. +#if 0 +// Tests that message passing between extensions and content scripts works. +IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, MessagingContentScript) { + ASSERT_TRUE(LoadExtension( + test_data_dir_.AppendASCII("good").AppendASCII("Extensions") + .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa") + .AppendASCII("1.0"))); + + UserScriptMaster* master = browser()->profile()->GetUserScriptMaster(); + if (!master->ScriptsReady()) { + // Wait for UserScriptMaster to finish its scan. + NotificationRegistrar registrar; + registrar.Add(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + ui_test_utils::RunMessageLoop(); + } + ASSERT_TRUE(master->ScriptsReady()); + + // Get the ExtensionHost that is hosting our background page. + ExtensionProcessManager* manager = + browser()->profile()->GetExtensionProcessManager(); + ExtensionHost* host = FindHostWithPath(manager, "/background.html", 1); + + // Load the tab whose content script will communicate with our background + // page. + FilePath test_file; + PathService::Get(chrome::DIR_TEST_DATA, &test_file); + test_file = test_file.AppendASCII("extensions") + .AppendASCII("test_file.html"); + ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); + + // First test that tab->extension messaging works. + bool result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents()->render_view_host(), L"", + L"testPostMessageFromTab()", &result); + EXPECT_TRUE(result); + + // Now test extension->tab messaging, with disconnect events. + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testDisconnect()", &result); + EXPECT_TRUE(result); + + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testPostMessage()", &result); + EXPECT_TRUE(result); + + result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + host->render_view_host(), L"", L"testDisconnectOnClose()", &result); + EXPECT_TRUE(result); +} +#endif
\ No newline at end of file diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 24eacf2..70cb59e 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -183,12 +183,9 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( url_(url), ALLOW_THIS_IN_INITIALIZER_LIST(peer_(new Peer(this))) { all_instances()->insert(this); - RenderProcessHost* process = render_view_host_->process(); - ExtensionMessageService* message_service = - ExtensionMessageService::GetInstance(profile()->GetRequestContext()); - DCHECK(process); - DCHECK(message_service); - message_service->RegisterExtension(extension_id(), process->pid()); + + // Ensure the message service is initialized. + ExtensionMessageService::GetInstance(profile()->GetRequestContext())->Init(); } ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc index 4929eea..78dd1f2 100644 --- a/chrome/browser/extensions/extension_message_service.cc +++ b/chrome/browser/extensions/extension_message_service.cc @@ -23,11 +23,11 @@ // Since we have 2 ports for every channel, we just index channels by half the // port ID. #define GET_CHANNEL_ID(port_id) ((port_id) / 2) -#define GET_CHANNEL_PORT1(channel_id) ((channel_id) * 2) -#define GET_CHANNEL_PORT2(channel_id) ((channel_id) * 2 + 1) +#define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) +#define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) // Port1 is always even, port2 is always odd. -#define IS_PORT1_ID(port_id) (((port_id) & 1) == 0) +#define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) // Change even to odd and vice versa, to get the other side of a given channel. #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) @@ -80,6 +80,10 @@ static void DispatchEvent(IPC::Message::Sender* channel, ExtensionMessageService::kDispatchEvent, args)); } +static std::string GetChannelConnectEvent(const std::string& extension_id) { + return StringPrintf("channel-connect:%s", extension_id.c_str()); +} + } // namespace // Since ExtensionMessageService is a collection of Singletons, we don't need to @@ -132,19 +136,6 @@ void ExtensionMessageService::Init() { NotificationService::AllSources()); } -void ExtensionMessageService::RegisterExtension( - const std::string& extension_id, int render_process_id) { - 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); - process_ids_[extension_id] = render_process_id; -} - void ExtensionMessageService::AddEventListener(std::string event_name, int render_process_id) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); @@ -166,54 +157,24 @@ void ExtensionMessageService::AllocatePortIdPair(int* port1, int* port2) { int port1_id = next_port_id_++; int port2_id = next_port_id_++; - DCHECK(IS_PORT1_ID(port1_id)); + DCHECK(IS_OPENER_PORT_ID(port1_id)); DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); int channel_id = GET_CHANNEL_ID(port1_id); - DCHECK(GET_CHANNEL_PORT1(channel_id) == port1_id); - DCHECK(GET_CHANNEL_PORT2(channel_id) == port2_id); + DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); + DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); *port1 = port1_id; *port2 = port2_id; } -int ExtensionMessageService::GetProcessIdForExtension( - const std::string& extension_id) { - AutoLock lock(process_ids_lock_); - ProcessIDMap::iterator process_id_it = process_ids_.find( - StringToLowerASCII(extension_id)); - if (process_id_it == process_ids_.end()) - return -1; - return process_id_it->second; -} - -RenderProcessHost* ExtensionMessageService::GetProcessForExtension( - const std::string& extension_id) { - DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); - - int process_id = GetProcessIdForExtension(extension_id); - if (process_id == -1) - return NULL; - - RenderProcessHost* host = RenderProcessHost::FromID(process_id); - DCHECK(host); - - return host; -} - int ExtensionMessageService::OpenChannelToExtension( 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 = GetProcessIdForExtension(extension_id); - if (process_id == -1) - return -1; - DCHECK(initialized_); // Create a channel ID for both sides of the channel. @@ -223,37 +184,49 @@ int ExtensionMessageService::OpenChannelToExtension( ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &ExtensionMessageService::OpenChannelOnUIThread, - routing_id, port1_id, source->GetProcessId(), port2_id, process_id, - extension_id)); + routing_id, port1_id, source->GetProcessId(), extension_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, const std::string& extension_id) { + const std::string& extension_id) { RenderProcessHost* source = RenderProcessHost::FromID(source_process_id); OpenChannelOnUIThreadImpl(source_routing_id, source_port_id, - source_process_id, source, dest_port_id, - dest_process_id, extension_id); + source_process_id, source, extension_id); } void ExtensionMessageService::OpenChannelOnUIThreadImpl( int source_routing_id, int source_port_id, int source_process_id, - IPC::Message::Sender* source, int dest_port_id, int dest_process_id, - const std::string& extension_id) { + IPC::Message::Sender* source, const std::string& extension_id) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); - MessageChannel channel; - channel.port1 = source; - channel.port2 = RenderProcessHost::FromID(dest_process_id); - if (!channel.port1 || !channel.port2) { - // One of the processes could have been closed while posting this task. + if (!source) + return; // Source closed while task was in flight. + + linked_ptr<MessageChannel> channel(new MessageChannel); + channel->opener.insert(source); + + // Get the list of processes that are listening for this extension's channel + // connect event. + std::string event_name = GetChannelConnectEvent(extension_id); + std::set<int>& pids = listeners_[event_name]; + for (std::set<int>::iterator pid = pids.begin(); pid != pids.end(); ++pid) { + RenderProcessHost* renderer = RenderProcessHost::FromID(*pid); + if (!renderer) + continue; + channel->receivers.insert(renderer); + } + if (channel->receivers.empty()) { + // Either no one is listening, or all listeners have since closed. + // TODO(mpcomplete): should we notify the source? return; } channels_[GET_CHANNEL_ID(source_port_id)] = channel; + // Include info about the opener's tab (if it was a tab). std::string tab_json = "null"; TabContents* contents = tab_util::GetTabContentsByID(source_process_id, source_routing_id); @@ -262,20 +235,18 @@ void ExtensionMessageService::OpenChannelOnUIThreadImpl( JSONWriter::Write(tab_value, false, &tab_json); } - // Send the process the id for the opposite port. - DispatchOnConnect(channel.port2, source_port_id, tab_json, extension_id); + // Broadcast the connect event to the receivers. Give them the opener's + // port ID (the opener has the opposite port ID). + for (MessageChannel::Ports::iterator it = channel->receivers.begin(); + it != channel->receivers.end(); ++it) { + DispatchOnConnect(*it, source_port_id, tab_json, extension_id); + } } int ExtensionMessageService::OpenAutomationChannelToExtension( int source_process_id, int routing_id, const std::string& extension_id, IPC::Message::Sender* source) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); - - // Lookup the targeted extension process. - int process_id = GetProcessIdForExtension(extension_id); - if (process_id == -1) - return -1; - DCHECK(initialized_); int port1_id = -1; @@ -289,7 +260,7 @@ int ExtensionMessageService::OpenAutomationChannelToExtension( // information should be supplied by the caller for // automation-initiated ports. OpenChannelOnUIThreadImpl(routing_id, port1_id, source_process_id, - source, port2_id, process_id, extension_id); + source, extension_id); return port2_id; } @@ -304,38 +275,41 @@ void ExtensionMessageService::CloseChannel(int port_id) { } void ExtensionMessageService::CloseChannelImpl( - MessageChannelMap::iterator channel_iter, int port_id) { + MessageChannelMap::iterator channel_iter, int closing_port_id) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); // Notify the other side. - if (port_id == GET_CHANNEL_PORT1(channel_iter->first)) { - DispatchOnDisconnect(channel_iter->second.port2, - GET_OPPOSITE_PORT_ID(port_id)); - } else { - DCHECK_EQ(port_id, GET_CHANNEL_PORT2(channel_iter->first)); - DispatchOnDisconnect(channel_iter->second.port1, - GET_OPPOSITE_PORT_ID(port_id)); + MessageChannel::Ports* ports = + IS_OPENER_PORT_ID(closing_port_id) ? + &channel_iter->second->receivers : &channel_iter->second->opener; + + for (MessageChannel::Ports::iterator it = ports->begin(); + it != ports->end(); ++it) { + DispatchOnDisconnect(*it, GET_OPPOSITE_PORT_ID(closing_port_id)); } channels_.erase(channel_iter); } void ExtensionMessageService::PostMessageFromRenderer( - int port_id, const std::string& message) { + int dest_port_id, const std::string& message) { DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); MessageChannelMap::iterator iter = - channels_.find(GET_CHANNEL_ID(port_id)); + channels_.find(GET_CHANNEL_ID(dest_port_id)); if (iter == channels_.end()) return; - MessageChannel& channel = iter->second; // Figure out which port the ID corresponds to. - IPC::Message::Sender* dest = - IS_PORT1_ID(port_id) ? channel.port1 : channel.port2; - - int source_port_id = GET_OPPOSITE_PORT_ID(port_id); - DispatchOnMessage(dest, message, source_port_id); + MessageChannel::Ports* ports = + IS_OPENER_PORT_ID(dest_port_id) ? + &iter->second->opener : &iter->second->receivers; + int source_port_id = GET_OPPOSITE_PORT_ID(dest_port_id); + + for (MessageChannel::Ports::iterator it = ports->begin(); + it != ports->end(); ++it) { + DispatchOnMessage(*it, message, source_port_id); + } } void ExtensionMessageService::DispatchEventToRenderers( @@ -369,26 +343,24 @@ void ExtensionMessageService::Observe(NotificationType type, RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr(); - { - 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. We notify the opposite // port that his pair has closed. for (MessageChannelMap::iterator it = channels_.begin(); it != channels_.end(); ) { MessageChannelMap::iterator current = it++; - if (current->second.port1 == renderer) { - CloseChannelImpl(current, GET_CHANNEL_PORT1(current->first)); - } else if (current->second.port2 == renderer) { - CloseChannelImpl(current, GET_CHANNEL_PORT2(current->first)); + if (current->second->opener.count(renderer) > 0) { + CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first)); + } else if (current->second->receivers.count(renderer) > 0) { + CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first)); } } + + // Remove this renderer from our listener maps. + for (ListenerMap::iterator it = listeners_.begin(); + it != listeners_.end(); ) { + ListenerMap::iterator current = it++; + current->second.erase(renderer->pid()); + if (current->second.empty()) + listeners_.erase(current); + } } diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h index e3b7ba8..7a87adf 100644 --- a/chrome/browser/extensions/extension_message_service.h +++ b/chrome/browser/extensions/extension_message_service.h @@ -9,6 +9,7 @@ #include <set> #include <string> +#include "base/linked_ptr.h" #include "base/lock.h" #include "chrome/common/ipc_message.h" #include "chrome/common/notification_registrar.h" @@ -43,12 +44,8 @@ class ExtensionMessageService : public NotificationObserver { // --- UI thread only: - // Gets the process for the specified extension. - RenderProcessHost* GetProcessForExtension(const std::string& extension_id); - - // Register an extension and its corresponding renderer process. - void RegisterExtension(const std::string& extension_id, - int render_process_id); + // UI-thread specific initialization. Does nothing if called more than once. + void Init(); // Add or remove |render_process_pid| as a listener for |event_name|. void AddEventListener(std::string event_name, int render_process_id); @@ -87,71 +84,54 @@ class ExtensionMessageService : public NotificationObserver { // message. int OpenChannelToExtension(int routing_id, const std::string& extension_id, ResourceMessageFilter* source); - + private: - // The connection between two ports. It is possible that both ports - // refer to the same renderer. + // A messaging channel. Since messages are broadcast, the channel can have + // multiple processes listening for messages. Note that the opening port + // can also be among the receivers, if an extension toolstrip wants to talk + // to its tab (for example). struct MessageChannel { - IPC::Message::Sender* port1; - IPC::Message::Sender* port2; + typedef std::set<IPC::Message::Sender*> Ports; + Ports opener; // only 1 opener, but we use a set to simplify logic + Ports receivers; }; // A map of channel ID to its channel object. - typedef std::map<int, MessageChannel> MessageChannelMap; + typedef std::map<int, linked_ptr<MessageChannel> > MessageChannelMap; // Allocates a pair of port ids. // NOTE: this can be called from any thread. void AllocatePortIdPair(int* port1, int* port2); - // Gets the process ID for the specified extension. - // NOTE: this can be called from any thread. - int GetProcessIdForExtension(const std::string& extension_id); - void CloseChannelImpl(MessageChannelMap::iterator channel_iter, int port_id); - int OpenChannelToExtensionImpl(const std::string& extension_id, - IPC::Message::Sender* source); - - NotificationRegistrar registrar_; - // 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_; - - // Protects the process_ids map, since it can be accessed on the IO thread - // or UI thread. Be careful not to hold this lock when calling external - // code (especially sending messages) to avoid deadlock. - Lock process_ids_lock_; - - // A map between an event name and a set of process id's that are listening - // to that event. - typedef std::map<std::string, std::set<int> > ListenerMap; - ListenerMap listeners_; - // --- UI thread only: - // UI-thread specific initialization. Does nothing if called more than once. - void Init(); - // 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, const std::string& extension_id); - // Common between OpenChannelOnUIThread and - // OpenAutomationChannelToExtension. + // Common between OpenChannelOnUIThread and OpenAutomationChannelToExtension. void OpenChannelOnUIThreadImpl( int source_routing_id, int source_port_id, int source_process_id, - IPC::Message::Sender* source, int dest_port_id, int dest_process_id, - const std::string& extension_id); + IPC::Message::Sender* source, const std::string& extension_id); + + NotificationRegistrar registrar_; MessageChannelMap channels_; + // A map between an event name and a set of process id's that are listening + // to that event. + typedef std::map<std::string, std::set<int> > ListenerMap; + ListenerMap listeners_; + + // --- UI or IO thread: + // True if Init has been called. bool initialized_; diff --git a/chrome/browser/extensions/extension_messages_unittest.cc b/chrome/browser/extensions/extension_messages_unittest.cc index 86a3180..27a5bd9 100644 --- a/chrome/browser/extensions/extension_messages_unittest.cc +++ b/chrome/browser/extensions/extension_messages_unittest.cc @@ -13,6 +13,7 @@ static void DispatchOnConnect(int source_port_id, const std::string& tab_json) { ListValue args; args.Set(0, Value::CreateIntegerValue(source_port_id)); args.Set(1, Value::CreateStringValue(tab_json)); + args.Set(2, Value::CreateStringValue("")); // extension ID is empty for tests RendererExtensionBindings::Invoke( ExtensionMessageService::kDispatchOnConnect, args); } diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index ac0bd97..555655c 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -572,7 +572,7 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { EXPECT_EQ(std::string(good2), loaded_[2]->id()); EXPECT_EQ(std::string("My extension 3"), loaded_[2]->name()); EXPECT_EQ(std::string(""), loaded_[2]->description()); - EXPECT_EQ(0u, loaded_[2]->content_scripts().size()); + EXPECT_EQ(1u, loaded_[2]->content_scripts().size()); EXPECT_EQ(Extension::INTERNAL, loaded_[2]->location()); }; |