diff options
author | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-16 02:41:28 +0000 |
---|---|---|
committer | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-16 02:41:28 +0000 |
commit | b68d5ed3f9d1b49b24713431bfe212b7601b75b1 (patch) | |
tree | 9d374ca1d7c1f5f8a25fefacde0bcf3396595da6 /chrome/browser/extensions | |
parent | f606747ffb21e9d0c6d55c9b57d42445503728f1 (diff) | |
download | chromium_src-b68d5ed3f9d1b49b24713431bfe212b7601b75b1.zip chromium_src-b68d5ed3f9d1b49b24713431bfe212b7601b75b1.tar.gz chromium_src-b68d5ed3f9d1b49b24713431bfe212b7601b75b1.tar.bz2 |
Initial plumbing for sending events from the browser to extension renderers. Implement onTabMoved.
Review URL: http://codereview.chromium.org/73065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13824 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
9 files changed, 211 insertions, 7 deletions
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc new file mode 100644 index 0000000..a80abea --- /dev/null +++ b/chrome/browser/extensions/extension_browser_event_router.cc @@ -0,0 +1,93 @@ +// 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/browser/extensions/extension_browser_event_router.h" + +#include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extension.h" +#include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/extensions/extension_tabs_module.h" +#include "chrome/common/notification_service.h" + +const char* kOnTabMoved = "tab-moved"; + +ExtensionBrowserEventRouter* ExtensionBrowserEventRouter::GetInstance() { + return Singleton<ExtensionBrowserEventRouter>::get(); +} + +void ExtensionBrowserEventRouter::Init() { + if (initialized_) + return; + + NotificationService::current()->AddObserver(this, + NotificationType::BROWSER_OPENED, NotificationService::AllSources()); + NotificationService::current()->AddObserver(this, + NotificationType::BROWSER_CLOSED, NotificationService::AllSources()); + + initialized_ = true; +} + +ExtensionBrowserEventRouter::ExtensionBrowserEventRouter() + : initialized_(false) { } + +// NotificationObserver +void ExtensionBrowserEventRouter::Observe(NotificationType type, + const NotificationSource& source, const NotificationDetails& details) { + Browser* browser; + + switch (type.value) { + case(NotificationType::BROWSER_OPENED) : + browser = Source<Browser>(source).ptr(); + browser->tabstrip_model()->AddObserver(this); + break; + case(NotificationType::BROWSER_CLOSED) : + browser = Source<Browser>(source).ptr(); + browser->tabstrip_model()->RemoveObserver(this); + break; + default: + NOTREACHED(); + break; + } +} + +void ExtensionBrowserEventRouter::TabInsertedAt(TabContents* contents, + int index, + bool foreground) { } + +void ExtensionBrowserEventRouter::TabClosingAt(TabContents* contents, + int index) { } + +void ExtensionBrowserEventRouter::TabDetachedAt(TabContents* contents, + int index) { } + +void ExtensionBrowserEventRouter::TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture) { } + +void ExtensionBrowserEventRouter::TabMoved(TabContents* contents, + int from_index, + int to_index) { + Profile *profile = contents->profile(); + + ListValue args; + DictionaryValue *object_args = new DictionaryValue(); + + object_args->Set(L"tabId", Value::CreateIntegerValue( + ExtensionTabUtil::GetTabId(contents))); + object_args->Set(L"windowId", Value::CreateIntegerValue( + ExtensionTabUtil::GetWindowIdOfTab(contents))); + object_args->Set(L"fromIndex", Value::CreateIntegerValue(from_index)); + object_args->Set(L"toIndex", Value::CreateIntegerValue(to_index)); + + args.Append(object_args); + ExtensionProcessManager::GetInstance()->DispatchEventToRenderers(profile, + kOnTabMoved, args); +} + +void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents, + int index, + bool loading_only) { } + +void ExtensionBrowserEventRouter::TabStripEmpty() { } diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h new file mode 100644 index 0000000..a438e66 --- /dev/null +++ b/chrome/browser/extensions/extension_browser_event_router.h @@ -0,0 +1,55 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ + +#include <vector> +#include <string> + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/common/notification_observer.h" + +// The ExtensionBrowserEventRouter listens to Browser window & tab events +// and routes them to listeners inside extension process renderers. +// ExtensionBrowserEventRouter listens to *all* events, but will only route +// events from windows/tabs within a profile to extension processes in the same +// profile. +class ExtensionBrowserEventRouter : public TabStripModelObserver, + public NotificationObserver { + public: + // Get Browser-Global instance + static ExtensionBrowserEventRouter* GetInstance(); + + // Must be called once. Subsequent calls have no effect. + void Init(); + + // TabStripModelObserver + void TabInsertedAt(TabContents* contents, int index, bool foreground); + void TabClosingAt(TabContents* contents, int index); + void TabDetachedAt(TabContents* contents, int index); + void TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture); + void TabMoved(TabContents* contents, int from_index, int to_index); + void TabChangedAt(TabContents* contents, int index, bool loading_only); + void TabStripEmpty(); + + // NotificationObserver + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: + ExtensionBrowserEventRouter(); + friend struct DefaultSingletonTraits<ExtensionBrowserEventRouter>; + + bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc index 74e2757..3c2c1de 100755 --- a/chrome/browser/extensions/extension_message_service.cc +++ b/chrome/browser/extensions/extension_message_service.cc @@ -54,12 +54,20 @@ ExtensionMessageService::ExtensionMessageService() : next_port_id_(0) { } +std::set<int> ExtensionMessageService::GetUniqueProcessIds() { + std::set<int> ids; + ProcessIDMap::iterator it; + AutoLock lock(renderers_lock_); + + for (it = process_ids_.begin(); it != process_ids_.end(); it++) { + ids.insert(it->second); + } + return ids; +} + void ExtensionMessageService::RegisterExtension( const std::string& extension_id, int render_process_id) { AutoLock lock(renderers_lock_); - // TODO(mpcomplete): We need to ensure an extension always ends up in a single - // process. I think this means having an ExtensionProcessManager which holds - // a BrowsingContext for each extension. DCHECK(process_ids_.find(extension_id) == process_ids_.end() || process_ids_[extension_id] == render_process_id); process_ids_[extension_id] = render_process_id; @@ -174,4 +182,3 @@ void ExtensionMessageService::Observe(NotificationType type, source); } } - diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h index 1238338..f938b51 100755 --- a/chrome/browser/extensions/extension_message_service.h +++ b/chrome/browser/extensions/extension_message_service.h @@ -61,6 +61,8 @@ class ExtensionMessageService : public NotificationObserver { const NotificationSource& source, const NotificationDetails& details); + std::set<int> GetUniqueProcessIds(); + private: // A map of extension ID to the render_process_id that the extension lives in. typedef std::map<std::string, int> ProcessIDMap; diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index e9d7bc9..b2fb63e 100755 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -4,10 +4,14 @@ #include "chrome/browser/extensions/extension_process_manager.h" +#include "base/json_writer.h" #include "base/singleton.h" +#include "base/values.h" #include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_view.h" +#include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/common/render_messages.h" // static ExtensionProcessManager* ExtensionProcessManager::GetInstance() { @@ -23,7 +27,7 @@ ExtensionProcessManager::~ExtensionProcessManager() { ExtensionView* ExtensionProcessManager::CreateView(Extension* extension, const GURL& url, Browser* browser) { - return new ExtensionView(extension, url, + return new ExtensionView(extension, url, GetSiteInstanceForURL(url, browser->profile()), browser); } @@ -34,6 +38,21 @@ SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL( return browsing_instance->GetSiteInstanceForURL(url); } +void ExtensionProcessManager::DispatchEventToRenderers(Profile *profile, + const std::string& event_name, const ListValue& data) { + std::string json_data; + JSONWriter::Write(&data, false, &json_data); + + std::set<int> process_ids = ExtensionMessageService::GetInstance( + profile->GetRequestContext())->GetUniqueProcessIds(); + + std::set<int>::iterator id; + for (id = process_ids.begin(); id != process_ids.end(); ++id) { + RenderProcessHost* rph = RenderProcessHost::FromID(*id); + rph->Send(new ViewMsg_ExtensionHandleEvent(event_name, json_data)); + } +} + BrowsingInstance* ExtensionProcessManager::GetBrowsingInstance( Profile* profile) { BrowsingInstance* instance = browsing_instance_map_[profile]; diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h index fdbff8a..7e56fc8 100755 --- a/chrome/browser/extensions/extension_process_manager.h +++ b/chrome/browser/extensions/extension_process_manager.h @@ -8,12 +8,14 @@ #include "base/ref_counted.h" #include <map> +#include <string> class Browser; class BrowsingInstance; class Extension; class ExtensionView; class GURL; +class ListValue; class Profile; class SiteInstance; @@ -41,6 +43,12 @@ class ExtensionProcessManager { // Returns the SiteInstance that the given URL belongs to in this profile. SiteInstance* GetSiteInstanceForURL(const GURL& url, Profile* profile); + + // Sends the event to each renderer process within the current profile that + // contain at least one extension renderer. + void DispatchEventToRenderers(Profile *profile, + const std::string& event_name, + const ListValue& data); private: // Returns our BrowsingInstance for the given profile. Lazily created and // cached. diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc index 811bc97..86fcf49 100644 --- a/chrome/browser/extensions/extension_tabs_module.cc +++ b/chrome/browser/extensions/extension_tabs_module.cc @@ -17,6 +17,14 @@ static DictionaryValue* CreateTabValue(TabStripModel* tab_strip_model, static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id, int* tab_index); +int ExtensionTabUtil::GetTabId(const TabContents* tab_contents) { + return tab_contents->controller()->session_id().id(); +} + +int ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) { + return tab_contents->controller()->window_id().id(); +} + bool GetTabsForWindowFunction::RunImpl() { if (!args_->IsType(Value::TYPE_NULL)) return false; @@ -198,9 +206,9 @@ static DictionaryValue* CreateTabValue(TabStripModel* tab_strip, DCHECK(controller); // TODO(aa): Is this a valid assumption? DictionaryValue* result = new DictionaryValue(); - result->SetInteger(L"id", controller->session_id().id()); + result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents)); result->SetInteger(L"index", tab_index); - result->SetInteger(L"windowId", controller->window_id().id()); + 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()); diff --git a/chrome/browser/extensions/extension_tabs_module.h b/chrome/browser/extensions/extension_tabs_module.h index c358529..3aa4520 100644 --- a/chrome/browser/extensions/extension_tabs_module.h +++ b/chrome/browser/extensions/extension_tabs_module.h @@ -7,6 +7,14 @@ #include "chrome/browser/extensions/extension_function.h" +class TabContents; + +class ExtensionTabUtil { + public: + static int GetTabId(const TabContents* tab_contents); + static int GetWindowIdOfTab(const TabContents* tab_contents); +}; + class GetTabsForWindowFunction : public SyncExtensionFunction { virtual bool RunImpl(); }; diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 942d23c..ecc69a1 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -14,6 +14,7 @@ #include "base/values.h" #include "net/base/file_stream.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/extensions/extension_view.h" @@ -85,6 +86,9 @@ ExtensionsService::~ExtensionsService() { } bool ExtensionsService::Init() { + // Start up the extension event routers. + ExtensionBrowserEventRouter::GetInstance()->Init(); + #if defined(OS_WIN) // TODO(port): ExtensionsServiceBackend::CheckForExternalUpdates depends on // the Windows registry. |