diff options
author | erikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-01 03:57:10 +0000 |
---|---|---|
committer | erikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-01 03:57:10 +0000 |
commit | ac7b5aff9ae65cdb387c557f49958ac1e388181c (patch) | |
tree | af017ea80734d7750913960d10e29372370743bc /chrome | |
parent | 3bc67d82dd6310c46b0c1e9c4d9c2af50481f4e7 (diff) | |
download | chromium_src-ac7b5aff9ae65cdb387c557f49958ac1e388181c.zip chromium_src-ac7b5aff9ae65cdb387c557f49958ac1e388181c.tar.gz chromium_src-ac7b5aff9ae65cdb387c557f49958ac1e388181c.tar.bz2 |
Implement page action popups.
A random side effect of this change is that it changes page action hover from bubble to tool tip.
BUG=24645
TEST=ExtensionApiTest.PageActionPopup
Review URL: http://codereview.chromium.org/347016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30677 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser_list.h | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/location_bar_view_mac.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/location_bar_view_mac.mm | 14 | ||||
-rw-r--r-- | chrome/browser/extensions/page_action_apitest.cc | 79 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.cc | 14 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.h | 3 | ||||
-rw-r--r-- | chrome/browser/location_bar.h | 10 | ||||
-rw-r--r-- | chrome/browser/views/browser_bubble_win.cc | 7 | ||||
-rw-r--r-- | chrome/browser/views/location_bar_view.cc | 102 | ||||
-rw-r--r-- | chrome/browser/views/location_bar_view.h | 9 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 4 |
11 files changed, 239 insertions, 8 deletions
diff --git a/chrome/browser/browser_list.h b/chrome/browser/browser_list.h index 45a0246..bc136aa 100644 --- a/chrome/browser/browser_list.h +++ b/chrome/browser/browser_list.h @@ -52,10 +52,12 @@ class BrowserList { // a browser does not become active (perhaps the user launches Chrome, then // clicks on another app before the first browser window appears) then this // returns NULL. + // WARNING #2: this will always be NULL in unit tests run on the bots. static Browser* GetLastActive(); // Identical in behavior to GetLastActive(), except that the most recently // open browser owned by |profile| is returned. If none exist, returns NULL. + // WARNING: see warnings in GetLastActive(). static Browser* GetLastActiveWithProfile(Profile *profile); // Find an existing browser window with the provided type. Searches in the diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h index fb08b3f..b9ff05a 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.h +++ b/chrome/browser/cocoa/location_bar_view_mac.h @@ -56,6 +56,9 @@ class LocationBarViewMac : public AutocompleteEditController, // Overriden from LocationBarTesting: virtual int PageActionCount(); virtual int PageActionVisibleCount(); + virtual ExtensionAction* GetPageAction(size_t index); + virtual ExtensionAction* GetVisiblePageAction(size_t index); + virtual void TestPageActionPressed(size_t index); // Updates the location bar. Resets the bar's permanent text and // security style, and if |should_restore_state| is true, restores diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm index 2e935cc..f74d951 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.mm +++ b/chrome/browser/cocoa/location_bar_view_mac.mm @@ -295,6 +295,20 @@ int LocationBarViewMac::PageActionVisibleCount() { return -1; } +ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) { + NOTIMPLEMENTED(); + return NULL; +} + +ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) { + NOTIMPLEMENTED(); + return NULL; +} + +void LocationBarViewMac::TestPageActionPressed(size_t index) { + NOTIMPLEMENTED(); +} + NSImage* LocationBarViewMac::GetTabButtonImage() { if (!tab_button_image_) { SkBitmap* skiaBitmap = ResourceBundle::GetSharedInstance(). diff --git a/chrome/browser/extensions/page_action_apitest.cc b/chrome/browser/extensions/page_action_apitest.cc index a0d6074..b145816 100644 --- a/chrome/browser/extensions/page_action_apitest.cc +++ b/chrome/browser/extensions/page_action_apitest.cc @@ -62,7 +62,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PageAction) { EXPECT_FALSE(action->GetIcon(tab_id).isNull()); } - // Tests old-style pageActions API that is deprecated but we don't want to // break. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OldPageActions) { @@ -92,3 +91,81 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OldPageActions) { } } +class PageActionPopupTest : public ExtensionApiTest { +public: + bool RunExtensionTest(const char* extension_name) { + last_action_ = NULL; + last_visibility_ = false; + waiting_ = false; + + return ExtensionApiTest::RunExtensionTest(extension_name); + }; + + void Observe(NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: { + last_action_ = Source<ExtensionAction>(source).ptr(); + TabContents* contents = Details<TabContents>(details).ptr(); + int tab_id = ExtensionTabUtil::GetTabId(contents); + last_visibility_ = last_action_->GetIsVisible(tab_id); + if (waiting_) + MessageLoopForUI::current()->Quit(); + break; + } + default: + ExtensionBrowserTest::Observe(type, source, details); + break; + } + } + + void WaitForPopupVisibilityChange() { + // Wait for EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED to come in. + if (!last_action_) { + waiting_ = true; + ui_test_utils::RunMessageLoop(); + waiting_ = false; + } + } + + protected: + bool waiting_; + ExtensionAction* last_action_; + bool last_visibility_; +}; + +// TODO(port) +#if defined(OS_WIN) +// Tests popups in page actions. +IN_PROC_BROWSER_TEST_F(PageActionPopupTest, Show) { + NotificationRegistrar registrar; + registrar.Add(this, + NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, + NotificationService::AllSources()); + + ASSERT_TRUE(RunExtensionTest("page_action_popup")) << message_; + + ExtensionsService* service = browser()->profile()->GetExtensionsService(); + ASSERT_EQ(1u, service->extensions()->size()); + Extension* extension = service->extensions()->at(0); + ASSERT_TRUE(extension); + + // Wait for The page action to actually become visible. + if (!last_visibility_) + last_action_ = NULL; + WaitForPopupVisibilityChange(); + ASSERT_TRUE(last_visibility_); + + LocationBarTesting* location_bar = + browser()->window()->GetLocationBar()->GetLocationBarForTesting(); + ASSERT_EQ(1, location_bar->PageActionVisibleCount()); + ExtensionAction* action = location_bar->GetVisiblePageAction(0); + ASSERT_TRUE(action == last_action_); + + { + ResultCatcher catcher; + location_bar->TestPageActionPressed(0); + ASSERT_TRUE(catcher.GetNextResult()); + } +} +#endif diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index 8ee260f..2c1f4ec 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -465,6 +465,20 @@ int LocationBarViewGtk::PageActionVisibleCount() { return count; } +ExtensionAction* LocationBarViewGtk::GetPageAction(size_t index) { + NOTIMPLEMENTED(); + return NULL; +} + +ExtensionAction* LocationBarViewGtk::GetVisiblePageAction(size_t index) { + NOTIMPLEMENTED(); + return NULL; +} + +void LocationBarViewGtk::TestPageActionPressed(size_t index) { + NOTIMPLEMENTED(); +} + void LocationBarViewGtk::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index be37d47..051979e8 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -91,6 +91,9 @@ class LocationBarViewGtk : public AutocompleteEditController, // Implement the LocationBarTesting interface. virtual int PageActionCount() { return page_action_views_.size(); } virtual int PageActionVisibleCount(); + virtual ExtensionAction* GetPageAction(size_t index); + virtual ExtensionAction* GetVisiblePageAction(size_t index); + virtual void TestPageActionPressed(size_t index); // Implement the NotificationObserver interface. virtual void Observe(NotificationType type, diff --git a/chrome/browser/location_bar.h b/chrome/browser/location_bar.h index 6cf544d..71dba9c 100644 --- a/chrome/browser/location_bar.h +++ b/chrome/browser/location_bar.h @@ -17,6 +17,7 @@ #include "webkit/glue/window_open_disposition.h" class AutocompleteEditView; +class ExtensionAction; class LocationBarTesting; class TabContents; @@ -77,6 +78,15 @@ class LocationBarTesting { // Returns the number of visible page actions in the Omnibox. virtual int PageActionVisibleCount() = 0; + + // Returns the ExtensionAction at |index|. + virtual ExtensionAction* GetPageAction(size_t index) = 0; + + // Returns the visible ExtensionAction at |index|. + virtual ExtensionAction* GetVisiblePageAction(size_t index) = 0; + + // Simulates a left mouse pressed on the visible page action at |index|. + virtual void TestPageActionPressed(size_t index) = 0; }; #endif // CHROME_BROWSER_LOCATION_BAR_H_ diff --git a/chrome/browser/views/browser_bubble_win.cc b/chrome/browser/views/browser_bubble_win.cc index 3a5bca1..4c085ee 100644 --- a/chrome/browser/views/browser_bubble_win.cc +++ b/chrome/browser/views/browser_bubble_win.cc @@ -46,8 +46,13 @@ public: void OnActivate(UINT action, BOOL minimized, HWND window) { BrowserBubble::Delegate* delegate = bubble_->delegate(); - if (!delegate) + if (!delegate) { + if (action == WA_INACTIVE && !closed_) { + bubble_->DetachFromBrowser(); + delete bubble_; + } return; + } if (action == WA_INACTIVE && !closed_) { delegate->BubbleLostFocus(bubble_); diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index 2d32c52..edbe5f2 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -24,6 +24,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/view_ids.h" +#include "chrome/browser/views/extensions/extension_popup.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -695,6 +696,14 @@ void LocationBarView::RefreshPageActionViews() { if (!service) return; + std::map<ExtensionAction*, bool> old_visibility; + for (size_t i = 0; i < page_action_views_.size(); i++) { + old_visibility[page_action_views_[i]->image_view()->page_action()] = + page_action_views_[i]->IsVisible(); + } + + // Remember the previous visibility of the page actions so that we can + // notify when this changes. for (size_t i = 0; i < service->extensions()->size(); ++i) { if (service->extensions()->at(i)->page_action()) page_actions.push_back(service->extensions()->at(i)->page_action()); @@ -721,8 +730,20 @@ void LocationBarView::RefreshPageActionViews() { if (!page_action_views_.empty() && contents) { GURL url = GURL(WideToUTF8(model_->GetText())); - for (size_t i = 0; i < page_action_views_.size(); i++) + for (size_t i = 0; i < page_action_views_.size(); i++) { page_action_views_[i]->UpdateVisibility(contents, url); + + // Check if the visibility of the action changed and notify if it did. + ExtensionAction* action = + page_action_views_[i]->image_view()->page_action(); + if (old_visibility.find(action) == old_visibility.end() || + old_visibility[action] != page_action_views_[i]->IsVisible()) { + NotificationService::current()->Notify( + NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, + Source<ExtensionAction>(action), + Details<TabContents>(contents)); + } + } } } @@ -1268,6 +1289,36 @@ LocationBarView::PageActionImageView::~PageActionImageView() { tracker_->StopTrackingImageLoad(); } +void LocationBarView::PageActionImageView::ExecuteAction(int button) { + if (page_action_->has_popup()) { + gfx::Point origin; + View::ConvertPointToScreen(this, &origin); + gfx::Rect rect = bounds(); + rect.set_x(origin.x()); + rect.set_y(origin.y()); + + // In tests, GetLastActive could return NULL, so we need to have + // a fallback. + // TODO(erikkay): Find a better way to get the Browser that this + // button is in. + Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); + if (!browser) + browser = BrowserList::FindBrowserWithProfile(profile_); + ExtensionPopup::Show(page_action_->popup_url(), browser, rect); + } else { + ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( + profile_, page_action_->extension_id(), page_action_->id(), + current_tab_id_, current_url_.spec(), button); + } +} + +void LocationBarView::PageActionImageView::OnMouseMoved( + const views::MouseEvent& event) { + // PageActionImageView uses normal tooltips rather than the info bubble, + // so just do nothing here rather than letting LocationBarImageView start + // its hover timer. +} + bool LocationBarView::PageActionImageView::OnMousePressed( const views::MouseEvent& event) { int button = -1; @@ -1277,10 +1328,8 @@ bool LocationBarView::PageActionImageView::OnMousePressed( button = 2; else if (event.IsRightMouseButton()) button = 3; - // Our PageAction icon was clicked on, notify proper authorities. - ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( - profile_, page_action_->extension_id(), page_action_->id(), - current_tab_id_, current_url_.spec(), button); + + ExecuteAction(button); return true; } @@ -1324,6 +1373,7 @@ void LocationBarView::PageActionImageView::UpdateVisibility( if (visible) { // Set the tooltip. tooltip_ = page_action_->GetTitle(current_tab_id_); + SetTooltipText(ASCIIToWide(tooltip_)); // Set the image. // It can come from three places. In descending order of priority: @@ -1413,3 +1463,45 @@ int LocationBarView::PageActionVisibleCount() { } return result; } + +ExtensionAction* LocationBarView::GetPageAction(size_t index) { + if (index < page_action_views_.size()) + return page_action_views_[index]->image_view()->page_action(); + + NOTREACHED(); + return NULL; +} + +ExtensionAction* LocationBarView::GetVisiblePageAction(size_t index) { + if (index >= 0) { + size_t current = 0; + for (size_t i = 0; i < page_action_views_.size(); ++i) { + if (page_action_views_[i]->IsVisible()) { + if (current == index) + return page_action_views_[i]->image_view()->page_action(); + + ++current; + } + } + } + + NOTREACHED(); + return NULL; +} + +void LocationBarView::TestPageActionPressed(size_t index) { + if (index >= 0) { + size_t current = 0; + for (size_t i = 0; i < page_action_views_.size(); ++i) { + if (page_action_views_[i]->IsVisible()) { + if (current == index) { + const int button = 1; // Left mouse button. + page_action_views_[i]->image_view()->ExecuteAction(button); + return; + } + ++current; + } + } + } + NOTREACHED(); +} diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h index 1bae7e7..8bac242 100644 --- a/chrome/browser/views/location_bar_view.h +++ b/chrome/browser/views/location_bar_view.h @@ -158,6 +158,9 @@ class LocationBarView : public LocationBar, // Overridden from LocationBarTesting: virtual int PageActionCount() { return page_action_views_.size(); } virtual int PageActionVisibleCount(); + virtual ExtensionAction* GetPageAction(size_t index); + virtual ExtensionAction* GetVisiblePageAction(size_t index); + virtual void TestPageActionPressed(size_t index); static const int kVertMargin; @@ -357,7 +360,8 @@ class LocationBarView : public LocationBar, int current_tab_id() { return current_tab_id_; } - // Overridden from view for the mouse hovering. + // Overridden from view. + virtual void OnMouseMoved(const views::MouseEvent& event); virtual bool OnMousePressed(const views::MouseEvent& event); // Overridden from LocationBarImageView. @@ -371,6 +375,9 @@ class LocationBarView : public LocationBar, // is the current page URL. void UpdateVisibility(TabContents* contents, const GURL& url); + // Either notify listners or show a popup depending on the page action. + void ExecuteAction(int button); + private: // The location bar view that owns us. LocationBarView* owner_; diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index de00154..643cca1 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -707,6 +707,10 @@ class NotificationType { // ExtensionAction* that changed. The details are an ExtensionActionState*. EXTENSION_BROWSER_ACTION_UPDATED, + // Sent when a page action's visibility has changed. The source is the + // ExtensionAction* that changed. The details are a TabContents*. + EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, + // Sent by an extension to notify the browser about the results of a unit // test. EXTENSION_TEST_PASSED, |