diff options
author | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 20:21:58 +0000 |
---|---|---|
committer | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 20:21:58 +0000 |
commit | 4577622518be7c7ddd4f3b45016d4fa68d253802 (patch) | |
tree | e09db89fdb34063d7dcb6ffc013821792ab3f38e /chrome | |
parent | 631d1ab9de83c531ca43b8134226eb247a4ee3aa (diff) | |
download | chromium_src-4577622518be7c7ddd4f3b45016d4fa68d253802.zip chromium_src-4577622518be7c7ddd4f3b45016d4fa68d253802.tar.gz chromium_src-4577622518be7c7ddd4f3b45016d4fa68d253802.tar.bz2 |
Retrying this patch. This was already reviewed by mpcomplete and the
only change is a fix for the UI test that broke and a small change to
event_bindings.cc (reviewed in-person).
ExtensionFunctionDispatcher now notifies ExtensionProcessManager of
renderviews created, which in turn notifies the renderer of page
actions that it knows about.
Remove generic event "page-action-executed" in favor of page action
specific event (sent as extension_id/page_action_id).
In the bindings, we now setup events for each page action we know about
so we can register for specific events, and not receive broadcast events
from all page actions. To setup these events I added a
GetCurrentPageActions() to extension_process_bindings.cc and a helper
function GetCurrentExtensionId().
And, finally, I simplified the page action background page by removing
the check to see if we are already subscribed to the feed (since we now
support multiple feed readers, it doesn't make sense anymore to always
check Google Reader). This check might make a comeback later in a
different form.
TBR=mpcomplete
BUG=13936
TEST=The RSS sample extension should work as before.
Review URL: http://codereview.chromium.org/149683
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20782 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
20 files changed, 212 insertions, 107 deletions
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc index 3bd807a..c7a5b33 100644 --- a/chrome/browser/extensions/extension_browser_event_router.cc +++ b/chrome/browser/extensions/extension_browser_event_router.cc @@ -329,6 +329,7 @@ void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents, void ExtensionBrowserEventRouter::TabStripEmpty() { } void ExtensionBrowserEventRouter::PageActionExecuted(Profile* profile, + std::string extension_id, std::string page_action_id, int tab_id, std::string url) { @@ -346,5 +347,6 @@ void ExtensionBrowserEventRouter::PageActionExecuted(Profile* profile, std::string json_args; JSONWriter::Write(&args, false, &json_args); - DispatchEvent(profile, events::kOnPageActionExecuted, json_args); + std::string event_name = extension_id + std::string("/") + page_action_id; + DispatchEvent(profile, event_name.c_str(), json_args); } diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h index 0cfd075..d2f7613 100644 --- a/chrome/browser/extensions/extension_browser_event_router.h +++ b/chrome/browser/extensions/extension_browser_event_router.h @@ -50,6 +50,7 @@ class ExtensionBrowserEventRouter : public TabStripModelObserver, // PageActions. void PageActionExecuted(Profile* profile, + std::string extension_id, std::string page_action_id, int tab_id, std::string url); diff --git a/chrome/browser/extensions/extension_event_names.cc b/chrome/browser/extensions/extension_event_names.cc index f4fd6e7..214d37b 100644 --- a/chrome/browser/extensions/extension_event_names.cc +++ b/chrome/browser/extensions/extension_event_names.cc @@ -6,7 +6,6 @@ namespace extension_event_names { -const char kOnPageActionExecuted[] = "page-action-executed"; const char kOnTabAttached[] = "tab-attached"; const char kOnTabCreated[] = "tab-created"; const char kOnTabDetached[] = "tab-detached"; diff --git a/chrome/browser/extensions/extension_event_names.h b/chrome/browser/extensions/extension_event_names.h index 9b9e3f2..3e3673a 100644 --- a/chrome/browser/extensions/extension_event_names.h +++ b/chrome/browser/extensions/extension_event_names.h @@ -9,7 +9,6 @@ namespace extension_event_names { -extern const char kOnPageActionExecuted[]; extern const char kOnTabAttached[]; extern const char kOnTabCreated[]; extern const char kOnTabDetached[]; diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 8238595..e486f89 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -13,6 +13,7 @@ #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_page_actions_module.h" #include "chrome/browser/extensions/extension_page_actions_module_constants.h" +#include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extension_tabs_module_constants.h" #include "chrome/browser/profile.h" @@ -188,6 +189,11 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( // Ensure the message service is initialized. ExtensionMessageService::GetInstance(profile()->GetRequestContext())->Init(); + + // Notify the ExtensionProcessManager that the view was created. + ExtensionProcessManager* epm = profile()->GetExtensionProcessManager(); + epm->RegisterExtensionProcess(extension_id(), + render_view_host->process()->pid()); } ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index 4c2047b..3018ea8 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -9,9 +9,11 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/site_instance.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" +#include "chrome/common/render_messages.h" static void CreateBackgroundHosts( ExtensionProcessManager* manager, const ExtensionList* extensions) { @@ -33,6 +35,10 @@ ExtensionProcessManager::ExtensionProcessManager(Profile* profile) NotificationService::AllSources()); registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED, Source<Profile>(profile)); + registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED, + NotificationService::AllSources()); } ExtensionProcessManager::~ExtensionProcessManager() { @@ -78,6 +84,39 @@ ExtensionHost* ExtensionProcessManager::CreateBackgroundHost( return host; } +void ExtensionProcessManager::RegisterExtensionProcess( + std::string extension_id, int process_id) { + ProcessIDMap::const_iterator it = process_ids_.find(extension_id); + if (it != process_ids_.end() && (*it).second == process_id) + return; + + process_ids_[extension_id] = process_id; + + ExtensionsService* extension_service = + browsing_instance_->profile()->GetExtensionsService(); + + std::vector<std::string> page_action_ids; + Extension* extension = extension_service->GetExtensionById(extension_id); + for (PageActionMap::const_iterator i = extension->page_actions().begin(); + i != extension->page_actions().end(); ++i) { + page_action_ids.push_back(i->first); + } + + RenderProcessHost* rph = RenderProcessHost::FromID(process_id); + rph->Send(new ViewMsg_Extension_UpdatePageActions(extension_id, + page_action_ids)); +} + +void ExtensionProcessManager::UnregisterExtensionProcess(int process_id) { + ProcessIDMap::iterator it = process_ids_.begin(); + while (it != process_ids_.end()) { + if (it->second == process_id) + process_ids_.erase(it++); + else + ++it; + } +} + SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) { return browsing_instance_->GetSiteInstanceForURL(url); } @@ -122,6 +161,13 @@ void ExtensionProcessManager::Observe(NotificationType type, break; } + case NotificationType::RENDERER_PROCESS_TERMINATED: + case NotificationType::RENDERER_PROCESS_CLOSED: { + RenderProcessHost* host = Source<RenderProcessHost>(source).ptr(); + UnregisterExtensionProcess(host->pid()); + break; + } + default: NOTREACHED(); } diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h index 58f6639..e3d6b76 100644 --- a/chrome/browser/extensions/extension_process_manager.h +++ b/chrome/browser/extensions/extension_process_manager.h @@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_PROCESS_MANAGER_H_ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_PROCESS_MANAGER_H_ +#include <map> #include <set> +#include <string> #include "base/ref_counted.h" #include "chrome/common/notification_registrar.h" @@ -43,6 +45,13 @@ class ExtensionProcessManager : public NotificationObserver { // Returns the SiteInstance that the given URL belongs to. SiteInstance* GetSiteInstanceForURL(const GURL& url); + // Register an extension process by |extension_id| and specifying which + // |process_id| it belongs to. + void RegisterExtensionProcess(std::string extension_id, int process_id); + + // Unregister an extension process with specified |process_id|. + void UnregisterExtensionProcess(int process_id); + // NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, @@ -69,6 +78,10 @@ class ExtensionProcessManager : public NotificationObserver { // controls process grouping. scoped_refptr<BrowsingInstance> browsing_instance_; + // 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_; + DISALLOW_COPY_AND_ASSIGN(ExtensionProcessManager); }; diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc index 6d7bc8c..6945446 100644 --- a/chrome/browser/extensions/extension_uitest.cc +++ b/chrome/browser/extensions/extension_uitest.cc @@ -86,7 +86,7 @@ class ExtensionUITest : public ParentTestType { } private: - DISALLOW_EVIL_CONSTRUCTORS(ExtensionUITest); + DISALLOW_COPY_AND_ASSIGN(ExtensionUITest); }; // For tests that only need to check for a single postMessage @@ -331,9 +331,6 @@ const char* BrowserEventAutomationProxy::event_names_[] = { "tab-detached", "tab-removed", - // Page action events. - "page-action-executed", - // Bookmark events. "bookmark-added", "bookmark-removed", @@ -445,6 +442,10 @@ class BrowserEventExtensionTest // ExternalTabMessageLoop is ported. #if defined(OS_WIN) TEST_F(BrowserEventExtensionTest, RunTest) { + // This test loads an HTML file that tries to add listeners to a bunch of + // chrome.* events and upon adding a listener it posts the name of the event + // to the automation layer, which we'll count to make sure the events work. + // // The extension for this test does not specify a "key" property in its // manifest file. Therefore, the extension system will automatically assign // it an Id. To make this test consistent and non-flaky, the genetated Id @@ -456,6 +457,10 @@ TEST_F(BrowserEventExtensionTest, RunTest) { BrowserEventAutomationProxy* proxy = static_cast<BrowserEventAutomationProxy*>(automation()); + // If this assert hits and the actual size is 0 then you need to look at: + // src\chrome\test\data\extensions\uitest\event_sink\test.html and see if + // all the events we are attaching to are valid. Also compare the list against + // the event_names_ string array above. EXPECT_EQ(arraysize(BrowserEventAutomationProxy::event_names_), proxy->event_count_.size()); for (std::map<std::string, int>::iterator i = proxy->event_count_.begin(); diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index eb6d629..d92b5b4 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -1277,7 +1277,8 @@ bool LocationBarView::PageActionImageView::OnMousePressed( const views::MouseEvent& event) { // Our PageAction icon was clicked on, notify proper authorities. ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( - profile_, page_action_->id(), current_tab_id_, current_url_.spec()); + profile_, page_action_->extension_id(), page_action_->id(), + current_tab_id_, current_url_.spec()); return true; } diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 5410091..e28eb51 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -562,6 +562,12 @@ IPC_BEGIN_MESSAGES(View) IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetFunctionNames, std::vector<std::string>) + // Tell the renderer process all known page action ids for a particular + // extension. + IPC_MESSAGE_CONTROL2(ViewMsg_Extension_UpdatePageActions, + std::string /* extension_id */, + std::vector<std::string> /* page_action_ids */) + // Changes the text direction of a selected input field. // * direction (int) // Represents the new text direction. diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index eab00fc..bb8df28 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -118,9 +118,13 @@ RenderThreadBase* EventBindings::GetRenderThread() { return render_thread ? render_thread : RenderThread::current(); } -static void HandleContextDestroyed(ContextList::iterator context_iter) { +static void HandleContextDestroyed(ContextList::iterator context_iter, + bool callUnload) { // Notify the bindings that they're going away. - CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", 0, NULL); + if (callUnload) { + CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", 0, + NULL); + } // Remove all pending requests for this context. PendingRequestMap& pending_requests = GetPendingRequestMap(); @@ -139,7 +143,7 @@ static void HandleContextDestroyed(ContextList::iterator context_iter) { it != GetContexts().end(); ) { ContextList::iterator current = it++; if ((*current)->parent_context == (*context_iter)->context) - HandleContextDestroyed(current); + HandleContextDestroyed(current, callUnload); } // Remove it from our registered contexts. @@ -155,7 +159,7 @@ static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, for (ContextList::iterator it = GetContexts().begin(); it != GetContexts().end(); ++it) { if ((*it)->context == context) { - HandleContextDestroyed(it); + HandleContextDestroyed(it, false); return; } } @@ -211,7 +215,7 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) { ContextList::iterator context_iter = bindings_utils::FindContext(context); DCHECK(context_iter != GetContexts().end()); - ::HandleContextDestroyed(context_iter); + ::HandleContextDestroyed(context_iter, true); } // static diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index e68fb82..fd70dcf 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -25,6 +25,9 @@ using bindings_utils::ExtensionBase; namespace { +// A map of extension ID to vector of page action ids. +typedef std::map< std::string, std::vector<std::string> > PageActionIdMap; + const char kExtensionName[] = "chrome/ExtensionProcessBindings"; const char* kExtensionDeps[] = { BaseJsV8Extension::kName, @@ -35,12 +38,17 @@ const char* kExtensionDeps[] = { struct SingletonData { std::set<std::string> function_names_; + PageActionIdMap page_action_ids_; }; static std::set<std::string>* GetFunctionNameSet() { return &Singleton<SingletonData>()->function_names_; } +static PageActionIdMap* GetPageActionMap() { + return &Singleton<SingletonData>()->page_action_ids_; +} + class ExtensionImpl : public ExtensionBase { public: ExtensionImpl() : ExtensionBase( @@ -62,6 +70,8 @@ class ExtensionImpl : public ExtensionBase { return v8::FunctionTemplate::New(GetViews); } else if (name->Equals(v8::String::New("GetNextRequestId"))) { return v8::FunctionTemplate::New(GetNextRequestId); + } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) { + return v8::FunctionTemplate::New(GetCurrentPageActions); } else if (names->find(*v8::String::AsciiValue(name)) != names->end()) { return v8::FunctionTemplate::New(StartRequest, name); } @@ -70,11 +80,15 @@ class ExtensionImpl : public ExtensionBase { } private: - static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { + static std::string ExtensionIdFromCurrentContext() { RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); DCHECK(renderview); GURL url = renderview->webview()->GetMainFrame()->GetURL(); - std::string extension_id = url.host(); + return url.host(); + } + + static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { + std::string extension_id = ExtensionIdFromCurrentContext(); ContextList contexts = bindings_utils::GetContextsForExtension(extension_id); @@ -97,7 +111,32 @@ class ExtensionImpl : public ExtensionBase { static int next_request_id = 0; return v8::Integer::New(next_request_id++); } - + + static v8::Handle<v8::Value> GetCurrentPageActions( + const v8::Arguments& args) { + std::string extension_id = ExtensionIdFromCurrentContext(); + PageActionIdMap* page_action_map = + GetPageActionMap(); + PageActionIdMap::const_iterator it = + page_action_map->find(extension_id); + + std::vector<std::string> page_actions; + size_t size = 0; + if (it != page_action_map->end()) { + page_actions = it->second; + size = page_actions.size(); + } + + v8::Local<v8::Array> page_action_vector = v8::Array::New(size); + for (size_t i = 0; i < size; ++i) { + std::string page_action_id = page_actions[i]; + page_action_vector->Set(v8::Integer::New(i), + v8::String::New(page_action_id.c_str())); + } + + return page_action_vector; + } + // Starts an API request to the browser, with an optional callback. The // callback will be dispatched to EventBindings::HandleResponse. static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) { @@ -159,3 +198,16 @@ void ExtensionProcessBindings::HandleResponse(int request_id, bool success, GetPendingRequestMap().erase(request_id); } + +// static +void ExtensionProcessBindings::SetPageActions( + const std::string& extension_id, + const std::vector<std::string>& page_actions) { + PageActionIdMap& page_action_map = *GetPageActionMap(); + if (!page_actions.empty()) { + page_action_map[extension_id] = page_actions; + } else { + if (page_action_map.find(extension_id) != page_action_map.end()) + page_action_map.erase(extension_id); + } +} diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h index 9e2c814..1ce6b47 100644 --- a/chrome/renderer/extensions/extension_process_bindings.h +++ b/chrome/renderer/extensions/extension_process_bindings.h @@ -7,6 +7,7 @@ #ifndef CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_ #define CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_ +#include <map> #include <string> #include <vector> @@ -21,6 +22,10 @@ class ExtensionProcessBindings { static void HandleResponse(int request_id, bool success, const std::string& response, const std::string& error); + + // Sets the page action ids for a particular extension. + static void SetPageActions(const std::string& extension_id, + const std::vector<std::string>& page_actions); }; #endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 16b4d45..3debfac 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -214,6 +214,12 @@ void RenderThread::OnSetExtensionFunctionNames( ExtensionProcessBindings::SetFunctionNames(names); } +void RenderThread::OnPageActionsUpdated( + const std::string& extension_id, + const std::vector<std::string>& page_actions) { + ExtensionProcessBindings::SetPageActions(extension_id, page_actions); +} + void RenderThread::OnControlMessageReceived(const IPC::Message& msg) { // App cache messages are handled by a delegate. if (app_cache_dispatcher_->OnMessageReceived(msg)) @@ -242,6 +248,8 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) { OnSetExtensionFunctionNames) IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache) + IPC_MESSAGE_HANDLER(ViewMsg_Extension_UpdatePageActions, + OnPageActionsUpdated) IPC_END_MESSAGE_MAP() } diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 733887e..5ced914 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -70,7 +70,7 @@ class RenderThread : public RenderThreadBase, // be accessed when running on the render thread itself static RenderThread* current(); - // Overridded from RenderThreadBase. + // Overridden from RenderThreadBase. virtual bool Send(IPC::Message* msg) { return ChildThread::Send(msg); } @@ -114,7 +114,7 @@ class RenderThread : public RenderThreadBase, private: virtual void OnControlMessageReceived(const IPC::Message& msg); - // Called by the thread base class + // Called by the thread base class. virtual void Init(); virtual void CleanUp(); @@ -124,6 +124,8 @@ class RenderThread : public RenderThreadBase, void OnUpdateUserScripts(base::SharedMemoryHandle table); void OnSetExtensionFunctionNames(const std::vector<std::string>& names); + void OnPageActionsUpdated(const std::string& extension_id, + const std::vector<std::string>& page_actions); void OnSetNextPageID(int32 next_page_id); void OnCreateNewView(gfx::NativeViewId parent_hwnd, ModalDialogEvent modal_dialog_event, diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd index eb128c7..a48534c 100644 --- 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. aa1 --> +without changes to the corresponding grd file. Zorglub2 --> <grit latest_public_release="0" current_release="1"> <outputs> <output filename="grit/renderer_resources.h" type="rc_header"> diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index 1c8fc9c4..e0dba27 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -30,6 +30,7 @@ var chrome = chrome || {}; native function GetTabLanguage(); native function EnablePageAction(); native function DisablePageAction(); + native function GetCurrentPageActions(); native function GetBookmarks(); native function GetBookmarkChildren(); native function GetBookmarkTree(); @@ -397,9 +398,16 @@ var chrome = chrome || {}; } ]; - // Sends ({pageActionId, tabId, tabUrl}). - chrome.pageActions.onExecute = - new chrome.Event("page-action-executed"); + // Page action events send (pageActionId, {tabId, tabUrl}). + function setupPageActionEvents(extensionId) { + var pageActions = GetCurrentPageActions(); + var eventName = ""; + for (var i = 0; i < pageActions.length; ++i) { + eventName = extensionId + "/" + pageActions[i]; + // Setup events for each extension_id/page_action_id string we find. + chrome.pageActions[pageActions[i]] = new chrome.Event(eventName); + } + } //---------------------------------------------------------------------------- // Bookmarks @@ -548,6 +556,8 @@ var chrome = chrome || {}; // TODO(mpcomplete): self.onConnect is deprecated. Remove it at 1.0. // http://code.google.com/p/chromium/issues/detail?id=16356 chrome.self.onConnect = new chrome.Event("channel-connect:" + extensionId); + + setupPageActionEvents(extensionId); }); chrome.self.getViews = function() { diff --git a/chrome/test/data/extensions/samples/subscribe_page_action/background.html b/chrome/test/data/extensions/samples/subscribe_page_action/background.html index 94761ff..4d14440 100644 --- a/chrome/test/data/extensions/samples/subscribe_page_action/background.html +++ b/chrome/test/data/extensions/samples/subscribe_page_action/background.html @@ -4,53 +4,14 @@ // The Page Action ID. var pageActionId = "RssPageAction"; - // The icons to use. These correspond to the icons listed in the manifest. + // The icon to use. This corresponds to the icon listed in the manifest. var subscribeId = 0; - var alreadySubscribedId = 1; - // The window this Page Action is associated with. - var windowId = -1; - - // The TabId this Page Action is associated with. - var tabId = -1; - - // The URL of the page that contains the feed. - var pageUrl = ""; - - // The feed URL found on the page. - var feedUrl = ""; - - // The URL to use to check if user is subscribed already. - var subscribedUrl = "http://www.google.com/reader/api/0/subscribed?s=feed%2F"; - - // The XMLHttpRequest object that checks if you are already subscribed. - var req; - - // The status of whether you have already subscribed to this feed or not. - var alreadySubscribed = false; - - function EnableIcon(subscribed) { - alreadySubscribed = subscribed; - if (!alreadySubscribed) { - chrome.pageActions.enableForTab( - pageActionId, {tabId: tabId, - url: pageUrl, - title: "Click to subscribe...", - iconId: subscribeId}); - } else { - chrome.pageActions.enableForTab( - pageActionId, {tabId: tabId, - url: pageUrl, - title: "You are already subscribed to this feed", - iconId: alreadySubscribedId}); - } - } + // A dictionary keyed off of tabId that keeps track of data per tab (for + // example what feedUrl was detected in the tab). + var feedData = {}; chrome.self.onConnect.addListener(function(port) { - windowId = port.tab.windowId; - tabId = port.tab.id; - pageUrl = port.tab.url; - // This will get called from the content script using PostMessage. // |feedUrls| is a list of URL feeds found on the page. We only need 1 to // enable the PageAction icon in the Omnibox. @@ -59,49 +20,39 @@ // Let Chrome know that the PageAction needs to be enabled for this tabId // and for the url of this page. if (feedUrl) { - EnableIcon(false); // Not subscribed (as far as we know, might change). - - // But also check the server to see if we have already subscribed so - // that we can update the status. - feedUrl = encodeURIComponent(feedUrl); - req = new XMLHttpRequest(); - req.onload = handleResponse; - req.open("GET", subscribedUrl + feedUrl, false); - req.send(null); + feedData[port.tab.id] = {pageUrl: port.tab.url, + feedUrl: feedUrl}; + + chrome.pageActions.enableForTab( + pageActionId, {tabId: port.tab.id, + url: port.tab.url, + title: "Click to subscribe...", + iconId: subscribeId}); } }); }); - function handleResponse() { - if (req.responseText == "true") - EnableIcon(true); // true == Already suscribed. - } - // Chrome will call into us when the user clicks on the icon in the OmniBox. - chrome.pageActions.onExecute.addListener(function(reply) { + chrome.pageActions["RssPageAction"].addListener(function(reply) { chrome.windows.getCurrent(function(window) { chrome.tabs.get(reply.data.tabId, function(tab) { - if (!alreadySubscribed && window.focused) { - // We need to know if we are the active window, because the tab may - // have moved to another window and we don't want to execute this - // action multiple times. - if (reply.pageActionId == pageActionId && - reply.data.tabUrl == pageUrl) { - // Create a new tab showing the subscription page with the right - // feed URL. - chrome.tabs.create({url: "subscribe.html?" + feedUrl, - windowId: windowId}); - } else { - console.log("Ignoring execute event."); - console.log("PageActionId: " + reply.pageActionId + " == " + - pageActionId); - console.log("TabUrl : " + reply.data.tabUrl + " == " + - pageUrl); - } + // We need to know if we are the active window, because the tab may + // have moved to another window and we don't want to execute this + // action multiple times. + if (window.focused) { + // Create a new tab showing the subscription page with the right + // feed URL. + chrome.tabs.create({url: "subscribe.html?" + + feedData[reply.data.tabId].feedUrl, + windowId: window.windowId}); } }); }); }); + + chrome.tabs.onRemoved.addListener(function(reply) { + feedData[reply.tabId] = null; + }); </script> </head> </html> diff --git a/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json b/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json index 5807816..7adaf8f 100644 --- a/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json +++ b/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json @@ -17,8 +17,7 @@ "id": "RssPageAction", "name": "Subscribe to this feed", "icons": [ - "feed-icon-16x16.png", - "feed-icon-16x16-subscribed.png" + "feed-icon-16x16.png" ] } ] diff --git a/chrome/test/data/extensions/uitest/event_sink/test.html b/chrome/test/data/extensions/uitest/event_sink/test.html index 2520d48..5462243 100644 --- a/chrome/test/data/extensions/uitest/event_sink/test.html +++ b/chrome/test/data/extensions/uitest/event_sink/test.html @@ -1,4 +1,5 @@ -HOLA!!! +HOLA!!! If you dont see the message DONE, then there is an error in the script. +<br> <script type="text/javascript"> // This extension registers for all tab and window events, and whenever one @@ -47,11 +48,6 @@ HOLA!!! portToAutomation.postMessage(chrome.tabs.onRemoved.eventName_); }); - // Page action events. - chrome.pageActions.onExecute.addListener(function(info) { - portToAutomation.postMessage(chrome.pageActions.onExecute.eventName_); - }); - // Bookmark events. chrome.bookmarks.onAdded.addListener(function(info) { portToAutomation.postMessage(chrome.bookmarks.onAdded.eventName_); |