summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 00:10:52 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 00:10:52 +0000
commit56ce6e5e9c393626dc3da68e9703423fffa273df (patch)
tree838bc7600dbcd7b37ff6180c9ed256856b960ead /chrome
parent530a94a66cc9a68075bce7c625cb6e1d480e22a8 (diff)
downloadchromium_src-56ce6e5e9c393626dc3da68e9703423fffa273df.zip
chromium_src-56ce6e5e9c393626dc3da68e9703423fffa273df.tar.gz
chromium_src-56ce6e5e9c393626dc3da68e9703423fffa273df.tar.bz2
Move page actions over to ExtensionAction2 and get rid of
extension_action.*. Final bit of refactor will be to rename ExtensionAction2 to ExtensionAction will be the next CL. BUG=24472,25844 Review URL: http://codereview.chromium.org/332021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30133 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_file_util.cc18
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.cc36
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.h8
-rw-r--r--chrome/browser/extensions/extensions_service.cc13
-rw-r--r--chrome/browser/extensions/extensions_service.h4
-rw-r--r--chrome/browser/extensions/page_action_apitest.cc17
-rw-r--r--chrome/browser/gtk/browser_actions_toolbar_gtk.cc10
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc128
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h16
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc62
-rw-r--r--chrome/browser/tab_contents/tab_contents.h35
-rw-r--r--chrome/browser/views/browser_actions_container.cc13
-rw-r--r--chrome/browser/views/location_bar_view.cc146
-rw-r--r--chrome/browser/views/location_bar_view.h17
-rwxr-xr-xchrome/chrome.gyp2
-rw-r--r--chrome/common/extensions/extension.cc107
-rw-r--r--chrome/common/extensions/extension.h6
-rwxr-xr-xchrome/common/extensions/extension_action2.cc131
-rwxr-xr-xchrome/common/extensions/extension_action2.h73
-rw-r--r--chrome/common/extensions/extension_action2_unittest.cc60
-rw-r--r--chrome/common/extensions/extension_unittest.cc102
-rw-r--r--chrome/test/data/extensions/samples/test_page_action/background.html23
-rwxr-xr-xchrome/test/data/extensions/samples/test_page_action/icon1.pngbin0 -> 2809 bytes
-rwxr-xr-xchrome/test/data/extensions/samples/test_page_action/icon2.pngbin0 -> 2809 bytes
-rw-r--r--chrome/test/data/extensions/samples/test_page_action/manifest.json3
-rw-r--r--chrome/test/data/extensions/samples/test_page_action/print_16x16.pngbin647 -> 0 bytes
26 files changed, 484 insertions, 546 deletions
diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc
index 60d4981..a71f2a2 100644
--- a/chrome/browser/extensions/extension_file_util.cc
+++ b/chrome/browser/extensions/extension_file_util.cc
@@ -228,10 +228,12 @@ bool ValidateExtension(Extension* extension, std::string* error) {
}
// Validate icon location for page actions.
- const ExtensionAction* page_action = extension->page_action();
+ ExtensionAction2* page_action = extension->page_action();
if (page_action) {
- const std::vector<std::string>& icon_paths = page_action->icon_paths();
- for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
+ std::vector<std::string> icon_paths(*page_action->icon_paths());
+ if (!page_action->default_icon_path().empty())
+ icon_paths.push_back(page_action->default_icon_path());
+ for (std::vector<std::string>::iterator iter = icon_paths.begin();
iter != icon_paths.end(); ++iter) {
if (extension->GetResource(*iter).GetFilePath().empty()) {
*error = StringPrintf("Could not load icon '%s' for page action.",
@@ -242,14 +244,14 @@ bool ValidateExtension(Extension* extension, std::string* error) {
}
// Validate icon location for browser actions.
+ // Note: browser actions don't use the icon_paths().
ExtensionAction2* browser_action = extension->browser_action();
if (browser_action) {
- std::vector<std::string>* icon_paths = browser_action->icon_paths();
- for (std::vector<std::string>::iterator iter = icon_paths->begin();
- iter != icon_paths->end(); ++iter) {
- if (extension->GetResource(*iter).GetFilePath().empty()) {
+ std::string default_icon_path = browser_action->default_icon_path();
+ if (!default_icon_path.empty()) {
+ if (extension->GetResource(default_icon_path).GetFilePath().empty()) {
*error = StringPrintf("Could not load icon '%s' for browser action.",
- iter->c_str());
+ default_icon_path.c_str());
return false;
}
}
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
index b39ca32..b41386d 100644
--- a/chrome/browser/extensions/extension_page_actions_module.cc
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -56,15 +56,14 @@ bool PageActionFunction::SetPageActionEnabled(bool enable) {
}
}
- const ExtensionAction* page_action =
- dispatcher()->GetExtension()->page_action();
+ ExtensionAction2* page_action = dispatcher()->GetExtension()->page_action();
if (!page_action) {
error_ = kNoPageActionError;
return false;
}
if (icon_id < 0 ||
- static_cast<size_t>(icon_id) >= page_action->icon_paths().size()) {
+ static_cast<size_t>(icon_id) >= page_action->icon_paths()->size()) {
error_ = (icon_id == 0) ? kNoIconSpecified : kIconIndexOutOfBounds;
return false;
}
@@ -86,7 +85,9 @@ bool PageActionFunction::SetPageActionEnabled(bool enable) {
}
// Set visibility and broadcast notifications that the UI should be updated.
- contents->SetPageActionEnabled(page_action, enable, title, icon_id);
+ page_action->SetIsVisible(tab_id, enable);
+ page_action->SetTitle(tab_id, title);
+ page_action->SetIconIndex(tab_id, icon_id);
contents->PageActionStateChanged();
return true;
@@ -108,17 +109,16 @@ bool PageActionFunction::InitCommon(int tab_id) {
return false;
}
- state_ = contents_->GetOrCreatePageActionState(page_action_);
return true;
}
-bool PageActionFunction::SetHidden(bool hidden) {
+bool PageActionFunction::SetVisible(bool visible) {
int tab_id;
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
if (!InitCommon(tab_id))
return false;
- state_->set_hidden(hidden);
+ page_action_->SetIsVisible(tab_id, visible);
contents_->PageActionStateChanged();
return true;
}
@@ -132,11 +132,11 @@ bool DisablePageActionFunction::RunImpl() {
}
bool PageActionShowFunction::RunImpl() {
- return SetHidden(false);
+ return SetVisible(true);
}
bool PageActionHideFunction::RunImpl() {
- return SetHidden(true);
+ return SetVisible(false);
}
bool PageActionSetIconFunction::RunImpl() {
@@ -158,15 +158,15 @@ bool PageActionSetIconFunction::RunImpl() {
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
EXTENSION_FUNCTION_VALIDATE(
IPC::ReadParam(&bitmap_pickle, &iter, bitmap.get()));
- state_->set_icon(bitmap.release());
+ page_action_->SetIcon(tab_id, *bitmap);
} else if (args->GetInteger(L"iconIndex", &icon_index)) {
- if (icon_index < 0 ||
- static_cast<size_t>(icon_index) >= page_action_->icon_paths().size()) {
+ if (icon_index < 0 || static_cast<size_t>(icon_index) >=
+ page_action_->icon_paths()->size()) {
error_ = kIconIndexOutOfBounds;
return false;
}
- state_->set_icon(NULL);
- state_->set_icon_index(icon_index);
+ page_action_->SetIcon(tab_id, SkBitmap());
+ page_action_->SetIconIndex(tab_id, icon_index);
} else {
EXTENSION_FUNCTION_VALIDATE(false);
}
@@ -187,7 +187,7 @@ bool PageActionSetTitleFunction::RunImpl() {
std::string title;
EXTENSION_FUNCTION_VALIDATE(args->GetString(L"title", &title));
- state_->set_title(title);
+ page_action_->SetTitle(tab_id, title);
contents_->PageActionStateChanged();
return true;
}
@@ -213,7 +213,7 @@ bool PageActionSetBadgeBackgroundColorFunction::RunImpl() {
SkColor color = SkColorSetARGB(color_array[3], color_array[0], color_array[1],
color_array[2]);
- state_->set_badge_background_color(color);
+ page_action_->SetBadgeBackgroundColor(tab_id, color);
contents_->PageActionStateChanged();
return true;
}
@@ -239,7 +239,7 @@ bool PageActionSetBadgeTextColorFunction::RunImpl() {
SkColor color = SkColorSetARGB(color_array[3], color_array[0], color_array[1],
color_array[2]);
- state_->set_badge_text_color(color);
+ page_action_->SetBadgeTextColor(tab_id, color);
contents_->PageActionStateChanged();
return true;
}
@@ -258,7 +258,7 @@ bool PageActionSetBadgeTextFunction::RunImpl() {
std::string text;
EXTENSION_FUNCTION_VALIDATE(args->GetString(L"text", &text));
- state_->set_badge_text(text);
+ page_action_->SetBadgeText(tab_id, text);
contents_->PageActionStateChanged();
return true;
}
diff --git a/chrome/browser/extensions/extension_page_actions_module.h b/chrome/browser/extensions/extension_page_actions_module.h
index f3ac6f0..f991d71 100644
--- a/chrome/browser/extensions/extension_page_actions_module.h
+++ b/chrome/browser/extensions/extension_page_actions_module.h
@@ -8,19 +8,17 @@
#include "chrome/browser/extensions/extension_function.h"
class TabContents;
-class ExtensionAction;
-class ExtensionActionState;
+class ExtensionAction2;
class PageActionFunction : public SyncExtensionFunction {
protected:
bool SetPageActionEnabled(bool enable);
bool InitCommon(int tab_id);
- bool SetHidden(bool hidden);
+ bool SetVisible(bool visible);
- ExtensionAction* page_action_;
+ ExtensionAction2* page_action_;
TabContents* contents_;
- ExtensionActionState* state_;
};
class EnablePageActionFunction : public PageActionFunction {
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 354d7d2..ef6d9cd 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -140,19 +140,6 @@ void ExtensionsService::Init() {
GarbageCollectExtensions();
}
-std::vector<ExtensionAction*> ExtensionsService::GetPageActions() const {
- std::vector<ExtensionAction*> result;
-
- // TODO(finnur): Sort the icons in some meaningful way.
- for (ExtensionList::const_iterator iter = extensions_.begin();
- iter != extensions_.end(); ++iter) {
- if ((*iter)->page_action())
- result.push_back((*iter)->page_action());
- }
-
- return result;
-}
-
void ExtensionsService::InstallExtension(const FilePath& extension_path) {
CrxInstaller::Start(extension_path, install_directory_, Extension::INTERNAL,
"", // no expected id
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 0dad4cd..ecd670d 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -102,10 +102,6 @@ class ExtensionsService
return GetExtensionByIdInternal(id, true, false);
}
- // Retrieves a vector of all page actions, irrespective of which extension
- // they belong to.
- std::vector<ExtensionAction*> GetPageActions() const;
-
// Install the extension file at |extension_path|. Will install as an
// update if an older version is already installed.
// For fresh installs, this method also causes the extension to be
diff --git a/chrome/browser/extensions/page_action_apitest.cc b/chrome/browser/extensions/page_action_apitest.cc
index 207eccc..4a97d79 100644
--- a/chrome/browser/extensions/page_action_apitest.cc
+++ b/chrome/browser/extensions/page_action_apitest.cc
@@ -12,7 +12,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/browser_actions_container.h"
#include "chrome/browser/views/toolbar_view.h"
-#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/extensions/extension_action2.h"
#include "chrome/test/ui_test_utils.h"
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PageAction) {
@@ -33,11 +33,11 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PageAction) {
}
// Test that we received the changes.
- const ExtensionActionState* action_state =
- browser()->GetSelectedTabContents()->GetPageActionState(
- extension->page_action());
- ASSERT_TRUE(action_state);
- EXPECT_EQ("Modified", action_state->title());
+ int tab_id =
+ browser()->GetSelectedTabContents()->controller().session_id().id();
+ ExtensionAction2* action = extension->page_action();
+ ASSERT_TRUE(action);
+ EXPECT_EQ("Modified", action->GetTitle(tab_id));
{
// Simulate the page action being clicked.
@@ -57,7 +57,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PageAction) {
}
// Test that we received the changes.
- action_state = browser()->GetSelectedTabContents()->GetPageActionState(
- extension->page_action());
- EXPECT_TRUE(action_state->icon());
+ tab_id = browser()->GetSelectedTabContents()->controller().session_id().id();
+ EXPECT_FALSE(action->GetIcon(tab_id).isNull());
}
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
index b137203..583f8ce 100644
--- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
@@ -53,7 +53,7 @@ class BrowserActionButton : public NotificationObserver,
// The Browser Action API does not allow the default icon path to be
// changed at runtime, so we can load this now and cache it.
- std::string path = extension_->browser_action()->GetDefaultIconPath();
+ std::string path = extension_->browser_action()->default_icon_path();
if (!path.empty()) {
tracker_ = new ImageLoadingTracker(this, 1);
tracker_->PostLoadImageTask(extension_->GetResource(path),
@@ -103,7 +103,8 @@ class BrowserActionButton : public NotificationObserver,
// ImageLoadingTracker::Observer implementation.
void OnImageLoaded(SkBitmap* image, size_t index) {
- default_icon_ = gfx::GdkPixbufFromSkBitmap(image);
+ if (image)
+ default_icon_ = gfx::GdkPixbufFromSkBitmap(image);
UpdateState();
}
@@ -167,10 +168,7 @@ class BrowserActionButton : public NotificationObserver,
gfx::CanvasPaint canvas(event, false);
gfx::Rect bounding_rect(widget->allocation);
- ExtensionActionState::PaintBadge(&canvas, bounding_rect,
- action->GetBadgeText(tab_id),
- action->GetBadgeTextColor(tab_id),
- action->GetBadgeBackgroundColor(tab_id));
+ action->PaintBadge(&canvas, bounding_rect, tab_id);
return FALSE;
}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 38c24c0..198aa31 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -33,7 +33,6 @@
#include "chrome/common/page_transition_types.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/window_open_disposition.h"
namespace {
@@ -406,17 +405,15 @@ void LocationBarViewGtk::FocusSearch() {
}
void LocationBarViewGtk::UpdatePageActions() {
- std::vector<ExtensionAction*> page_actions;
- if (profile_->GetExtensionsService())
- page_actions = profile_->GetExtensionsService()->GetPageActions();
-
- // Page actions can be created without an icon, so make sure we count only
- // those that have been given an icon.
- for (size_t i = 0; i < page_actions.size();) {
- if (page_actions[i]->icon_paths().empty())
- page_actions.erase(page_actions.begin() + i);
- else
- ++i;
+ std::vector<ExtensionAction2*> page_actions;
+ ExtensionsService* service = profile_->GetExtensionsService();
+ if (!service)
+ return;
+
+ // Find all the page actions.
+ 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());
}
// Initialize on the first call, or re-inialize if more extensions have been
@@ -690,11 +687,10 @@ gboolean LocationBarViewGtk::OnSecurityIconPressed(
LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
LocationBarViewGtk* owner, Profile* profile,
- const ExtensionAction* page_action)
+ ExtensionAction2* page_action)
: owner_(owner),
profile_(profile),
page_action_(page_action),
- last_icon_skbitmap_(NULL),
last_icon_pixbuf_(NULL) {
event_box_.Own(gtk_event_box_new());
gtk_widget_set_size_request(event_box_.get(), kButtonSize, kButtonSize);
@@ -713,11 +709,14 @@ LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
page_action->extension_id());
DCHECK(extension);
- DCHECK(!page_action->icon_paths().empty());
- const std::vector<std::string>& icon_paths = page_action->icon_paths();
- pixbufs_.resize(icon_paths.size());
+ // Load all the icons declared in the manifest. This is the contents of the
+ // icons array, plus the default_icon property, if any.
+ std::vector<std::string> icon_paths(*page_action->icon_paths());
+ if (!page_action_->default_icon_path().empty())
+ icon_paths.push_back(page_action_->default_icon_path());
+
tracker_ = new ImageLoadingTracker(this, icon_paths.size());
- for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
+ for (std::vector<std::string>::iterator iter = icon_paths.begin();
iter != icon_paths.end(); ++iter) {
tracker_->PostLoadImageTask(
extension->GetResource(*iter),
@@ -731,9 +730,9 @@ LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() {
tracker_->StopTrackingImageLoad();
image_.Destroy();
event_box_.Destroy();
- for (size_t i = 0; i < pixbufs_.size(); ++i) {
- if (pixbufs_[i])
- g_object_unref(pixbufs_[i]);
+ for (PixbufMap::iterator iter = pixbufs_.begin(); iter != pixbufs_.end();
+ ++iter) {
+ g_object_unref(iter->second);
}
if (last_icon_pixbuf_)
g_object_unref(last_icon_pixbuf_);
@@ -746,35 +745,48 @@ void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility(
current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
current_url_ = url;
- const ExtensionActionState* state =
- contents->GetPageActionState(page_action_);
- bool visible = state && !state->hidden();
+ bool visible = page_action_->GetIsVisible(current_tab_id_);
if (visible) {
// Set the tooltip.
- if (state->title().empty())
- gtk_widget_set_tooltip_text(event_box_.get(),
- page_action_->title().c_str());
- else
- gtk_widget_set_tooltip_text(event_box_.get(), state->title().c_str());
+ gtk_widget_set_tooltip_text(event_box_.get(),
+ page_action_->GetTitle(current_tab_id_).c_str());
// Set the image.
- SkBitmap* icon = state->icon();
+ // It can come from three places. In descending order of priority:
+ // - The developer can set it dynamically by path or bitmap. It will be in
+ // page_action_->GetIcon().
+ // - The developer can set it dyanmically by index. It will be in
+ // page_action_->GetIconIndex().
+ // - It can be set in the manifest by path. It will be in page_action_->
+ // default_icon_path().
+
+ // First look for a dynamically set bitmap.
+ SkBitmap icon = page_action_->GetIcon(current_tab_id_);
GdkPixbuf* pixbuf = NULL;
- if (icon) {
- if (icon != last_icon_skbitmap_) {
+ if (!icon.isNull()) {
+ if (icon.pixelRef() != last_icon_skbitmap_.pixelRef()) {
if (last_icon_pixbuf_)
g_object_unref(last_icon_pixbuf_);
last_icon_skbitmap_ = icon;
- last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(icon);
+ last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&icon);
}
DCHECK(last_icon_pixbuf_);
pixbuf = last_icon_pixbuf_;
} else {
- int index = state->icon_index();
- // The image index (if not within bounds) will be set to the first image.
- if (index < 0 || index >= static_cast<int>(pixbufs_.size()))
- index = 0;
- pixbuf = pixbufs_[index];
+ // Otherwise look for a dynamically set index, or fall back to the
+ // default path.
+ int icon_index = page_action_->GetIconIndex(current_tab_id_);
+ std::string icon_path;
+ if (icon_index >= 0)
+ icon_path = page_action_->icon_paths()->at(icon_index);
+ else
+ icon_path = page_action_->default_icon_path();
+
+ if (!icon_path.empty()) {
+ PixbufMap::iterator iter = pixbufs_.find(icon_path);
+ if (iter != pixbufs_.end())
+ pixbuf = iter->second;
+ }
}
// The pixbuf might not be loaded yet.
@@ -793,10 +805,27 @@ void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility(
void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded(SkBitmap* image,
size_t index) {
- DCHECK(index < pixbufs_.size());
- if (index == pixbufs_.size() - 1)
- tracker_ = NULL; // The tracker object will delete itself when we return.
- pixbufs_[index] = gfx::GdkPixbufFromSkBitmap(image);
+ // We loaded icons()->size() icons, plus one extra if the page action had
+ // a default icon.
+ size_t total_icons = page_action_->icon_paths()->size();
+ if (!page_action_->default_icon_path().empty())
+ total_icons++;
+ DCHECK(index < total_icons);
+
+ // Map the index of the loaded image back to its name. If we ever get an
+ // index greater than the number of icons, it must be the default icon.
+ if (image) {
+ GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(image);
+ if (index < page_action_->icon_paths()->size())
+ pixbufs_[page_action_->icon_paths()->at(index)] = pixbuf;
+ else
+ pixbufs_[page_action_->default_icon_path()] = pixbuf;
+ }
+
+ // If we are done, release the tracker.
+ if (index == (total_icons - 1))
+ tracker_ = NULL;
+
owner_->UpdatePageActions();
}
@@ -821,16 +850,17 @@ gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent(
TabContents* contents = view->owner_->browser_->GetSelectedTabContents();
if (!contents)
return FALSE;
- const ExtensionActionState* state =
- contents->GetPageActionState(view->page_action_);
- if (!state || state->badge_text().empty())
+
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+ if (tab_id < 0)
+ return FALSE;
+
+ std::string badge_text = view->page_action_->GetBadgeText(tab_id);
+ if (badge_text.empty())
return FALSE;
gfx::CanvasPaint canvas(event, false);
gfx::Rect bounding_rect(widget->allocation);
- ExtensionActionState::PaintBadge(&canvas, bounding_rect,
- state->badge_text(),
- state->badge_text_color(),
- state->badge_background_color());
+ view->page_action_->PaintBadge(&canvas, bounding_rect, tab_id);
return FALSE;
}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index bedf724..3d38c4e 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -7,8 +7,8 @@
#include <gtk/gtk.h>
+#include <map>
#include <string>
-#include <vector>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
@@ -21,14 +21,15 @@
#include "chrome/common/notification_registrar.h"
#include "chrome/common/owned_widget_gtk.h"
#include "chrome/common/page_transition_types.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/window_open_disposition.h"
class AutocompleteEditViewGtk;
class BubblePositioner;
class Browser;
class CommandUpdater;
+class ExtensionAction2;
class GtkThemeProvider;
-class ExtensionAction;
class Profile;
class SkBitmap;
class TabContents;
@@ -105,7 +106,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
public:
PageActionViewGtk(
LocationBarViewGtk* owner, Profile* profile,
- const ExtensionAction* page_action);
+ ExtensionAction2* page_action);
virtual ~PageActionViewGtk();
GtkWidget* widget() { return event_box_.get(); }
@@ -133,15 +134,16 @@ class LocationBarViewGtk : public AutocompleteEditController,
// The PageAction that this view represents. The PageAction is not owned by
// us, it resides in the extension of this particular profile.
- const ExtensionAction* page_action_;
+ ExtensionAction2* page_action_;
- // The icons representing different states for the page action.
- std::vector<GdkPixbuf*> pixbufs_;
+ // A cache of all the different icon paths associated with this page action.
+ typedef std::map<std::string, GdkPixbuf*> PixbufMap;
+ PixbufMap pixbufs_;
// A cache of the last dynamically generated bitmap and the pixbuf that
// corresponds to it. We keep track of both so we can free old pixbufs as
// their icons are replaced.
- SkBitmap* last_icon_skbitmap_;
+ SkBitmap last_icon_skbitmap_;
GdkPixbuf* last_icon_pixbuf_;
// The object that is waiting for the image loading to complete
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 3876053..6fdd6bb 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -55,7 +55,7 @@
#include "chrome/browser/search_engines/template_url_fetcher.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/extensions/extension_action2.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
@@ -605,36 +605,6 @@ void TabContents::SetIsCrashed(bool state) {
NotifyNavigationStateChanged(INVALIDATE_TAB);
}
-void TabContents::SetPageActionEnabled(const ExtensionAction* page_action,
- bool enable,
- const std::string& title,
- int icon_id) {
- DCHECK(page_action);
- ExtensionActionState* state = GetOrCreatePageActionState(page_action);
- state->set_hidden(!enable);
- state->set_title(title);
- state->set_icon_index(icon_id);
- state->set_icon(NULL);
-}
-
-const ExtensionActionState* TabContents::GetPageActionState(
- const ExtensionAction* page_action) {
- if (page_actions_.end() == page_actions_.find(page_action))
- return NULL;
-
- return page_actions_[page_action].get();
-}
-
-ExtensionActionState* TabContents::GetOrCreatePageActionState(
- const ExtensionAction* page_action) {
- if (page_actions_.end() == page_actions_.find(page_action)) {
- page_actions_[page_action].reset(
- new ExtensionActionState(page_action->title(), 0));
- }
-
- return page_actions_[page_action].get();
-}
-
void TabContents::PageActionStateChanged() {
NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);
}
@@ -1414,27 +1384,31 @@ void TabContents::DidNavigateMainFramePostCommit(
// Get the favicon, either from history or request it from the net.
fav_icon_helper_.FetchFavIcon(details.entry->url());
- // Disable all page actions, unless this is an in-page navigation.
+ // Clear all page and browser action state for this tab, unless this is an
+ // in-page navigation.
url_canon::Replacements<char> replacements;
replacements.ClearRef();
if (params.url.ReplaceComponents(replacements) !=
params.referrer.ReplaceComponents(replacements)) {
- if (!page_actions_.empty())
- page_actions_.clear();
-
ExtensionsService* service = profile()->GetExtensionsService();
if (service) {
for (size_t i = 0; i < service->extensions()->size(); ++i) {
- ExtensionAction2* action =
+ ExtensionAction2* browser_action =
service->extensions()->at(i)->browser_action();
- if (!action)
- continue;
-
- action->ClearAllValuesForTab(controller().session_id().id());
- NotificationService::current()->Notify(
- NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
- Source<ExtensionAction2>(action),
- NotificationService::NoDetails());
+ if (browser_action) {
+ browser_action->ClearAllValuesForTab(controller().session_id().id());
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
+ Source<ExtensionAction2>(browser_action),
+ NotificationService::NoDetails());
+ }
+
+ ExtensionAction2* page_action =
+ service->extensions()->at(i)->page_action();
+ if (page_action) {
+ page_action->ClearAllValuesForTab(controller().session_id().id());
+ PageActionStateChanged();
+ }
}
}
}
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 091bde2..b613627 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -30,7 +30,6 @@
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/page_navigator.h"
#include "chrome/browser/tab_contents/render_view_host_manager.h"
-#include "chrome/common/extensions/extension_action.h"
#include "chrome/common/gears_api.h"
#include "chrome/common/navigation_types.h"
#include "chrome/common/notification_registrar.h"
@@ -74,7 +73,6 @@ class DOMUI;
class DownloadItem;
class LoadNotificationDetails;
class OmniboxSearchHint;
-class PageAction;
class PasswordManager;
class PluginInstaller;
class Profile;
@@ -255,28 +253,7 @@ class TabContents : public PageNavigator,
bool is_crashed() const { return is_crashed_; }
void SetIsCrashed(bool state);
- // Adds/removes a page action to the list of page actions that are active in
- // this tab. The parameter |title| (if not empty) can be used to override the
- // page action title for this tab and |icon_id| specifies an icon index
- // (defined in the manifest) to use instead of the first icon (for this tab).
- void SetPageActionEnabled(const ExtensionAction* page_action, bool enable,
- const std::string& title, int icon_id);
-
- // Returns the page action state for this tab. The pair returns contains
- // the title (string) for the page action and the icon index to use (int).
- // If this function returns NULL it means the page action is not enabled for
- // this tab.
- const ExtensionActionState* GetPageActionState(
- const ExtensionAction* page_action);
-
- // Same as above, but creates an enable state if it doesn't exist. The return
- // value can be updated. The caller should call PageActionStateChanged when
- // done modifying the state.
- ExtensionActionState* GetOrCreatePageActionState(
- const ExtensionAction* page_action);
-
- // Call this after updating a ExtensionActionState object returned by
- // GetOrCreatePageActionState to notify clients about the changes.
+ // Call this after updating a page action to notify clients about the changes.
void PageActionStateChanged();
// Whether the tab is in the process of being destroyed.
@@ -1127,16 +1104,6 @@ class TabContents : public PageNavigator,
// information to build its presentation.
FindNotificationDetails last_search_result_;
- // Data for Page Actions -----------------------------------------------------
-
- // A map of page actions that this tab knows about (and a state object that
- // can be used to update the title, icon, visibilty, etc used for the page
- // action). This map is cleared every time the mainframe navigates and
- // populated by the PageAction extension API.
- typedef std::map< const ExtensionAction*, linked_ptr<ExtensionActionState> >
- PageActionStateMap;
- PageActionStateMap page_actions_;
-
// Data for misc internal state ----------------------------------------------
// See capturing_contents() above.
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc
index f3f02f0..6a91690 100644
--- a/chrome/browser/views/browser_actions_container.cc
+++ b/chrome/browser/views/browser_actions_container.cc
@@ -15,8 +15,6 @@
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "chrome/browser/views/toolbar_view.h"
-#include "chrome/common/extensions/extension_action.h"
-#include "chrome/common/extensions/extension_action2.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "grit/app_resources.h"
@@ -86,7 +84,7 @@ void BrowserActionButton::LoadImage() {
// Load the default image from the browser action asynchronously on the file
// thread. We'll get a call back into OnImageLoaded if the image loads
// successfully.
- std::string relative_path = browser_action()->GetDefaultIconPath();
+ std::string relative_path = browser_action()->default_icon_path();
if (relative_path.empty())
return;
@@ -98,7 +96,8 @@ void BrowserActionButton::LoadImage() {
}
void BrowserActionButton::OnImageLoaded(SkBitmap* image, size_t index) {
- SetIcon(*image);
+ if (image)
+ SetIcon(*image);
tracker_ = NULL; // The tracker object will delete itself when we return.
GetParent()->SchedulePaint();
}
@@ -211,11 +210,7 @@ void BrowserActionView::PaintChildren(gfx::Canvas* canvas) {
if (tab_id < 0)
return;
- ExtensionActionState::PaintBadge(
- canvas, gfx::Rect(width(), height()),
- action->GetBadgeText(tab_id),
- action->GetBadgeTextColor(tab_id),
- action->GetBadgeBackgroundColor(tab_id));
+ action->PaintBadge(canvas, gfx::Rect(width(), height()), tab_id);
}
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index 95d2915..cbe8dd6 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -108,13 +108,13 @@ void LocationBarView::PageActionWithBadgeView::Layout() {
void LocationBarView::PageActionWithBadgeView::PaintChildren(
gfx::Canvas* canvas) {
View::PaintChildren(canvas);
- const ExtensionActionState* state = image_view_->GetPageActionState();
- if (state) {
- ExtensionActionState::PaintBadge(canvas, gfx::Rect(width(), height()),
- state->badge_text(),
- state->badge_text_color(),
- state->badge_background_color());
- }
+
+ ExtensionAction2* action = image_view_->page_action();
+ int tab_id = image_view_->current_tab_id();
+ if (tab_id < 0)
+ return;
+
+ action->PaintBadge(canvas, gfx::Rect(width(), height()), tab_id);
}
void LocationBarView::PageActionWithBadgeView::UpdateVisibility(
@@ -684,17 +684,14 @@ void LocationBarView::DeletePageActionViews() {
}
void LocationBarView::RefreshPageActionViews() {
- std::vector<ExtensionAction*> page_actions;
- if (profile_->GetExtensionsService())
- page_actions = profile_->GetExtensionsService()->GetPageActions();
-
- // Page actions can be created without an icon, so make sure we count only
- // those that have been given an icon.
- for (size_t i = 0; i < page_actions.size();) {
- if (page_actions[i]->icon_paths().empty())
- page_actions.erase(page_actions.begin() + i);
- else
- ++i;
+ std::vector<ExtensionAction2*> page_actions;
+ ExtensionsService* service = profile_->GetExtensionsService();
+ if (!service)
+ return;
+
+ 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());
}
// On startup we sometimes haven't loaded any extensions. This makes sure
@@ -1228,48 +1225,30 @@ void LocationBarView::SecurityImageView::ShowInfoBubble() {
SECURITY_INFO_BUBBLE_TEXT));
}
-void LocationBarView::PageActionImageView::Paint(gfx::Canvas* canvas) {
- LocationBarImageView::Paint(canvas);
-
- TabContents* contents = owner_->delegate_->GetTabContents();
- if (!contents)
- return;
-
- const ExtensionActionState* state =
- contents->GetPageActionState(page_action_);
- if (state) {
- ExtensionActionState::PaintBadge(canvas, gfx::Rect(width(), height()),
- state->badge_text(),
- state->badge_text_color(),
- state->badge_background_color());
- }
-}
-
// PageActionImageView----------------------------------------------------------
LocationBarView::PageActionImageView::PageActionImageView(
LocationBarView* owner,
Profile* profile,
- const ExtensionAction* page_action,
+ ExtensionAction2* page_action,
const BubblePositioner* bubble_positioner)
: LocationBarImageView(bubble_positioner),
owner_(owner),
profile_(profile),
page_action_(page_action),
- current_tab_id_(-1),
- tooltip_(page_action_->title()) {
+ current_tab_id_(-1) {
Extension* extension = profile->GetExtensionsService()->GetExtensionById(
page_action->extension_id());
DCHECK(extension);
- // Load the images this view needs asynchronously on the file thread. We'll
- // get a call back into OnImageLoaded if the image loads successfully. If not,
- // the ImageView will have no image and will not appear in the Omnibox.
- DCHECK(!page_action->icon_paths().empty());
- const std::vector<std::string>& icon_paths = page_action->icon_paths();
- page_action_icons_.resize(icon_paths.size());
+ // Load all the icons declared in the manifest. This is the contents of the
+ // icons array, plus the default_icon property, if any.
+ std::vector<std::string> icon_paths(*page_action->icon_paths());
+ if (!page_action_->default_icon_path().empty())
+ icon_paths.push_back(page_action_->default_icon_path());
+
tracker_ = new ImageLoadingTracker(this, icon_paths.size());
- for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
+ for (std::vector<std::string>::iterator iter = icon_paths.begin();
iter != icon_paths.end(); ++iter) {
tracker_->PostLoadImageTask(
extension->GetResource(*iter),
@@ -1299,26 +1278,32 @@ bool LocationBarView::PageActionImageView::OnMousePressed(
return true;
}
-const ExtensionActionState*
- LocationBarView::PageActionImageView::GetPageActionState() {
- TabContents* contents = owner_->delegate_->GetTabContents();
- if (!contents)
- return NULL;
-
- return contents->GetPageActionState(page_action_);
-}
-
void LocationBarView::PageActionImageView::ShowInfoBubble() {
ShowInfoBubbleImpl(ASCIIToWide(tooltip_), GetColor(false, TEXT));
}
void LocationBarView::PageActionImageView::OnImageLoaded(SkBitmap* image,
size_t index) {
- DCHECK(index < page_action_icons_.size());
- if (index == page_action_icons_.size() - 1)
- tracker_ = NULL; // The tracker object will delete itself when we return.
- if (image)
- page_action_icons_[index] = *image;
+ // We loaded icons()->size() icons, plus one extra if the page action had
+ // a default icon.
+ int total_icons = page_action_->icon_paths()->size();
+ if (!page_action_->default_icon_path().empty())
+ total_icons++;
+ DCHECK(static_cast<int>(index) < total_icons);
+
+ // Map the index of the loaded image back to its name. If we ever get an
+ // index greater than the number of icons, it must be the default icon.
+ if (image) {
+ if (index < page_action_->icon_paths()->size())
+ page_action_icons_[page_action_->icon_paths()->at(index)] = *image;
+ else
+ page_action_icons_[page_action_->default_icon_path()] = *image;
+ }
+
+ // If we are done, release the tracker.
+ if (static_cast<int>(index) == (total_icons - 1))
+ tracker_ = NULL;
+
owner_->UpdatePageActions();
}
@@ -1329,26 +1314,39 @@ void LocationBarView::PageActionImageView::UpdateVisibility(
current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
current_url_ = url;
- const ExtensionActionState* state =
- contents->GetPageActionState(page_action_);
- bool visible = state && !state->hidden();
+ bool visible = page_action_->GetIsVisible(current_tab_id_);
if (visible) {
// Set the tooltip.
- if (state->title().empty())
- tooltip_ = page_action_->title();
- else
- tooltip_ = state->title();
+ tooltip_ = page_action_->GetTitle(current_tab_id_);
// Set the image.
- SkBitmap* icon = state->icon();
- if (!icon) {
- int index = state->icon_index();
- // The image index (if not within bounds) will be set to the first image.
- if (index < 0 || index >= static_cast<int>(page_action_icons_.size()))
- index = 0;
- icon = &page_action_icons_[index];
+ // It can come from three places. In descending order of priority:
+ // - The developer can set it dynamically by path or bitmap. It will be in
+ // page_action_->GetIcon().
+ // - The developer can set it dynamically by index. It will be in
+ // page_action_->GetIconIndex().
+ // - It can be set in the manifest by path. It will be in page_action_->
+ // default_icon_path().
+
+ // First look for a dynamically set bitmap.
+ SkBitmap icon = page_action_->GetIcon(current_tab_id_);
+ if (icon.isNull()) {
+ int icon_index = page_action_->GetIconIndex(current_tab_id_);
+ std::string icon_path;
+ if (icon_index >= 0)
+ icon_path = page_action_->icon_paths()->at(icon_index);
+ else
+ icon_path = page_action_->default_icon_path();
+
+ if (!icon_path.empty()) {
+ PageActionMap::iterator iter = page_action_icons_.find(icon_path);
+ if (iter != page_action_icons_.end())
+ icon = iter->second;
+ }
}
- ImageView::SetImage(icon);
+
+ if (!icon.isNull())
+ ImageView::SetImage(&icon);
}
SetVisible(visible);
}
diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h
index 5c40886..5accd9b 100644
--- a/chrome/browser/views/location_bar_view.h
+++ b/chrome/browser/views/location_bar_view.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_
#include <string>
+#include <map>
#include <vector>
#include "app/gfx/font.h"
@@ -29,8 +30,8 @@
class BubblePositioner;
class CommandUpdater;
+class ExtensionAction2;
class GURL;
-class PageAction;
class Profile;
/////////////////////////////////////////////////////////////////////////////
@@ -348,18 +349,19 @@ class LocationBarView : public LocationBar,
public:
PageActionImageView(LocationBarView* owner,
Profile* profile,
- const ExtensionAction* page_action,
+ ExtensionAction2* page_action,
const BubblePositioner* bubble_positioner);
virtual ~PageActionImageView();
- const ExtensionActionState* GetPageActionState();
+ ExtensionAction2* page_action() { return page_action_; }
+
+ int current_tab_id() { return current_tab_id_; }
// Overridden from view for the mouse hovering.
virtual bool OnMousePressed(const views::MouseEvent& event);
// Overridden from LocationBarImageView.
virtual void ShowInfoBubble();
- virtual void Paint(gfx::Canvas* canvas);
// Overridden from ImageLoadingTracker.
virtual void OnImageLoaded(SkBitmap* image, size_t index);
@@ -378,10 +380,11 @@ class LocationBarView : public LocationBar,
// The PageAction that this view represents. The PageAction is not owned by
// us, it resides in the extension of this particular profile.
- const ExtensionAction* page_action_;
+ ExtensionAction2* page_action_;
- // The icons representing different states for the page action.
- std::vector<SkBitmap> page_action_icons_;
+ // A cache of bitmaps the page actions might need to show, mapped by path.
+ typedef std::map<std::string, SkBitmap> PageActionMap;
+ PageActionMap page_action_icons_;
// The object that is waiting for the image loading to complete
// asynchronously.
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index ed9a1bc..71486f6 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -538,8 +538,6 @@
'common/extensions/extension_error_reporter.h',
'common/extensions/extension_error_utils.cc',
'common/extensions/extension_error_utils.h',
- 'common/extensions/extension_action.cc',
- 'common/extensions/extension_action.h',
'common/extensions/extension_action2.cc',
'common/extensions/extension_action2.h',
'common/extensions/extension_message_bundle.cc',
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 202a2dc..2fae2ab 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -297,99 +297,15 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
return true;
}
-// Helper method that loads a PageAction or BrowserAction object from a
-// dictionary in the page_actions list or browser_action key of the manifest.
-ExtensionAction* Extension::LoadExtensionActionHelper(
- const DictionaryValue* page_action, std::string* error,
- ExtensionAction::ExtensionActionType action_type) {
- scoped_ptr<ExtensionAction> result(new ExtensionAction());
- result->set_extension_id(id());
- result->set_type(action_type);
-
- // TODO(EXTENSIONS_DEPRECATED): icons list is obsolete.
- ListValue* icons = NULL;
- if (page_action->HasKey(keys::kPageActionIcons) &&
- page_action->GetList(keys::kPageActionIcons, &icons)) {
- for (ListValue::const_iterator iter = icons->begin();
- iter != icons->end(); ++iter) {
- std::string path;
- if (!(*iter)->GetAsString(&path) || path.empty()) {
- *error = errors::kInvalidPageActionIconPath;
- return NULL;
- }
-
- result->AddIconPath(path);
- }
- }
-
- // TODO(EXTENSIONS_DEPRECATED): Read the page action |id| (optional).
- std::string id;
- if (action_type == ExtensionAction::PAGE_ACTION)
- page_action->GetString(keys::kPageActionId, &id);
- result->set_id(id);
-
- std::string default_icon;
- // Read the page action |default_icon| (optional).
- if (page_action->HasKey(keys::kPageActionDefaultIcon)) {
- if (!page_action->GetString(keys::kPageActionDefaultIcon, &default_icon) ||
- default_icon.empty()) {
- *error = errors::kInvalidPageActionIconPath;
- return NULL;
- }
- // TODO(EXTENSIONS_DEPRECATED): one icon.
- result->AddIconPath(default_icon);
- }
-
- // Read the page action |default_title|.
- std::string title;
- if (!page_action->GetString(keys::kName, &title) &&
- !page_action->GetString(keys::kPageActionDefaultTitle, &title)) {
- *error = errors::kInvalidPageActionDefaultTitle;
- return NULL;
- }
- result->set_title(title);
-
- // Read the action's |popup| (optional).
- DictionaryValue* popup = NULL;
- std::string url_str;
- if (page_action->HasKey(keys::kPageActionPopup) &&
- !page_action->GetDictionary(keys::kPageActionPopup, &popup) &&
- !page_action->GetString(keys::kPageActionPopup, &url_str)) {
- *error = errors::kInvalidPageActionPopup;
- return NULL;
- }
- if (popup) {
- // TODO(EXTENSIONS_DEPRECATED): popup is a string only
- if (!popup->GetString(keys::kPageActionPopupPath, &url_str)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPageActionPopupPath, "<missing>");
- return NULL;
- }
- GURL url = GetResourceURL(url_str);
- if (!url.is_valid()) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPageActionPopupPath, url_str);
- return NULL;
- }
- result->set_popup_url(url);
- } else if (!url_str.empty()) {
- GURL url = GetResourceURL(url_str);
- if (!url.is_valid()) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPageActionPopupPath, url_str);
- return NULL;
- }
- result->set_popup_url(url);
- }
-
- return result.release();
-}
-
ExtensionAction2* Extension::LoadExtensionAction2Helper(
const DictionaryValue* extension_action, std::string* error) {
scoped_ptr<ExtensionAction2> result(new ExtensionAction2());
result->set_extension_id(id());
+ // Page actions are hidden by default, and browser actions ignore
+ // visibility.
+ result->SetIsVisible(ExtensionAction2::kDefaultTabId, false);
+
// TODO(EXTENSIONS_DEPRECATED): icons list is obsolete.
ListValue* icons = NULL;
if (extension_action->HasKey(keys::kPageActionIcons) &&
@@ -403,7 +319,6 @@ ExtensionAction2* Extension::LoadExtensionAction2Helper(
}
result->icon_paths()->push_back(path);
- result->SetDefaultIcon(path);
}
}
@@ -426,7 +341,7 @@ ExtensionAction2* Extension::LoadExtensionAction2Helper(
*error = errors::kInvalidPageActionIconPath;
return NULL;
}
- result->SetDefaultIcon(default_icon);
+ result->set_default_icon_path(default_icon);
}
// Read the page action |default_title|.
@@ -1031,8 +946,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
}
page_action_.reset(
- LoadExtensionActionHelper(page_action_value, error,
- ExtensionAction::PAGE_ACTION));
+ LoadExtensionAction2Helper(page_action_value, error));
if (!page_action_.get())
return false; // Failed to parse page action definition.
} else if (source.HasKey(keys::kPageAction)) {
@@ -1043,8 +957,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
}
page_action_.reset(
- LoadExtensionActionHelper(page_action_value, error,
- ExtensionAction::PAGE_ACTION));
+ LoadExtensionAction2Helper(page_action_value, error));
if (!page_action_.get())
return false; // Failed to parse page action definition.
}
@@ -1179,9 +1092,9 @@ std::set<FilePath> Extension::GetBrowserImages() {
// page action icons
if (page_action_.get()) {
- const std::vector<std::string>& icon_paths = page_action_->icon_paths();
- for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
- iter != icon_paths.end(); ++iter) {
+ std::vector<std::string>* icon_paths = page_action_->icon_paths();
+ for (std::vector<std::string>::iterator iter = icon_paths->begin();
+ iter != icon_paths->end(); ++iter) {
image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter)));
}
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 4a9fcd9..4677e2d 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -191,7 +191,7 @@ class Extension {
const std::string& public_key() const { return public_key_; }
const std::string& description() const { return description_; }
const UserScriptList& content_scripts() const { return content_scripts_; }
- ExtensionAction* page_action() const { return page_action_.get(); }
+ ExtensionAction2* page_action() const { return page_action_.get(); }
ExtensionAction2* browser_action() const { return browser_action_.get(); }
const std::vector<PrivacyBlacklistInfo>& privacy_blacklists() const {
return privacy_blacklists_;
@@ -281,7 +281,7 @@ class Extension {
// Helper method that loads a ExtensionAction object from a
// dictionary in the page_action or browser_action section of the manifest.
- ExtensionAction* LoadExtensionActionHelper(
+ ExtensionAction2* LoadExtensionActionHelper(
const DictionaryValue* contextual_action,
std::string* error,
ExtensionAction::ExtensionActionType action_type);
@@ -326,7 +326,7 @@ class Extension {
UserScriptList content_scripts_;
// The extension's page action, if any.
- scoped_ptr<ExtensionAction> page_action_;
+ scoped_ptr<ExtensionAction2> page_action_;
// The extension's browser action, if any.
scoped_ptr<ExtensionAction2> browser_action_;
diff --git a/chrome/common/extensions/extension_action2.cc b/chrome/common/extensions/extension_action2.cc
index 653de95..b36ef44 100755
--- a/chrome/common/extensions/extension_action2.cc
+++ b/chrome/common/extensions/extension_action2.cc
@@ -4,28 +4,129 @@
#include "chrome/common/extensions/extension_action2.h"
-#include "base/logging.h"
+#include "app/gfx/canvas.h"
+#include "app/resource_bundle.h"
+#include "base/gfx/rect.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "grit/app_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
const int ExtensionAction2::kDefaultTabId = -1;
-void ExtensionAction2::SetDefaultIcon(const std::string& path) {
- default_icon_path_ = path;
- icon_.erase(kDefaultTabId);
+void ExtensionAction2::ClearAllValuesForTab(int tab_id) {
+ title_.erase(tab_id);
+ icon_.erase(tab_id);
+ icon_index_.erase(tab_id);
+ badge_text_.erase(tab_id);
+ badge_text_color_.erase(tab_id);
+ badge_background_color_.erase(tab_id);
+ visible_.erase(tab_id);
}
-void ExtensionAction2::SetDefaultIcon(int icon_index) {
- if (static_cast<size_t>(icon_index) >= icon_paths_.size()) {
- NOTREACHED();
+void ExtensionAction2::PaintBadge(gfx::Canvas* canvas,
+ const gfx::Rect& bounds,
+ int tab_id) {
+ std::string text = GetBadgeText(tab_id);
+ if (text.empty())
return;
+
+ SkColor text_color = GetBadgeTextColor(tab_id);
+ SkColor background_color = GetBadgeBackgroundColor(tab_id);
+
+ if (SkColorGetA(text_color) == 0x00)
+ text_color = SK_ColorWHITE;
+
+ if (SkColorGetA(background_color) == 0x00)
+ background_color = SkColorSetARGB(255, 218, 0, 24); // default badge color
+
+ // Different platforms need slightly different constants to look good.
+#if defined(OS_LINUX)
+ const int kTextSize = 9;
+ const int kBottomMargin = 4;
+ const int kPadding = 2;
+ const int kBadgeHeight = 12;
+ const int kMaxTextWidth = 23;
+ // The minimum width for center-aligning the badge.
+ const int kCenterAlignThreshold = 20;
+#else
+ const int kTextSize = 8;
+ const int kBottomMargin = 5;
+ const int kPadding = 2;
+ const int kBadgeHeight = 11;
+ const int kMaxTextWidth = 23;
+ // The minimum width for center-aligning the badge.
+ const int kCenterAlignThreshold = 20;
+#endif
+
+ canvas->save();
+
+ SkTypeface* typeface = SkTypeface::CreateFromName("Arial", SkTypeface::kBold);
+ SkPaint text_paint;
+ text_paint.setAntiAlias(true);
+ text_paint.setColor(text_color);
+ text_paint.setFakeBoldText(true);
+ text_paint.setTextAlign(SkPaint::kLeft_Align);
+ text_paint.setTextSize(SkIntToScalar(kTextSize));
+ text_paint.setTypeface(typeface);
+
+ // Calculate text width. We clamp it to a max size.
+ SkScalar text_width = text_paint.measureText(text.c_str(), text.size());
+ text_width = SkIntToScalar(
+ std::min(kMaxTextWidth, SkScalarFloor(text_width)));
+
+ // Cacluate badge size. It is clamped to a min width just because it looks
+ // silly if it is too skinny.
+ int badge_width = SkScalarFloor(text_width) + kPadding * 2;
+ badge_width = std::max(kBadgeHeight, badge_width);
+
+ // Paint the badge background color in the right location. It is usually
+ // right-aligned, but it can also be center-aligned if it is large.
+ SkRect rect;
+ rect.fBottom = SkIntToScalar(bounds.bottom() - kBottomMargin);
+ rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight);
+ if (badge_width >= kCenterAlignThreshold) {
+ rect.fLeft = SkIntToScalar((bounds.right() - badge_width) / 2);
+ rect.fRight = rect.fLeft + SkIntToScalar(badge_width);
+ } else {
+ rect.fRight = SkIntToScalar(bounds.right());
+ rect.fLeft = rect.fRight - badge_width;
}
- SetDefaultIcon(icon_paths_[icon_index]);
-}
+ SkPaint rect_paint;
+ rect_paint.setStyle(SkPaint::kFill_Style);
+ rect_paint.setAntiAlias(true);
+ rect_paint.setColor(background_color);
+ canvas->drawRoundRect(rect, SkIntToScalar(2), SkIntToScalar(2), rect_paint);
-void ExtensionAction2::ClearAllValuesForTab(int tab_id) {
- title_.erase(tab_id);
- icon_.erase(tab_id);
- badge_text_.erase(tab_id);
- badge_background_color_.erase(tab_id);
- badge_text_color_.erase(tab_id);
+ // Overlay the gradient. It is stretchy, so we do this in three parts.
+ ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance();
+ SkBitmap* gradient_left = resource_bundle.GetBitmapNamed(
+ IDR_BROWSER_ACTION_BADGE_LEFT);
+ SkBitmap* gradient_right = resource_bundle.GetBitmapNamed(
+ IDR_BROWSER_ACTION_BADGE_RIGHT);
+ SkBitmap* gradient_center = resource_bundle.GetBitmapNamed(
+ IDR_BROWSER_ACTION_BADGE_CENTER);
+
+ canvas->drawBitmap(*gradient_left, rect.fLeft, rect.fTop);
+ canvas->TileImageInt(*gradient_center,
+ SkScalarFloor(rect.fLeft) + gradient_left->width(),
+ SkScalarFloor(rect.fTop),
+ SkScalarFloor(rect.width()) - gradient_left->width() -
+ gradient_right->width(),
+ SkScalarFloor(rect.height()));
+ canvas->drawBitmap(*gradient_right,
+ rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop);
+
+ // Finally, draw the text centered within the badge. We set a clip in case the
+ // text was too large.
+ rect.fLeft += kPadding;
+ rect.fRight -= kPadding;
+ canvas->clipRect(rect);
+ canvas->drawText(text.c_str(), text.size(),
+ rect.fLeft + (rect.width() - text_width) / 2,
+ rect.fTop + kTextSize + 1,
+ text_paint);
+ canvas->restore();
}
diff --git a/chrome/common/extensions/extension_action2.h b/chrome/common/extensions/extension_action2.h
index ae4cf34..53c62bc 100755
--- a/chrome/common/extensions/extension_action2.h
+++ b/chrome/common/extensions/extension_action2.h
@@ -10,11 +10,17 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "googleurl/src/gurl.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
+namespace gfx {
+class Canvas;
+class Rect;
+}
+
// ExtensionAction2 encapsulates the state of a browser or page action.
// Instances can have both global and per-tab state. If a property does not have
// a per-tab value, the global value is used instead.
@@ -37,6 +43,13 @@ class ExtensionAction2 {
void set_popup_url(const GURL& url) { popup_url_ = url; }
bool has_popup() const { return !popup_url_.is_empty(); }
+ // action id -- only used with legacy page actions API
+ std::string id() const { return id_; }
+ void set_id(const std::string& id) { id_ = id; }
+
+ // static icon paths from manifest -- only used with legacy page actions API.
+ std::vector<std::string>* icon_paths() { return &icon_paths_; }
+
// title
void SetTitle(int tab_id, const std::string& title) {
SetValue(&title_, tab_id, title);
@@ -50,20 +63,30 @@ class ExtensionAction2 {
// To get the default icon, first check for the bitmap. If it is null, check
// for the path.
- // icon bitmap
+ // Icon bitmap.
void SetIcon(int tab_id, const SkBitmap& bitmap) {
SetValue(&icon_, tab_id, bitmap);
- if (tab_id == kDefaultTabId)
- default_icon_path_.clear();
}
SkBitmap GetIcon(int tab_id) { return GetValue(&icon_, tab_id); }
- // icon path (relative to extension_id()'s root)
- // For legacy code, we also support setting the path as an index into
- // icon_paths().
- void SetDefaultIcon(const std::string& path);
- void SetDefaultIcon(int icon_index);
- std::string GetDefaultIconPath() {
+ // Icon index -- for use with icon_paths(), only used in page actions.
+ void SetIconIndex(int tab_id, int index) {
+ if (static_cast<size_t>(index) >= icon_paths_.size()) {
+ NOTREACHED();
+ return;
+ }
+ SetValue(&icon_index_, tab_id, index);
+ }
+ int GetIconIndex(int tab_id) {
+ return GetValue(&icon_index_, tab_id);
+ }
+
+ // Non-tab-specific icon path. This is used to support the default_icon key of
+ // page and browser actions.
+ void set_default_icon_path(const std::string& path) {
+ default_icon_path_ = path;
+ }
+ std::string default_icon_path() {
return default_icon_path_;
}
@@ -89,16 +112,19 @@ class ExtensionAction2 {
return GetValue(&badge_background_color_, tab_id);
}
+ // visibility
+ void SetIsVisible(int tab_id, bool value) {
+ SetValue(&visible_, tab_id, value);
+ }
+ bool GetIsVisible(int tab_id) {
+ return GetValue(&visible_, tab_id);
+ }
+
// Remove all tab-specific state.
void ClearAllValuesForTab(int tab_id);
- //---------------------------------------------------------------------------
- // Legacy support
-
- std::string id() const { return id_; }
- void set_id(const std::string& id) { id_ = id; }
-
- std::vector<std::string>* icon_paths() { return &icon_paths_; }
+ // If the specified tab has a badge, paint it into the provided bounds.
+ void PaintBadge(gfx::Canvas* canvas, const gfx::Rect& bounds, int tab_id);
private:
template <class T>
@@ -132,31 +158,30 @@ class ExtensionAction2 {
// kDefaultTabId), or tab-specific state (stored with the tab_id as the key).
std::map<int, std::string> title_;
std::map<int, SkBitmap> icon_;
+ std::map<int, int> icon_index_; // index into icon_paths_
std::map<int, std::string> badge_text_;
std::map<int, SkColor> badge_background_color_;
std::map<int, SkColor> badge_text_color_;
+ std::map<int, bool> visible_;
std::string default_icon_path_;
// If the action has a popup, it has a URL and a height.
GURL popup_url_;
- //---------------------------------------------------------------------------
- // Legacy support
-
// The id for the ExtensionAction2, for example: "RssPageAction". This is
// needed for compat with an older version of the page actions API.
std::string id_;
// A list of paths to icons this action might show. This is needed to support
- // the setIcon({iconIndex:...} method.
+ // the legacy setIcon({iconIndex:...} method of the page actions API.
std::vector<std::string> icon_paths_;
};
-template <>
-struct ExtensionAction2::ValueTraits<SkColor> {
- static SkColor CreateEmpty() {
- return 0x00000000;
+template<>
+struct ExtensionAction2::ValueTraits<int> {
+ static int CreateEmpty() {
+ return -1;
}
};
diff --git a/chrome/common/extensions/extension_action2_unittest.cc b/chrome/common/extensions/extension_action2_unittest.cc
index 7f1d78b..47a32d7 100644
--- a/chrome/common/extensions/extension_action2_unittest.cc
+++ b/chrome/common/extensions/extension_action2_unittest.cc
@@ -65,6 +65,35 @@ TEST(ExtensionAction2Test, TabSpecificState) {
ASSERT_TRUE(BitmapsAreEqual(icon1, action.GetIcon(1)));
ASSERT_TRUE(BitmapsAreEqual(icon2, action.GetIcon(100)));
+ // icon index
+ ASSERT_EQ(-1, action.GetIconIndex(1));
+ action.icon_paths()->push_back("foo.png");
+ action.icon_paths()->push_back("bar.png");
+ action.SetIconIndex(ExtensionAction2::kDefaultTabId, 1);
+ ASSERT_EQ(1, action.GetIconIndex(1));
+ ASSERT_EQ(1, action.GetIconIndex(100));
+ action.SetIconIndex(100, 0);
+ ASSERT_EQ(0, action.GetIconIndex(100));
+ ASSERT_EQ(1, action.GetIconIndex(1));
+ action.ClearAllValuesForTab(100);
+ ASSERT_EQ(1, action.GetIconIndex(100));
+ ASSERT_EQ(1, action.GetIconIndex(1));
+
+ // visibility
+ ASSERT_EQ(false, action.GetIsVisible(1));
+ action.SetIsVisible(ExtensionAction2::kDefaultTabId, true);
+ ASSERT_EQ(true, action.GetIsVisible(1));
+ ASSERT_EQ(true, action.GetIsVisible(100));
+ action.SetIsVisible(ExtensionAction2::kDefaultTabId, false);
+ ASSERT_EQ(false, action.GetIsVisible(1));
+ ASSERT_EQ(false, action.GetIsVisible(100));
+ action.SetIsVisible(100, true);
+ ASSERT_EQ(false, action.GetIsVisible(1));
+ ASSERT_EQ(true, action.GetIsVisible(100));
+ action.ClearAllValuesForTab(100);
+ ASSERT_EQ(false, action.GetIsVisible(1));
+ ASSERT_EQ(false, action.GetIsVisible(100));
+
// badge text
ASSERT_EQ("", action.GetBadgeText(1));
action.SetBadgeText(ExtensionAction2::kDefaultTabId, "foo");
@@ -80,48 +109,29 @@ TEST(ExtensionAction2Test, TabSpecificState) {
// badge text color
ASSERT_EQ(0x00000000u, action.GetBadgeTextColor(1));
- action.SetBadgeTextColor(ExtensionAction2::kDefaultTabId, 0xFFFF0000);
+ action.SetBadgeTextColor(ExtensionAction2::kDefaultTabId, 0xFFFF0000u);
ASSERT_EQ(0xFFFF0000u, action.GetBadgeTextColor(1));
ASSERT_EQ(0xFFFF0000u, action.GetBadgeTextColor(100));
action.SetBadgeTextColor(100, 0xFF00FF00);
ASSERT_EQ(0xFFFF0000u, action.GetBadgeTextColor(1));
ASSERT_EQ(0xFF00FF00u, action.GetBadgeTextColor(100));
- action.SetBadgeTextColor(ExtensionAction2::kDefaultTabId, 0xFF0000FF);
+ action.SetBadgeTextColor(ExtensionAction2::kDefaultTabId, 0xFF0000FFu);
ASSERT_EQ(0xFF0000FFu, action.GetBadgeTextColor(1));
action.ClearAllValuesForTab(100);
ASSERT_EQ(0xFF0000FFu, action.GetBadgeTextColor(100));
// badge background color
ASSERT_EQ(0x00000000u, action.GetBadgeBackgroundColor(1));
- action.SetBadgeBackgroundColor(ExtensionAction2::kDefaultTabId, 0xFFFF0000);
+ action.SetBadgeBackgroundColor(ExtensionAction2::kDefaultTabId,
+ 0xFFFF0000u);
ASSERT_EQ(0xFFFF0000u, action.GetBadgeBackgroundColor(1));
ASSERT_EQ(0xFFFF0000u, action.GetBadgeBackgroundColor(100));
action.SetBadgeBackgroundColor(100, 0xFF00FF00);
ASSERT_EQ(0xFFFF0000u, action.GetBadgeBackgroundColor(1));
ASSERT_EQ(0xFF00FF00u, action.GetBadgeBackgroundColor(100));
- action.SetBadgeBackgroundColor(ExtensionAction2::kDefaultTabId, 0xFF0000FF);
+ action.SetBadgeBackgroundColor(ExtensionAction2::kDefaultTabId,
+ 0xFF0000FFu);
ASSERT_EQ(0xFF0000FFu, action.GetBadgeBackgroundColor(1));
action.ClearAllValuesForTab(100);
ASSERT_EQ(0xFF0000FFu, action.GetBadgeBackgroundColor(100));
}
-
-TEST(ExtensionAction2Test, IconOddCases) {
- ExtensionAction2 action;
-
- action.SetIcon(ExtensionAction2::kDefaultTabId, LoadIcon("icon1.png"));
- action.SetDefaultIcon("foo.png");
- ASSERT_TRUE(action.GetIcon(1).isNull());
- ASSERT_EQ("foo.png", action.GetDefaultIconPath());
-
- action.icon_paths()->push_back("a.png");
- action.icon_paths()->push_back("b.png");
- action.SetDefaultIcon(1);
- ASSERT_TRUE(action.GetIcon(1).isNull());
- ASSERT_EQ("b.png", action.GetDefaultIconPath());
-
- action.SetIcon(100, LoadIcon("icon1.png"));
- ASSERT_TRUE(!action.GetIcon(100).isNull());
- action.SetIcon(ExtensionAction2::kDefaultTabId, LoadIcon("icon1.png"));
- ASSERT_TRUE(!action.GetIcon(1).isNull());
- ASSERT_EQ("", action.GetDefaultIconPath());
-}
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index eeb4499..dd366fb 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -297,18 +297,18 @@ TEST(ExtensionTest, LoadPageActionHelper) {
#endif
Extension extension(path);
std::string error_msg;
- scoped_ptr<ExtensionAction> action;
+ scoped_ptr<ExtensionAction2> action;
DictionaryValue input;
// First try with an empty dictionary. We should get nothing back.
- ASSERT_TRUE(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::PAGE_ACTION) == NULL);
+ ASSERT_TRUE(extension.LoadExtensionAction2Helper(
+ &input, &error_msg) == NULL);
ASSERT_STRNE("", error_msg.c_str());
error_msg = "";
// Now try the same, but as a browser action. Ensure same results.
- ASSERT_TRUE(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::BROWSER_ACTION) == NULL);
+ ASSERT_TRUE(extension.LoadExtensionAction2Helper(
+ &input, &error_msg) == NULL);
ASSERT_STRNE("", error_msg.c_str());
error_msg = "";
@@ -326,46 +326,23 @@ TEST(ExtensionTest, LoadPageActionHelper) {
icons->Set(1, Value::CreateStringValue(img2));
input.Set(keys::kPageActionIcons, icons);
- // Parse as page action and read back the values from the object.
- action.reset(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::PAGE_ACTION));
+ // Parse and read back the values from the object.
+ action.reset(extension.LoadExtensionAction2Helper(
+ &input, &error_msg));
ASSERT_TRUE(NULL != action.get());
ASSERT_STREQ("", error_msg.c_str());
ASSERT_STREQ(id.c_str(), action->id().c_str());
- ASSERT_STREQ(name.c_str(), action->title().c_str());
- ASSERT_EQ(2u, action->icon_paths().size());
- ASSERT_STREQ(img1.c_str(), action->icon_paths()[0].c_str());
- ASSERT_STREQ(img2.c_str(), action->icon_paths()[1].c_str());
- ASSERT_EQ(ExtensionAction::PAGE_ACTION, action->type());
-
- // Now try the same, but as a browser action.
- action.reset(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::BROWSER_ACTION));
- ASSERT_TRUE(NULL != action.get());
- ASSERT_STREQ("", error_msg.c_str());
- // Browser actions don't have an id, page actions do.
- ASSERT_STREQ("", action->id().c_str());
- ASSERT_STREQ(name.c_str(), action->title().c_str());
- ASSERT_EQ(2u, action->icon_paths().size());
- ASSERT_STREQ(img1.c_str(), action->icon_paths()[0].c_str());
- ASSERT_STREQ(img2.c_str(), action->icon_paths()[1].c_str());
- ASSERT_EQ(ExtensionAction::BROWSER_ACTION, action->type());
+ ASSERT_STREQ(name.c_str(), action->GetTitle(1).c_str());
+ ASSERT_EQ(2u, action->icon_paths()->size());
+ ASSERT_STREQ(img1.c_str(), action->icon_paths()->at(0).c_str());
+ ASSERT_STREQ(img2.c_str(), action->icon_paths()->at(1).c_str());
// Explicitly set the same type and parse again.
input.SetString(keys::kType, values::kPageActionTypeTab);
- action.reset(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::BROWSER_ACTION));
- ASSERT_TRUE(NULL != action.get());
- ASSERT_STREQ("", error_msg.c_str());
- ASSERT_EQ(ExtensionAction::BROWSER_ACTION, action->type());
-
- // Explicitly set the PAGE_ACTION type and parse again.
- input.SetString(keys::kType, values::kPageActionTypePermanent);
- action.reset(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::PAGE_ACTION));
+ action.reset(extension.LoadExtensionAction2Helper(
+ &input, &error_msg));
ASSERT_TRUE(NULL != action.get());
ASSERT_STREQ("", error_msg.c_str());
- ASSERT_EQ(ExtensionAction::PAGE_ACTION, action->type());
// Make a deep copy of the input and remove one key at a time and see if we
// get the right error.
@@ -374,18 +351,8 @@ TEST(ExtensionTest, LoadPageActionHelper) {
// First remove id key.
copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
copy->Remove(keys::kPageActionId, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::PAGE_ACTION));
- ASSERT_TRUE(NULL != action.get());
- ASSERT_STREQ("", error_msg.c_str());
- error_msg = "";
-
- // Same test (id key), but with browser action.
- copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
- copy->Remove(keys::kPageActionId, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::BROWSER_ACTION));
- // Having no id is valid for browser actions.
+ action.reset(extension.LoadExtensionAction2Helper(
+ copy.get(), &error_msg));
ASSERT_TRUE(NULL != action.get());
ASSERT_STREQ("", error_msg.c_str());
error_msg = "";
@@ -393,18 +360,8 @@ TEST(ExtensionTest, LoadPageActionHelper) {
// Then remove the name key.
copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
copy->Remove(keys::kName, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::PAGE_ACTION));
- ASSERT_TRUE(NULL == action.get());
- ASSERT_TRUE(MatchPattern(error_msg.c_str(),
- errors::kInvalidPageActionDefaultTitle));
- error_msg = "";
-
- // Same test (name key), but with browser action.
- copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
- copy->Remove(keys::kName, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::BROWSER_ACTION));
+ action.reset(extension.LoadExtensionAction2Helper(
+ copy.get(), &error_msg));
ASSERT_TRUE(NULL == action.get());
ASSERT_TRUE(MatchPattern(error_msg.c_str(),
errors::kInvalidPageActionDefaultTitle));
@@ -413,18 +370,11 @@ TEST(ExtensionTest, LoadPageActionHelper) {
// Then remove the icon paths key.
copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
copy->Remove(keys::kPageActionIcons, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::PAGE_ACTION));
+ action.reset(extension.LoadExtensionAction2Helper(
+ copy.get(), &error_msg));
ASSERT_TRUE(NULL != action.get());
error_msg = "";
- // Same test (name key), but with browser action.
- copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
- copy->Remove(keys::kPageActionIcons, NULL);
- action.reset(extension.LoadExtensionActionHelper(
- copy.get(), &error_msg, ExtensionAction::BROWSER_ACTION));
- ASSERT_TRUE(NULL != action.get());
-
// Now test that we can parse the new format for page actions.
// Now setup some values to use in the page action.
@@ -436,15 +386,13 @@ TEST(ExtensionTest, LoadPageActionHelper) {
input.SetString(keys::kPageActionDefaultTitle, kTitle);
input.SetString(keys::kPageActionDefaultIcon, kIcon);
- // Parse as page action and read back the values from the object.
- action.reset(extension.LoadExtensionActionHelper(
- &input, &error_msg, ExtensionAction::PAGE_ACTION));
+ // Parse and read back the values from the object.
+ action.reset(extension.LoadExtensionAction2Helper(
+ &input, &error_msg));
ASSERT_TRUE(action.get());
ASSERT_STREQ("", error_msg.c_str());
- ASSERT_EQ(kTitle, action->title());
- ASSERT_EQ(1u, action->icon_paths().size());
- ASSERT_EQ(kIcon, action->icon_paths()[0]);
- ASSERT_EQ(ExtensionAction::PAGE_ACTION, action->type());
+ ASSERT_EQ(kTitle, action->GetTitle(1));
+ ASSERT_EQ(0u, action->icon_paths()->size());
}
TEST(ExtensionTest, IdIsValid) {
diff --git a/chrome/test/data/extensions/samples/test_page_action/background.html b/chrome/test/data/extensions/samples/test_page_action/background.html
index b9de03d..2b77a66 100644
--- a/chrome/test/data/extensions/samples/test_page_action/background.html
+++ b/chrome/test/data/extensions/samples/test_page_action/background.html
@@ -2,15 +2,18 @@
<head>
<script>
var lastTabId = 0;
+ var visible = false;
chrome.tabs.onUpdated.addListener(function(tabId, p) {
lastTabId = tabId;
+ chrome.pageAction.show(tabId);
});
- // Called when the user clicks on the browser action.
+ // Called when the user clicks on the page action.
var clicks = 0;
var text = "";
chrome.pageAction.onClicked.addListener(function(_, info) {
- chrome.pageAction.setIcon({iconIndex: clicks, tabId: info.tabId});
+ chrome.pageAction.setIcon({path: "icon" + (clicks + 1) + ".png",
+ tabId: info.tabId});
if (clicks % 2) {
chrome.pageAction.show(info.tabId);
} else {
@@ -18,19 +21,7 @@
setTimeout(function() { chrome.pageAction.show(info.tabId); }, 200);
}
chrome.pageAction.setTitle({title: "click:" + clicks, tabId: info.tabId});
- chrome.pageAction.setBadgeTextColor({
- tabId: info.tabId,
- color: [255, 255, clicks * 50, 255]
- });
- chrome.pageAction.setBadgeBackgroundColor({
- tabId: info.tabId,
- color: [255, clicks * 50, 0, 255]
- });
text += clicks.toString();
- chrome.pageAction.setBadgeText({
- tabId: info.tabId,
- text: text
- });
// We only have 2 icons, but cycle through 3 icons to test the
// out-of-bounds index bug.
@@ -43,6 +34,10 @@
window.setInterval(function() {
// Don't animate while in "click" mode.
if (clicks > 0) return;
+
+ // Don't do anything if we don't have a tab yet.
+ if (lastTabId == 0) return;
+
i++;
chrome.pageAction.setIcon({imageData: draw(i*2, i*4), tabId: lastTabId});
}, 50);
diff --git a/chrome/test/data/extensions/samples/test_page_action/icon1.png b/chrome/test/data/extensions/samples/test_page_action/icon1.png
new file mode 100755
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/test/data/extensions/samples/test_page_action/icon1.png
Binary files differ
diff --git a/chrome/test/data/extensions/samples/test_page_action/icon2.png b/chrome/test/data/extensions/samples/test_page_action/icon2.png
new file mode 100755
index 0000000..8d3f710
--- /dev/null
+++ b/chrome/test/data/extensions/samples/test_page_action/icon2.png
Binary files differ
diff --git a/chrome/test/data/extensions/samples/test_page_action/manifest.json b/chrome/test/data/extensions/samples/test_page_action/manifest.json
index 28e0dab..5a374e8 100644
--- a/chrome/test/data/extensions/samples/test_page_action/manifest.json
+++ b/chrome/test/data/extensions/samples/test_page_action/manifest.json
@@ -5,7 +5,6 @@
"permissions": ["tabs"],
"background_page": "background.html",
"page_action": {
- "default_title": "First icon",
- "default_icon": "print_16x16.png"
+ "default_title": "First icon"
}
}
diff --git a/chrome/test/data/extensions/samples/test_page_action/print_16x16.png b/chrome/test/data/extensions/samples/test_page_action/print_16x16.png
deleted file mode 100644
index d145964..0000000
--- a/chrome/test/data/extensions/samples/test_page_action/print_16x16.png
+++ /dev/null
Binary files differ