summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-01 21:57:00 +0000
committerfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-01 21:57:00 +0000
commitd7eaf5753249cbb6e95441b07e00a6349c7afe89 (patch)
tree7d03c6ce6a182a52465ad4d8f410117c2430a6bf /chrome
parent92ac30171a8334bc1691096abccf004ed02d0d42 (diff)
downloadchromium_src-d7eaf5753249cbb6e95441b07e00a6349c7afe89.zip
chromium_src-d7eaf5753249cbb6e95441b07e00a6349c7afe89.tar.gz
chromium_src-d7eaf5753249cbb6e95441b07e00a6349c7afe89.tar.bz2
PageActions can now specify multiple icons and switch between them
using optional parameters to enableForTab. BUG=http://crbug.com/11906 TEST=None Review URL: http://codereview.chromium.org/149046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19772 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.cc14
-rwxr-xr-xchrome/browser/extensions/extension_page_actions_module_constants.cc2
-rwxr-xr-xchrome/browser/extensions/extension_page_actions_module_constants.h2
-rw-r--r--chrome/browser/extensions/extensions_service.cc16
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc7
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc28
-rw-r--r--chrome/browser/tab_contents/tab_contents.h24
-rw-r--r--chrome/browser/views/location_bar_view.cc75
-rw-r--r--chrome/browser/views/location_bar_view.h8
-rw-r--r--chrome/common/extensions/extension.cc43
-rw-r--r--chrome/common/extensions/extension.h2
-rw-r--r--chrome/common/page_action.h34
-rw-r--r--chrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js4
-rw-r--r--chrome/test/data/extensions/page_action.crxbin6515 -> 16810 bytes
-rw-r--r--chrome/test/data/extensions/samples/subscribe_page_action/background.html51
-rw-r--r--chrome/test/data/extensions/samples/subscribe_page_action/feed-icon-16x16-subscribed.pngbin0 -> 450 bytes
-rw-r--r--chrome/test/data/extensions/samples/subscribe_page_action/manifest.json5
18 files changed, 250 insertions, 67 deletions
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
index 66bd9e3..d3ba09a 100644
--- a/chrome/browser/extensions/extension_page_actions_module.cc
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -31,6 +31,18 @@ bool PageActionFunction::SetPageActionEnabled(bool enable) {
std::string url;
EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kUrlKey, &url));
+ std::string title;
+ int icon_id = 0;
+ if (enable) {
+ // Both of those are optional.
+ if (action->HasKey(keys::kTitleKey))
+ EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kTitleKey, &title));
+ if (action->HasKey(keys::kIconIdKey)) {
+ EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kIconIdKey,
+ &icon_id));
+ }
+ }
+
// Find the TabContents that contains this tab id.
TabContents* contents = NULL;
ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL, &contents, NULL);
@@ -66,7 +78,7 @@ bool PageActionFunction::SetPageActionEnabled(bool enable) {
}
// Set visibility and broadcast notifications that the UI should be updated.
- contents->SetPageActionEnabled(page_action, enable);
+ contents->SetPageActionEnabled(page_action, enable, title, icon_id);
contents->NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);
return true;
diff --git a/chrome/browser/extensions/extension_page_actions_module_constants.cc b/chrome/browser/extensions/extension_page_actions_module_constants.cc
index e58264b..2b54f1b 100755
--- a/chrome/browser/extensions/extension_page_actions_module_constants.cc
+++ b/chrome/browser/extensions/extension_page_actions_module_constants.cc
@@ -8,6 +8,8 @@ namespace extension_page_actions_module_constants {
const wchar_t kTabIdKey[] = L"tabId";
const wchar_t kUrlKey[] = L"url";
+const wchar_t kTitleKey[] = L"title";
+const wchar_t kIconIdKey[] = L"iconId";
const char kNoExtensionError[] = "No extension with id: *.";
const char kNoTabError[] = "No tab with id: *.";
diff --git a/chrome/browser/extensions/extension_page_actions_module_constants.h b/chrome/browser/extensions/extension_page_actions_module_constants.h
index bf28b9f..91db0d8 100755
--- a/chrome/browser/extensions/extension_page_actions_module_constants.h
+++ b/chrome/browser/extensions/extension_page_actions_module_constants.h
@@ -12,6 +12,8 @@ namespace extension_page_actions_module_constants {
// Keys.
extern const wchar_t kTabIdKey[];
extern const wchar_t kUrlKey[];
+extern const wchar_t kTitleKey[];
+extern const wchar_t kIconIdKey[];
// Error messages.
extern const char kNoExtensionError[];
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index df59e04..b44c630 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -753,12 +753,16 @@ Extension* ExtensionsServiceBackend::LoadExtension(
for (PageActionMap::const_iterator i(page_actions.begin());
i != page_actions.end(); ++i) {
PageAction* page_action = i->second;
- FilePath path = page_action->icon_path();
- if (!file_util::PathExists(path)) {
- ReportExtensionLoadError(extension_path,
- StringPrintf("Could not load icon '%s' for page action.",
- WideToUTF8(path.ToWStringHack()).c_str()));
- return NULL;
+ const std::vector<FilePath>& icon_paths = page_action->icon_paths();
+ for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ FilePath path = *iter;
+ if (!file_util::PathExists(path)) {
+ ReportExtensionLoadError(extension_path,
+ StringPrintf("Could not load icon '%s' for page action.",
+ WideToUTF8(path.ToWStringHack()).c_str()));
+ return NULL;
+ }
}
}
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index b195151..3b75dcc 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -40,7 +40,7 @@ const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj";
const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk";
const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
-const char* const page_action = "kemkhnabegjkabakmlcaafgikalipenj";
+const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln";
const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
@@ -654,7 +654,9 @@ TEST_F(ExtensionsServiceTest, CleanupOnStartup) {
ASSERT_FALSE(file_util::PathExists(vers));
}
-// Test installing extensions.
+// Test installing extensions. This test tries to install few extensions using
+// crx files. If you need to change those crx files, feel free to repackage
+// them, throw away the key used and change the id's above.
TEST_F(ExtensionsServiceTest, InstallExtension) {
InitializeEmptyExtensionsService();
@@ -690,6 +692,7 @@ TEST_F(ExtensionsServiceTest, InstallExtension) {
// Bad signature.
path = extensions_path.AppendASCII("bad_signature.crx");
InstallExtension(path, false);
+ ValidatePrefKeyCount(pref_count);
// 0-length extension file.
path = extensions_path.AppendASCII("not_an_extension.crx");
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index c4906ce..0884317 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -565,23 +565,31 @@ void TabContents::SetIsCrashed(bool state) {
}
void TabContents::SetPageActionEnabled(const PageAction* page_action,
- bool enable) {
+ bool enable,
+ const std::string& title,
+ int icon_id) {
DCHECK(page_action);
- if (enable == IsPageActionEnabled(page_action))
- return; // Don't need to do anything more.
+ if (!enable &&
+ enabled_page_actions_.end() == enabled_page_actions_.find(page_action)) {
+ return; // Don't need to disable twice.
+ }
- if (enable)
- enabled_page_actions_.insert(page_action);
- else
+ if (enable) {
+ enabled_page_actions_[page_action].reset(
+ new PageActionState(title, icon_id));
+ } else {
enabled_page_actions_.erase(page_action);
+ }
}
-bool TabContents::IsPageActionEnabled(const PageAction* page_action) {
- DCHECK(page_action);
- return enabled_page_actions_.end() != enabled_page_actions_.find(page_action);
-}
+const PageActionState* TabContents::GetPageActionState(
+ const PageAction* page_action) {
+ if (enabled_page_actions_.end() == enabled_page_actions_.find(page_action))
+ return NULL;
+ return enabled_page_actions_[page_action].get();
+}
void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
if (delegate_)
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 5b4fa7b..f81c725 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -32,6 +32,7 @@
#include "chrome/common/gears_api.h"
#include "chrome/common/navigation_types.h"
#include "chrome/common/notification_registrar.h"
+#include "chrome/common/page_action.h"
#include "chrome/common/property_bag.h"
#include "chrome/common/renderer_preferences.h"
#include "net/base/load_states.h"
@@ -254,10 +255,17 @@ class TabContents : public PageNavigator,
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 PageAction* 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.
- void SetPageActionEnabled(const PageAction* page_action, bool enable);
- // Checks to see if the PageAction should be visible in this tab.
- bool IsPageActionEnabled(const PageAction* page_action);
+ const PageActionState* GetPageActionState(const PageAction* page_action);
// Whether the tab is in the process of being destroyed.
// Added as a tentative work-around for focus related bug #4633. This allows
@@ -1036,10 +1044,12 @@ class TabContents : public PageNavigator,
// Data for Page Actions -----------------------------------------------------
- // A set of page actions that are enabled in this tab. This list is cleared
- // every time the mainframe navigates and populated by the PageAction
- // extension API.
- std::set<const PageAction*> enabled_page_actions_;
+ // A map of page actions that are enabled in this tab (and a state object
+ // that can be used to override the title and icon used for the page action).
+ // This map is cleared every time the mainframe navigates and populated by the
+ // PageAction extension API.
+ std::map< const PageAction*, linked_ptr<PageActionState> >
+ enabled_page_actions_;
// Data for misc internal state ----------------------------------------------
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index 7530dee..af8c57f 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -1140,7 +1140,8 @@ void LocationBarView::SecurityImageView::ShowInfoBubble() {
class LocationBarView::PageActionImageView::ImageLoadingTracker
: public base::RefCountedThreadSafe<ImageLoadingTracker> {
public:
- explicit ImageLoadingTracker(PageActionImageView* view) : view_(view) {
+ explicit ImageLoadingTracker(PageActionImageView* view, int image_count)
+ : view_(view), image_count_(image_count) {
AddRef(); // We hold on to a reference to ourself to make sure we don't
// get deleted until we get a response from image loading (see
// ImageLoadingDone).
@@ -1151,16 +1152,20 @@ class LocationBarView::PageActionImageView::ImageLoadingTracker
view_ = NULL;
}
- void OnImageLoaded(SkBitmap* image) {
- view_->OnImageLoaded(image);
+ void OnImageLoaded(SkBitmap* image, int index) {
+ view_->OnImageLoaded(image, index);
delete image;
- Release(); // We are no longer needed.
+ if (--image_count_ == 0)
+ Release(); // We are no longer needed.
}
private:
// The view that is waiting for the image to load.
PageActionImageView* view_;
+
+ // The number of images this ImageTracker should keep track of.
+ int image_count_;
};
// The LoadImageTask is for asynchronously loading the image on the file thread.
@@ -1168,16 +1173,24 @@ class LocationBarView::PageActionImageView::ImageLoadingTracker
// |callback_loop| to let the caller know the image is done loading.
class LocationBarView::PageActionImageView::LoadImageTask : public Task {
public:
+ // Constructor for the LoadImageTask class. |tracker| is the object that
+ // we use to communicate back to the entity that wants the image after we
+ // decode it. |path| is the path to load the image from. |index| is an
+ // identifier for the image that we pass back to the caller.
LoadImageTask(ImageLoadingTracker* tracker,
- const FilePath& path)
+ const FilePath& path,
+ int index)
: callback_loop_(MessageLoop::current()),
tracker_(tracker),
- path_(path) {}
+ path_(path),
+ index_(index) {}
void ReportBack(SkBitmap* image) {
DCHECK(image);
callback_loop_->PostTask(FROM_HERE, NewRunnableMethod(tracker_,
- &PageActionImageView::ImageLoadingTracker::OnImageLoaded, image));
+ &PageActionImageView::ImageLoadingTracker::OnImageLoaded,
+ image,
+ index_));
}
virtual void Run() {
@@ -1223,6 +1236,9 @@ class LocationBarView::PageActionImageView::LoadImageTask : public Task {
// The path to the image to load asynchronously.
FilePath path_;
+
+ // The index of the icon being loaded.
+ int index_;
};
LocationBarView::PageActionImageView::PageActionImageView(
@@ -1233,15 +1249,22 @@ LocationBarView::PageActionImageView::PageActionImageView(
owner_(owner),
profile_(profile),
page_action_(page_action),
- tracker_(new ImageLoadingTracker(this)) {
+ current_tab_id_(-1),
+ tooltip_(page_action_->name()) {
// 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_path().empty());
- FilePath path = FilePath(page_action->icon_path());
+ DCHECK(!page_action->icon_paths().empty());
+ const std::vector<FilePath>& icon_paths = page_action->icon_paths();
+ page_action_icons_.resize(icon_paths.size());
+ int index = 0;
MessageLoop* file_loop = g_browser_process->file_thread()->message_loop();
- file_loop->PostTask(FROM_HERE,
- new LoadImageTask(tracker_, page_action->icon_path()));
+ tracker_ = new ImageLoadingTracker(this, icon_paths.size());
+ for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ FilePath path = *iter;
+ file_loop->PostTask(FROM_HERE, new LoadImageTask(tracker_, path, index++));
+ }
}
LocationBarView::PageActionImageView::~PageActionImageView() {
@@ -1259,7 +1282,7 @@ bool LocationBarView::PageActionImageView::OnMousePressed(
void LocationBarView::PageActionImageView::ShowInfoBubble() {
SkColor text_color = SK_ColorBLACK;
- ShowInfoBubbleImpl(ASCIIToWide(page_action_->name()), text_color);
+ ShowInfoBubbleImpl(ASCIIToWide(tooltip_), text_color);
}
void LocationBarView::PageActionImageView::UpdateVisibility(
@@ -1269,12 +1292,30 @@ void LocationBarView::PageActionImageView::UpdateVisibility(
current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
current_url_ = url;
- SetVisible(contents->IsPageActionEnabled(page_action_));
+ const PageActionState* state = contents->GetPageActionState(page_action_);
+ bool visible = state != NULL;
+ if (visible) {
+ // Set the tooltip.
+ if (state->title().empty())
+ tooltip_ = page_action_->name();
+ else
+ tooltip_ = state->title();
+ // Set the image.
+ 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;
+ ImageView::SetImage(page_action_icons_[index]);
+ }
+ SetVisible(visible);
}
-void LocationBarView::PageActionImageView::OnImageLoaded(SkBitmap* image) {
- tracker_ = NULL; // The tracker object will delete itself when we return.
- ImageView::SetImage(image);
+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.
+ page_action_icons_[index] = *image;
owner_->UpdatePageActions();
}
diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h
index b90693f..97e7eb6 100644
--- a/chrome/browser/views/location_bar_view.h
+++ b/chrome/browser/views/location_bar_view.h
@@ -332,7 +332,7 @@ class LocationBarView : public LocationBar,
void UpdateVisibility(TabContents* contents, GURL url);
// A callback for when the image has loaded.
- void OnImageLoaded(SkBitmap* image);
+ void OnImageLoaded(SkBitmap* image, size_t index);
private:
// We load the images for the PageActions on the file thread. These tasks
@@ -350,6 +350,9 @@ class LocationBarView : public LocationBar,
// us, it resides in the extension of this particular profile.
const PageAction* page_action_;
+ // The icons representing different states for the page action.
+ std::vector<SkBitmap> page_action_icons_;
+
// The object that is waiting for the image loading to complete
// asynchronously.
ImageLoadingTracker* tracker_;
@@ -360,6 +363,9 @@ class LocationBarView : public LocationBar,
// The URL we are currently showing the icon for.
GURL current_url_;
+ // The string to show for a tooltip;
+ std::string tooltip_;
+
DISALLOW_COPY_AND_ASSIGN(PageActionImageView);
};
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 33baff8..6bce681 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -55,6 +55,7 @@ const wchar_t* Extension::kContentScriptsKey = L"content_scripts";
const wchar_t* Extension::kCssKey = L"css";
const wchar_t* Extension::kDescriptionKey = L"description";
const wchar_t* Extension::kIconPathKey = L"icon";
+const wchar_t* Extension::kIconPathsKey = L"icons";
const wchar_t* Extension::kJsKey = L"js";
const wchar_t* Extension::kMatchesKey = L"matches";
const wchar_t* Extension::kNameKey = L"name";
@@ -126,10 +127,12 @@ const char* Extension::kInvalidNameError =
"Required value 'name' is missing or invalid.";
const char* Extension::kInvalidPageActionError =
"Invalid value for 'page_actions[*]'.";
+const char* Extension::kInvalidPageActionIconPathError =
+ "Invalid value for 'page_actions[*].icons[*]'.";
const char* Extension::kInvalidPageActionsListError =
"Invalid value for 'page_actions'.";
-const char* Extension::kInvalidPageActionIconPathError =
- "Invalid value for 'page_actions[*].icon'.";
+const char* Extension::kInvalidPageActionIconPathsError =
+ "Required value 'page_actions[*].icons' is missing or invalid.";
const char* Extension::kInvalidPageActionIdError =
"Required value 'id' is missing or invalid.";
const char* Extension::kInvalidPageActionTypeValueError =
@@ -398,15 +401,31 @@ PageAction* Extension::LoadPageActionHelper(
scoped_ptr<PageAction> result(new PageAction());
result->set_extension_id(id());
- // Read the page action |icon|.
- std::string icon;
- if (!page_action->GetString(kIconPathKey, &icon)) {
+ ListValue* icons;
+ // Read the page action |icons|.
+ if (!page_action->HasKey(kIconPathsKey) ||
+ !page_action->GetList(kIconPathsKey, &icons) ||
+ icons->GetSize() == 0) {
*error = ExtensionErrorUtils::FormatErrorMessage(
- kInvalidPageActionIconPathError, IntToString(definition_index));
+ kInvalidPageActionIconPathsError, IntToString(definition_index));
return NULL;
}
- FilePath icon_path = path_.AppendASCII(icon);
- result->set_icon_path(icon_path);
+
+ int icon_count = 0;
+ for (ListValue::const_iterator iter = icons->begin();
+ iter != icons->end(); ++iter) {
+ FilePath::StringType path;
+ if (!(*iter)->GetAsString(&path) || path.empty()) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ kInvalidPageActionIconPathError,
+ IntToString(definition_index), IntToString(icon_count));
+ return NULL;
+ }
+
+ FilePath icon_path = path_.Append(path);
+ result->AddIconPath(icon_path);
+ ++icon_count;
+ }
// Read the page action |id|.
std::string id;
@@ -504,7 +523,7 @@ FilePath Extension::GetResourcePath(const FilePath& extension_path,
return ret_val;
}
-Extension::Extension(const FilePath& path) {
+Extension::Extension(const FilePath& path) : is_theme_(false) {
DCHECK(path.IsAbsolute());
location_ = INVALID;
@@ -939,7 +958,11 @@ std::set<FilePath> Extension::GetBrowserImages() {
for (PageActionMap::const_iterator it = page_actions().begin();
it != page_actions().end(); ++it) {
- image_paths.insert(it->second->icon_path());
+ const std::vector<FilePath>& icon_paths = it->second->icon_paths();
+ for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ image_paths.insert(*iter);
+ }
}
return image_paths;
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index ec14b0b..1705e12 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -60,6 +60,7 @@ class Extension {
static const wchar_t* kCssKey;
static const wchar_t* kDescriptionKey;
static const wchar_t* kIconPathKey;
+ static const wchar_t* kIconPathsKey;
static const wchar_t* kJsKey;
static const wchar_t* kMatchesKey;
static const wchar_t* kNameKey;
@@ -115,6 +116,7 @@ class Extension {
static const char* kInvalidPageActionError;
static const char* kInvalidPageActionsListError;
static const char* kInvalidPageActionIconPathError;
+ static const char* kInvalidPageActionIconPathsError;
static const char* kInvalidPageActionIdError;
static const char* kInvalidPageActionTypeValueError;
static const char* kInvalidPermissionsError;
diff --git a/chrome/common/page_action.h b/chrome/common/page_action.h
index d9ccfea..3331f8e 100644
--- a/chrome/common/page_action.h
+++ b/chrome/common/page_action.h
@@ -5,8 +5,9 @@
#ifndef CHROME_COMMON_PAGE_ACTION_H_
#define CHROME_COMMON_PAGE_ACTION_H_
-#include <string>
#include <map>
+#include <string>
+#include <vector>
#include "base/file_path.h"
@@ -34,9 +35,9 @@ class PageAction {
std::string name() const { return name_; }
void set_name(const std::string& name) { name_ = name; }
- FilePath icon_path() const { return icon_path_; }
- void set_icon_path(const FilePath& icon_path) {
- icon_path_ = icon_path;
+ const std::vector<FilePath>& icon_paths() const { return icon_paths_; }
+ void AddIconPath(const FilePath& icon_path) {
+ icon_paths_.push_back(icon_path);
}
private:
@@ -53,10 +54,31 @@ class PageAction {
// The name of the PageAction.
std::string name_;
- // The icon that represents the PageIcon.
- FilePath icon_path_;
+ // The paths to the icons that this PageIcon can show.
+ std::vector<FilePath> icon_paths_;
};
typedef std::map<std::string, PageAction*> PageActionMap;
+// This class keeps track of what values each tab uses to override the default
+// values of the PageAction.
+class PageActionState {
+ public:
+ PageActionState(std::string title, int icon_index)
+ : title_(title), icon_index_(icon_index) {
+ }
+
+ std::string title() const { return title_; }
+ int icon_index() const { return icon_index_; }
+
+ private:
+ // The title to use.
+ std::string title_;
+
+ // The icon to use.
+ int icon_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageActionState);
+};
+
#endif // CHROME_COMMON_PAGE_ACTION_H_
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index c59e98c..cda253b 100644
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. -->
+without changes to the corresponding grd file. -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 8b4c4bb..2e76723 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -320,7 +320,9 @@ var chrome = chrome || {};
type: "object",
properties: {
tabId: chrome.types.pInt,
- url: chrome.types.str
+ url: chrome.types.str,
+ title: chrome.types.optStr,
+ iconId: chrome.types.optPInt,
},
optional: false
}
diff --git a/chrome/test/data/extensions/page_action.crx b/chrome/test/data/extensions/page_action.crx
index 2a397c8..7420c32 100644
--- a/chrome/test/data/extensions/page_action.crx
+++ b/chrome/test/data/extensions/page_action.crx
Binary files differ
diff --git a/chrome/test/data/extensions/samples/subscribe_page_action/background.html b/chrome/test/data/extensions/samples/subscribe_page_action/background.html
index e85e5a6..0eeca7e 100644
--- a/chrome/test/data/extensions/samples/subscribe_page_action/background.html
+++ b/chrome/test/data/extensions/samples/subscribe_page_action/background.html
@@ -1,8 +1,13 @@
<html>
+<head>
<script>
// The Page Action ID.
var pageActionId = "RssPageAction";
+ // The icons to use. These correspond to the icons listed in the manifest.
+ var subscribeId = 0;
+ var alreadySubscribedId = 1;
+
// The window this Page Action is associated with.
var windowId = -1;
@@ -15,6 +20,32 @@
// The feed URL found on the page.
var feedUrl = "";
+ // The URL to use to check if user is subscribed already.
+ var subscribedUrl = "http://www.google.com/reader/api/0/subscribed?s=feed%2F";
+
+ // The XMLHttpRequest object that checks if you are already subscribed.
+ var req;
+
+ // The status of whether you have already subscribed to this feed or not.
+ var alreadySubscribed = false;
+
+ function EnableIcon(subscribed) {
+ alreadySubscribed = subscribed;
+ if (!alreadySubscribed) {
+ chrome.pageActions.enableForTab(
+ pageActionId, {tabId: tabId,
+ url: pageUrl,
+ title: "Click to subscribe...",
+ iconId: subscribeId});
+ } else {
+ chrome.pageActions.enableForTab(
+ pageActionId, {tabId: tabId,
+ url: pageUrl,
+ title: "You are already subscribed to this feed",
+ iconId: alreadySubscribedId});
+ }
+ }
+
chrome.self.onConnect.addListener(function(port) {
windowId = port.tab.windowId;
tabId = port.tab.id;
@@ -28,17 +59,29 @@
// Let Chrome know that the PageAction needs to be enabled for this tabId
// and for the url of this page.
if (feedUrl) {
- chrome.pageActions.enableForTab(pageActionId,
- {tabId: tabId, url: pageUrl});
+ EnableIcon(false); // Not subscribed (as far as we know, might change).
+
+ // But also check the server to see if we have already subscribed so
+ // that we can update the status.
+ feedUrl = encodeURIComponent(feedUrl);
+ req = new XMLHttpRequest();
+ req.onload = handleResponse;
+ req.open("GET", subscribedUrl + feedUrl, false);
+ req.send(null);
}
});
});
+ function handleResponse() {
+ if (req.responseText == "true")
+ EnableIcon(true); // true == Already suscribed.
+ }
+
// Chrome will call into us when the user clicks on the icon in the OmniBox.
chrome.pageActions.onExecute.addListener(function(reply) {
chrome.windows.getCurrent(function(window) {
chrome.tabs.get(reply.data.tabId, function(tab) {
- if (window.focused) {
+ if (!alreadySubscribed && window.focused) {
// We need to know if we are the active window, because the tab may
// have moved to another window and we don't want to execute this
// action multiple times.
@@ -46,7 +89,6 @@
reply.data.tabUrl == pageUrl) {
// Create a new tab showing the subscription page with the right
// feed URL.
- var url = "http://www.google.com/reader/view/feed/" + feedUrl;
chrome.tabs.create({url: "subscribe.html?" + feedUrl,
windowId: windowId});
}
@@ -55,4 +97,5 @@
});
});
</script>
+</head>
</html>
diff --git a/chrome/test/data/extensions/samples/subscribe_page_action/feed-icon-16x16-subscribed.png b/chrome/test/data/extensions/samples/subscribe_page_action/feed-icon-16x16-subscribed.png
new file mode 100644
index 0000000..0369a6b37
--- /dev/null
+++ b/chrome/test/data/extensions/samples/subscribe_page_action/feed-icon-16x16-subscribed.png
Binary files differ
diff --git a/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json b/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json
index 9c34a50..6a8f225 100644
--- a/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json
+++ b/chrome/test/data/extensions/samples/subscribe_page_action/manifest.json
@@ -16,7 +16,10 @@
{
"id": "RssPageAction",
"name": "Subscribe to this feed",
- "icon": "feed-icon-16x16.png"
+ "icons": [
+ "feed-icon-16x16.png",
+ "feed-icon-16x16-subscribed.png"
+ ]
}
]
} \ No newline at end of file