summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-01 03:57:10 +0000
committererikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-01 03:57:10 +0000
commitac7b5aff9ae65cdb387c557f49958ac1e388181c (patch)
treeaf017ea80734d7750913960d10e29372370743bc /chrome
parent3bc67d82dd6310c46b0c1e9c4d9c2af50481f4e7 (diff)
downloadchromium_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.h2
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.h3
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.mm14
-rw-r--r--chrome/browser/extensions/page_action_apitest.cc79
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc14
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h3
-rw-r--r--chrome/browser/location_bar.h10
-rw-r--r--chrome/browser/views/browser_bubble_win.cc7
-rw-r--r--chrome/browser/views/location_bar_view.cc102
-rw-r--r--chrome/browser/views/location_bar_view.h9
-rw-r--r--chrome/common/notification_type.h4
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,