summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 22:02:34 +0000
committerfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 22:02:34 +0000
commitf7f3a5f86a24f65666284802b51d0eaa5c9d7741 (patch)
tree5605992d68c1b48fe47f7fbee560dca7cda6693b /chrome
parent32d371758f777380486f9c8ef28b1faca37ab26c (diff)
downloadchromium_src-f7f3a5f86a24f65666284802b51d0eaa5c9d7741.zip
chromium_src-f7f3a5f86a24f65666284802b51d0eaa5c9d7741.tar.gz
chromium_src-f7f3a5f86a24f65666284802b51d0eaa5c9d7741.tar.bz2
This is the first part of the PageAction implementation. More work is required, but this is a good checkpoint.
Design doc: http://dev.chromium.org/developers/design-documents/extensions/page-actions-api This checkin only covers Tab scoped page actions (not type "permanent"). It works end to end (if you have an extension that supplies the page action info -- I created an RSS page action that links to Google Reader). Please note that TabIndex is hard coded to 0 until the extension system can provide the tab id to the extensions (which I understand is in progress). This means that page action(s) only show up for the first tab in the tabstrip. :) BUG=None TEST=There is a unit test for the API, but apart from that it is not possible to test this manually without writing an extension that adds a PageAction. My RSS page action is not ready to be checked in but I can provide it if there is interest in a sneak preview during review/QA. Review URL: http://codereview.chromium.org/99253 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15105 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser.cc3
-rw-r--r--chrome/browser/browser.vcproj8
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.h1
-rw-r--r--chrome/browser/extensions/extension.cc130
-rw-r--r--chrome/browser/extensions/extension.h32
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.cc26
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.h12
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc9
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.cc64
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.h14
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc6
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h1
-rw-r--r--chrome/browser/location_bar.h3
-rw-r--r--chrome/browser/tab_contents/tab_contents.h2
-rw-r--r--chrome/browser/views/location_bar_view.cc161
-rw-r--r--chrome/browser/views/location_bar_view.h79
-rw-r--r--chrome/chrome.gyp4
-rw-r--r--chrome/common/common.vcproj8
-rw-r--r--chrome/common/page_action.cc27
-rw-r--r--chrome/common/page_action.h82
-rwxr-xr-xchrome/renderer/extensions/extension_api_client_unittest.cc6
-rwxr-xr-xchrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js50
-rw-r--r--chrome/test/test_location_bar.h11
24 files changed, 701 insertions, 40 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 6d50e66..ac79476 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -2370,6 +2370,9 @@ void Browser::ProcessPendingUIUpdates() {
if (flags & TabContents::INVALIDATE_FEEDLIST)
window()->GetLocationBar()->UpdateFeedIcon();
+ if (flags & TabContents::INVALIDATE_PAGE_ACTIONS)
+ window()->GetLocationBar()->UpdatePageActions();
+
// Updating the URL happens synchronously in ScheduleUIUpdate.
if (flags & TabContents::INVALIDATE_LOAD && GetStatusBubble())
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index 88150e2..2afce4c 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -1974,6 +1974,14 @@
>
</File>
<File
+ RelativePath=".\extensions\extension_page_actions_module.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\extension_page_actions_module.h"
+ >
+ </File>
+ <File
RelativePath=".\extensions\extension_protocols.cc"
>
</File>
diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h
index 90cb2a6..7de0d95 100644
--- a/chrome/browser/cocoa/location_bar_view_mac.h
+++ b/chrome/browser/cocoa/location_bar_view_mac.h
@@ -39,6 +39,7 @@ class LocationBarViewMac : public AutocompleteEditController,
virtual void FocusLocation();
virtual void FocusSearch() { NOTIMPLEMENTED(); }
virtual void UpdateFeedIcon() { /* http://crbug.com/8832 */ }
+ virtual void UpdatePageActions() { NOTIMPLEMENTED(); }
virtual void SaveStateToContents(TabContents* contents);
virtual void OnAutocompleteAccept(const GURL& url,
diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc
index 6b2bb3e..35b169e 100644
--- a/chrome/browser/extensions/extension.cc
+++ b/chrome/browser/extensions/extension.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/extension.h"
#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "net/base/net_util.h"
@@ -18,21 +19,28 @@ const char Extension::kManifestFilename[] = "manifest.json";
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::kIdKey = L"id";
const wchar_t* Extension::kJsKey = L"js";
const wchar_t* Extension::kMatchesKey = L"matches";
const wchar_t* Extension::kNameKey = L"name";
+const wchar_t* Extension::kPageActionsKey = L"page_actions";
const wchar_t* Extension::kPermissionsKey = L"permissions";
const wchar_t* Extension::kPluginsDirKey = L"plugins_dir";
const wchar_t* Extension::kBackgroundKey = L"background";
const wchar_t* Extension::kRunAtKey = L"run_at";
const wchar_t* Extension::kThemeKey = L"theme";
const wchar_t* Extension::kToolstripsKey = L"toolstrips";
+const wchar_t* Extension::kTooltipKey = L"tooltip";
+const wchar_t* Extension::kTypeKey = L"type";
const wchar_t* Extension::kVersionKey = L"version";
const wchar_t* Extension::kZipHashKey = L"zip_hash";
const char* Extension::kRunAtDocumentStartValue = "document_start";
const char* Extension::kRunAtDocumentEndValue = "document_end";
+const char* Extension::kPageActionTypeTab = "tab";
+const char* Extension::kPageActionTypePermanent = "permanent";
+
// Extension-related error messages. Some of these are simple patterns, where a
// '*' is replaced at runtime with a specific value. This is used instead of
@@ -65,6 +73,16 @@ const char* Extension::kInvalidMatchesError =
"Required value 'content_scripts[*].matches' is missing or invalid.";
const char* Extension::kInvalidNameError =
"Required value 'name' is missing or invalid.";
+const char* Extension::kInvalidPageActionError =
+ "Invalid value for 'page_actions[*]'.";
+const char* Extension::kInvalidPageActionsListError =
+ "Invalid value for 'page_actions'.";
+const char* Extension::kInvalidPageActionIconPathError =
+ "Invalid value for 'page_actions[*].icon'.";
+const char* Extension::kInvalidPageActionTooltipError =
+ "Invalid value for 'page_actions[*].tooltip'.";
+const char* Extension::kInvalidPageActionTypeValueError =
+ "Invalid value for 'page_actions[*].type', expected 'tab' or 'permanent'.";
const char* Extension::kInvalidPermissionsError =
"Required value 'permissions' is missing or invalid.";
const char* Extension::kInvalidPermissionCountWarning =
@@ -90,6 +108,8 @@ const char* Extension::kInvalidZipHashError =
"Required key 'zip_hash' is missing or invalid.";
const char* Extension::kMissingFileError =
"At least one js or css file is required for 'content_scripts[*]'.";
+const char* Extension::kMissingPageActionIcon =
+ "Unable to find 'page_actions[*].icon'";
const size_t Extension::kIdSize = 20; // SHA1 (160 bits) == 20 bytes
@@ -101,11 +121,18 @@ Extension::Extension(const Extension& rhs)
name_(rhs.name_),
description_(rhs.description_),
content_scripts_(rhs.content_scripts_),
+ page_actions_(rhs.page_actions_),
plugins_dir_(rhs.plugins_dir_),
zip_hash_(rhs.zip_hash_),
theme_paths_(rhs.theme_paths_) {
}
+Extension::~Extension() {
+ for (PageActionMap::iterator i = page_actions_.begin();
+ i != page_actions_.end(); ++i)
+ delete i->second;
+}
+
const std::string Extension::VersionString() const {
return version_->GetString();
}
@@ -130,6 +157,14 @@ FilePath Extension::GetThemeResourcePath(const int resource_id) {
return FilePath();
}
+bool Extension::UpdatePageAction(std::string id, int tab_id, GURL url) {
+ if (page_actions_.find(id) == page_actions_.end())
+ return false;
+
+ page_actions_[id]->SetActiveTabIdAndUrl(tab_id, url);
+ return true;
+}
+
// static
FilePath Extension::GetResourcePath(const FilePath& extension_path,
const std::string& relative_path) {
@@ -323,6 +358,74 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
return true;
}
+// Helper method that loads a PageAction object from a dictionary in the
+// page_action list of the manifest.
+bool Extension::LoadPageActionHelper(const DictionaryValue* page_action,
+ int definition_index, std::string* error,
+ PageAction* result) {
+ result->set_extension_id(id());
+
+ // Read the page action |icon|.
+ std::string icon;
+ if (!page_action->GetString(kIconPathKey, &icon)) {
+ *error = FormatErrorMessage(kInvalidPageActionIconPathError,
+ IntToString(definition_index));
+ return false;
+ }
+ FilePath icon_path = path_.AppendASCII(icon);
+ if (!file_util::PathExists(icon_path)) {
+ *error = FormatErrorMessage(kMissingPageActionIcon,
+ IntToString(definition_index));
+ return false;
+ }
+ result->set_icon_path(icon_path);
+
+ // Read the page action |id|.
+ std::string id;
+ if (!page_action->GetString(kIdKey, &id)) {
+ *error = FormatErrorMessage(kInvalidIdError, IntToString(definition_index));
+ return false;
+ }
+ result->set_id(id);
+
+ // Read the page action |name|.
+ std::string name;
+ if (!page_action->GetString(kNameKey, &name)) {
+ *error = FormatErrorMessage(kInvalidNameError,
+ IntToString(definition_index));
+ return false;
+ }
+ result->set_name(name);
+
+ // Read the page action |tooltip|.
+ std::string tooltip;
+ if (!page_action->GetString(kTooltipKey, &tooltip)) {
+ *error = FormatErrorMessage(kInvalidPageActionTooltipError,
+ IntToString(definition_index));
+ return false;
+ }
+ result->set_tooltip(tooltip);
+
+ // Read the page action |type|. It is optional and set to permanent if
+ // missing.
+ std::string type;
+ if (!page_action->GetString(kTypeKey, &type)) {
+ result->set_type(PageAction::PERMANENT);
+ } else if (!LowerCaseEqualsASCII(type, kPageActionTypeTab) &&
+ !LowerCaseEqualsASCII(type, kPageActionTypePermanent)) {
+ *error = FormatErrorMessage(kInvalidPageActionTypeValueError,
+ IntToString(definition_index));
+ return false;
+ } else {
+ if (LowerCaseEqualsASCII(type, kPageActionTypeTab))
+ result->set_type(PageAction::TAB);
+ else
+ result->set_type(PageAction::PERMANENT);
+ }
+
+ return true;
+}
+
bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
std::string* error) {
// Initialize id.
@@ -474,6 +577,31 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
}
}
+ // Initialize page actions (optional).
+ if (source.HasKey(kPageActionsKey)) {
+ ListValue* list_value;
+ if (!source.GetList(kPageActionsKey, &list_value)) {
+ *error = kInvalidPageActionsListError;
+ return false;
+ }
+
+ for (size_t i = 0; i < list_value->GetSize(); ++i) {
+ DictionaryValue* page_action_value;
+ if (!list_value->GetDictionary(i, &page_action_value)) {
+ *error = FormatErrorMessage(kInvalidPageActionError,
+ IntToString(i));
+ return false;
+ }
+
+ PageAction* page_action = new PageAction();
+ if (!LoadPageActionHelper(page_action_value, i, error, page_action)) {
+ delete page_action;
+ return false; // Failed to parse page action definition.
+ }
+ page_actions_[page_action->id()] = page_action;
+ }
+ }
+
// Initialize the permissions (optional).
if (source.HasKey(kPermissionsKey)) {
ListValue* hosts = NULL;
diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h
index 95f04bb..bf62694 100644
--- a/chrome/browser/extensions/extension.h
+++ b/chrome/browser/extensions/extension.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -16,6 +16,7 @@
#include "base/version.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/common/extensions/url_pattern.h"
+#include "chrome/common/page_action.h"
#include "googleurl/src/gurl.h"
// Represents a Chromium extension.
@@ -24,6 +25,7 @@ class Extension {
Extension() {}
explicit Extension(const FilePath& path);
explicit Extension(const Extension& path);
+ virtual ~Extension();
// The name of the manifest inside an extension.
static const char kManifestFilename[];
@@ -32,22 +34,28 @@ class Extension {
static const wchar_t* kContentScriptsKey;
static const wchar_t* kCssKey;
static const wchar_t* kDescriptionKey;
+ static const wchar_t* kIconPathKey;
static const wchar_t* kIdKey;
static const wchar_t* kJsKey;
static const wchar_t* kMatchesKey;
static const wchar_t* kNameKey;
+ static const wchar_t* kPageActionsKey;
static const wchar_t* kPermissionsKey;
static const wchar_t* kPluginsDirKey;
static const wchar_t* kBackgroundKey;
static const wchar_t* kRunAtKey;
static const wchar_t* kThemeKey;
static const wchar_t* kToolstripsKey;
+ static const wchar_t* kTooltipKey;
+ static const wchar_t* kTypeKey;
static const wchar_t* kVersionKey;
static const wchar_t* kZipHashKey;
// Some values expected in manifests.
static const char* kRunAtDocumentStartValue;
static const char* kRunAtDocumentEndValue;
+ static const char* kPageActionTypeTab;
+ static const char* kPageActionTypePermanent;
// Error messages returned from InitFromValue().
static const char* kInvalidContentScriptError;
@@ -69,12 +77,18 @@ class Extension {
static const char* kInvalidToolstripError;
static const char* kInvalidToolstripsError;
static const char* kInvalidVersionError;
+ static const char* kInvalidPageActionError;
+ static const char* kInvalidPageActionsListError;
+ static const char* kInvalidPageActionIconPathError;
+ static const char* kInvalidPageActionTooltipError;
+ static const char* kInvalidPageActionTypeValueError;
static const char* kInvalidPermissionsError;
static const char* kInvalidPermissionCountWarning;
static const char* kInvalidPermissionError;
static const char* kInvalidPermissionSchemeError;
static const char* kInvalidZipHashError;
static const char* kMissingFileError;
+ static const char* kMissingPageActionIcon;
// The number of bytes in a legal id.
static const size_t kIdSize;
@@ -114,6 +128,10 @@ class Extension {
// as providing a theme.
FilePath GetThemeResourcePath(const int resource_id);
+ // Update the status of the page action with |id| in tab |tab_id| and set the
+ // current page url to |url|.
+ bool UpdatePageAction(std::string id, int tab_id, GURL url);
+
const FilePath& path() const { return path_; }
const GURL& url() const { return extension_url_; }
const std::string& id() const { return id_; }
@@ -123,6 +141,7 @@ class Extension {
const std::string& name() const { return name_; }
const std::string& description() const { return description_; }
const UserScriptList& content_scripts() const { return content_scripts_; }
+ const PageActionMap& page_actions() const { return page_actions_; }
const FilePath& plugins_dir() const { return plugins_dir_; }
const GURL& background_url() const { return background_url_; }
const std::vector<std::string>& toolstrips() const { return toolstrips_; }
@@ -136,6 +155,14 @@ class Extension {
int definition_index,
std::string* error,
UserScript* result);
+
+ // Helper method that loads a PageAction object from a
+ // dictionary in the page_action list of the manifest.
+ bool LoadPageActionHelper(const DictionaryValue* page_action,
+ int definition_index,
+ std::string* error,
+ PageAction* result);
+
// The absolute path to the directory the extension is stored in.
FilePath path_;
@@ -162,6 +189,9 @@ class Extension {
// Paths to the content scripts the extension contains.
UserScriptList content_scripts_;
+ // A list of page actions.
+ PageActionMap page_actions_;
+
// Optional absolute path to the directory of NPAPI plugins that the extension
// contains.
FilePath plugins_dir_;
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index c05e793..fb3d354 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -13,14 +13,15 @@
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/common/notification_service.h"
-const char* kOnWindowCreated = "window-created";
-const char* kOnWindowRemoved = "window-removed";
+const char* kOnPageActionExecuted = "page-action-executed";
const char* kOnTabCreated = "tab-created";
const char* kOnTabMoved = "tab-moved";
const char* kOnTabSelectionChanged = "tab-selection-changed";
const char* kOnTabAttached = "tab-attached";
const char* kOnTabDetached = "tab-detached";
const char* kOnTabRemoved = "tab-removed";
+const char* kOnWindowCreated = "window-created";
+const char* kOnWindowRemoved = "window-removed";
ExtensionBrowserEventRouter* ExtensionBrowserEventRouter::GetInstance() {
return Singleton<ExtensionBrowserEventRouter>::get();
@@ -200,3 +201,24 @@ void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents,
bool loading_only) { }
void ExtensionBrowserEventRouter::TabStripEmpty() { }
+
+void ExtensionBrowserEventRouter::PageActionExecuted(Profile *profile,
+ std::string page_action_id,
+ int tab_id,
+ std::string url) {
+ ListValue args;
+ DictionaryValue *object_args = new DictionaryValue();
+ object_args->Set(L"pageActionId", Value::CreateStringValue(page_action_id));
+
+ DictionaryValue *data = new DictionaryValue();
+ data->Set(L"tabId", Value::CreateIntegerValue(tab_id));
+ data->Set(L"tabUrl", Value::CreateStringValue(url));
+ object_args->Set(L"data", data);
+
+ args.Append(object_args);
+
+ std::string json_args;
+ JSONWriter::Write(&args, false, &json_args);
+
+ DispatchEvent(profile, kOnPageActionExecuted, json_args);
+}
diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h
index 29ec398..51099fd 100644
--- a/chrome/browser/extensions/extension_browser_event_router.h
+++ b/chrome/browser/extensions/extension_browser_event_router.h
@@ -22,13 +22,13 @@
class ExtensionBrowserEventRouter : public TabStripModelObserver,
public NotificationObserver {
public:
- // Get Browser-Global instance
+ // Get Browser-Global instance.
static ExtensionBrowserEventRouter* GetInstance();
// Must be called once. Subsequent calls have no effect.
void Init();
- // TabStripModelObserver
+ // TabStripModelObserver.
void TabInsertedAt(TabContents* contents, int index, bool foreground);
void TabClosingAt(TabContents* contents, int index);
void TabDetachedAt(TabContents* contents, int index);
@@ -40,7 +40,13 @@ class ExtensionBrowserEventRouter : public TabStripModelObserver,
void TabChangedAt(TabContents* contents, int index, bool loading_only);
void TabStripEmpty();
- // NotificationObserver
+ // PageActions.
+ void PageActionExecuted(Profile *profile,
+ std::string page_action_id,
+ int tab_id,
+ std::string url);
+
+ // NotificationObserver.
void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 0d45d84..8843ee8 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -11,6 +11,7 @@
#include "base/values.h"
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/extensions/extension_page_actions_module.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
@@ -50,7 +51,7 @@ FactoryRegistry* FactoryRegistry::instance() {
FactoryRegistry::FactoryRegistry() {
// Register all functions here.
- // Tabs
+ // Tabs.
factories_["GetWindows"] = &NewExtensionFunction<GetWindowsFunction>;
factories_["CreateWindow"] = &NewExtensionFunction<CreateWindowFunction>;
factories_["RemoveWindow"] = &NewExtensionFunction<RemoveWindowFunction>;
@@ -62,7 +63,11 @@ FactoryRegistry::FactoryRegistry() {
factories_["MoveTab"] = &NewExtensionFunction<MoveTabFunction>;
factories_["RemoveTab"] = &NewExtensionFunction<RemoveTabFunction>;
- // Bookmarks
+ // Page Actions.
+ factories_["EnablePageAction"] =
+ &NewExtensionFunction<EnablePageActionFunction>;
+
+ // Bookmarks.
factories_["GetBookmarks"] = &NewExtensionFunction<GetBookmarksFunction>;
factories_["GetBookmarkChildren"] =
&NewExtensionFunction<GetBookmarkChildrenFunction>;
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
new file mode 100644
index 0000000..edf08dd
--- /dev/null
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_page_actions_module.h"
+
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/extensions/extension.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/extensions_service.h"
+
+bool EnablePageActionFunction::RunImpl() {
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
+ const ListValue* args = static_cast<const ListValue*>(args_);
+
+ std::string page_action_id;
+ EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &page_action_id));
+ DictionaryValue* action;
+ EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &action));
+
+ int tab_id;
+ EXTENSION_FUNCTION_VALIDATE(action->GetInteger(L"tabId", &tab_id));
+ std::string url;
+ EXTENSION_FUNCTION_VALIDATE(action->GetString(L"url", &url));
+
+ Browser* browser = BrowserList::GetLastActive();
+ if (!browser)
+ return false;
+
+ // HACK: We need to figure out the tab index from the tab_id (pending).
+ // For now we only support page actions in the first tab in the strip (tab 0).
+ int tab_index = 0;
+
+ TabStripModel* tab_strip = browser->tabstrip_model();
+ TabContents* contents = tab_strip->GetTabContentsAt(tab_index);
+
+ // Not needed when we stop hard-coding the tab index.
+ tab_id = ExtensionTabUtil::GetTabId(contents);
+
+ // Find our extension.
+ Extension* extension = NULL;
+ if (profile()->GetExtensionsService()) {
+ const ExtensionList* extensions =
+ profile()->GetExtensionsService()->extensions();
+ for (ExtensionList::const_iterator iter = extensions->begin();
+ iter != extensions->end(); ++iter) {
+ if ((*iter)->id() == extension_id()) {
+ extension = (*iter);
+ break; // Found our extension.
+ }
+ }
+ }
+
+ if (!extension ||
+ !extension->UpdatePageAction(page_action_id, tab_id, GURL(url)))
+ return false;
+
+ // Broadcast notifications when the UI should be updated.
+ contents->NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);
+
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_page_actions_module.h b/chrome/browser/extensions/extension_page_actions_module.h
new file mode 100644
index 0000000..b6e9d87
--- /dev/null
+++ b/chrome/browser/extensions/extension_page_actions_module.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_PAGE_ACTIONS_MODULE_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PAGE_ACTIONS_MODULE_H_
+
+#include "chrome/browser/extensions/extension_function.h"
+
+class EnablePageActionFunction : public SyncExtensionFunction {
+ virtual bool RunImpl();
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PAGE_ACTIONS_MODULE_H_
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 4308c3b..11e4ac1 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -75,7 +75,7 @@ void LocationBarViewGtk::Init() {
gtk_widget_set_app_paintable(alignment_.get(), TRUE);
// Have GTK double buffer around the expose signal.
gtk_widget_set_double_buffered(alignment_.get(), TRUE);
- g_signal_connect(alignment_.get(), "expose-event",
+ g_signal_connect(alignment_.get(), "expose-event",
G_CALLBACK(&HandleExposeThunk), this);
gtk_container_add(GTK_CONTAINER(alignment_.get()),
@@ -189,6 +189,10 @@ void LocationBarViewGtk::UpdateFeedIcon() {
NOTIMPLEMENTED();
}
+void LocationBarViewGtk::UpdatePageActions() {
+ NOTIMPLEMENTED();
+}
+
void LocationBarViewGtk::SaveStateToContents(TabContents* contents) {
NOTIMPLEMENTED();
}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index bf7a8f1..22a7c9c 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -70,6 +70,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
virtual void FocusLocation();
virtual void FocusSearch();
virtual void UpdateFeedIcon();
+ virtual void UpdatePageActions();
virtual void SaveStateToContents(TabContents* contents);
// Translation between a security level and the background color. Both the
diff --git a/chrome/browser/location_bar.h b/chrome/browser/location_bar.h
index a7b0c0d..a1f4898 100644
--- a/chrome/browser/location_bar.h
+++ b/chrome/browser/location_bar.h
@@ -50,6 +50,9 @@ class LocationBar {
// Update the state of the feed icon.
virtual void UpdateFeedIcon() = 0;
+ // Update the state of the page actions.
+ virtual void UpdatePageActions() = 0;
+
// Saves the state of the location bar to the specified TabContents, so that
// it can be restored later. (Done when switching tabs).
virtual void SaveStateToContents(TabContents* contents) = 0;
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 181aafb..4ce03c5 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -97,7 +97,7 @@ class TabContents : public PageNavigator,
INVALIDATE_FAVICON = 4, // The favicon has changed.
INVALIDATE_LOAD = 8, // The loading state has changed.
INVALIDATE_FEEDLIST = 16, // The Atom/RSS feed has changed.
-
+ INVALIDATE_PAGE_ACTIONS = 32, // Page action icons have changed.
// Helper for forcing a refresh.
INVALIDATE_EVERYTHING = 0xFFFFFFFF
};
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index 3311a52..62c7a8d 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -12,6 +12,9 @@
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/command_updater.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
@@ -102,6 +105,10 @@ LocationBarView::LocationBarView(Profile* profile,
}
}
+LocationBarView::~LocationBarView() {
+ DeletePageActionViews();
+}
+
bool LocationBarView::IsInitialized() const {
return location_entry_view_ != NULL;
}
@@ -178,6 +185,7 @@ void LocationBarView::Init() {
void LocationBarView::Update(const TabContents* tab_for_state_restoring) {
SetSecurityIcon(model_->GetIcon());
SetRssIconVisibility(model_->GetFeedList().get());
+ RefreshPageActionViews();
std::wstring info_text, info_tooltip;
SkColor text_color;
model_->GetInfoText(&info_text, &text_color, &info_tooltip);
@@ -193,6 +201,13 @@ void LocationBarView::UpdateFeedIcon() {
SchedulePaint();
}
+void LocationBarView::UpdatePageActions() {
+ RefreshPageActionViews();
+
+ Layout();
+ SchedulePaint();
+}
+
void LocationBarView::Focus() {
::SetFocus(location_entry_->m_hWnd);
}
@@ -346,10 +361,18 @@ void LocationBarView::DoLayout(const bool force_layout) {
int entry_width = width() - (kEntryPadding * 2);
+ gfx::Size page_action_size;
+ for (size_t i = 0; i < page_action_image_views_.size(); i++) {
+ if (page_action_image_views_[i]->IsVisible()) {
+ page_action_size = page_action_image_views_[i]->GetPreferredSize();
+ entry_width -= (page_action_size.width() + kInnerPadding) *
+ page_action_image_views_.size();
+ }
+ }
gfx::Size rss_image_size;
if (rss_image_view_.IsVisible()) {
rss_image_size = rss_image_view_.GetPreferredSize();
- entry_width -= rss_image_size.width();
+ entry_width -= rss_image_size.width() + kInnerPadding;
}
gfx::Size security_image_size;
if (security_image_view_.IsVisible()) {
@@ -383,6 +406,19 @@ void LocationBarView::DoLayout(const bool force_layout) {
}
const int info_label_width = info_label_size.width() ?
info_label_size.width() + kInnerPadding : 0;
+
+ int offset = width() - kEntryPadding - info_label_width -
+ security_image_size.width();
+
+ for (size_t i = 0; i < page_action_image_views_.size(); i++) {
+ if (page_action_image_views_[i]->IsVisible()) {
+ page_action_size = page_action_image_views_[i]->GetPreferredSize();
+ offset -= page_action_size.width();
+ page_action_image_views_[i]->SetBounds(offset, location_y,
+ page_action_size.width(),
+ location_height);
+ }
+ }
if (rss_image_view_.IsVisible()) {
rss_image_view_.SetBounds(width() - kEntryPadding -
info_label_width -
@@ -529,6 +565,64 @@ void LocationBarView::SetRssIconVisibility(FeedList* feeds) {
rss_image_view_.SetVisible(false);
}
+void LocationBarView::DeletePageActionViews() {
+ if (!page_action_image_views_.empty()) {
+ for (size_t i = 0; i < page_action_image_views_.size(); ++i)
+ RemoveChildView(page_action_image_views_[i]);
+ STLDeleteContainerPointers(page_action_image_views_.begin(),
+ page_action_image_views_.end());
+ page_action_image_views_.clear();
+ }
+}
+
+std::vector<PageAction*> LocationBarView::GetPageActions() {
+ std::vector<PageAction*> result;
+
+ // Query the extension system to see how many page actions we have.
+ // TODO(finnur): Sort the page icons in some meaningful way.
+ const ExtensionList* extensions =
+ profile_->GetExtensionsService()->extensions();
+ for (ExtensionList::const_iterator iter = extensions->begin();
+ iter != extensions->end(); ++iter) {
+ const PageActionMap& page_actions = (*iter)->page_actions();
+ for (PageActionMap::const_iterator i(page_actions.begin());
+ i != page_actions.end(); ++i) {
+ result.push_back(i->second);
+ }
+ }
+
+ return result;
+}
+
+void LocationBarView::RefreshPageActionViews() {
+ std::vector<PageAction*> page_actions = GetPageActions();
+
+ // On startup we sometimes haven't loaded any extensions. This makes sure
+ // we catch up when the extensions (and any page actions) load.
+ if (page_actions.size() != page_action_image_views_.size()) {
+ DeletePageActionViews(); // Delete the old views (if any).
+
+ page_action_image_views_.resize(page_actions.size());
+
+ for (size_t i = 0; i < page_actions.size(); ++i) {
+ page_action_image_views_[i] =
+ new PageActionImageView(this, profile_, page_actions[i]);
+ page_action_image_views_[i]->SetVisible(false);
+ page_action_image_views_[i]->SetParentOwned(false);
+ AddChildView(page_action_image_views_[i]);
+ }
+ }
+
+ TabContents* contents = delegate_->GetTabContents();
+ if (!page_action_image_views_.empty() && contents) {
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+ GURL url = GURL(model_->GetText());
+
+ for (size_t i = 0; i < page_action_image_views_.size(); i++)
+ page_action_image_views_[i]->UpdateVisibility(tab_id, url);
+ }
+}
+
void LocationBarView::SetInfoText(const std::wstring& text,
SkColor text_color,
const std::wstring& tooltip_text) {
@@ -840,7 +934,7 @@ class LocationBarView::ShowInfoBubbleTask : public Task {
LocationBarView::LocationBarImageView* image_view_;
bool cancelled_;
- DISALLOW_EVIL_CONSTRUCTORS(ShowInfoBubbleTask);
+ DISALLOW_COPY_AND_ASSIGN(ShowInfoBubbleTask);
};
LocationBarView::ShowInfoBubbleTask::ShowInfoBubbleTask(
@@ -1078,6 +1172,67 @@ void LocationBarView::RssImageView::ShowInfoBubble() {
ShowInfoBubbleImpl(text, text_color);
}
+// PageActionImageView----------------------------------------------------------
+
+LocationBarView::PageActionImageView::PageActionImageView(
+ LocationBarView* owner,
+ Profile* profile,
+ const PageAction* page_action)
+ : owner_(owner),
+ profile_(profile),
+ page_action_(page_action),
+ LocationBarImageView() {
+ // The first thing we do is try to set the image from the PageAction icon.
+ if (page_action->icon_path().empty()) {
+ NOTREACHED();
+ return; // Need icon path to continue.
+ }
+
+ IconManager* im = g_browser_process->icon_manager();
+
+ SkBitmap* icon = im->LookupIcon(page_action->icon_path(),
+ IconLoader::SMALL);
+ if (icon) {
+ ImageView::SetImage(icon);
+ } else {
+ // Ask the Icon Manager to load the icon (happens on the File thread).
+ IconManager::Handle h = im->LoadIcon(page_action->icon_path(),
+ IconLoader::SMALL, &icon_consumer_,
+ NewCallback(this, &LocationBarView::PageActionImageView::OnIconLoaded));
+ }
+}
+
+LocationBarView::PageActionImageView::~PageActionImageView() {
+ icon_consumer_.CancelAllRequests();
+}
+
+bool LocationBarView::PageActionImageView::OnMousePressed(
+ const views::MouseEvent& event) {
+ // Our PageAction icon was clicked on, notify proper authorities.
+ ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+ profile_, page_action_->id(), current_tab_id_, current_url_.spec());
+ return true;
+}
+
+void LocationBarView::PageActionImageView::ShowInfoBubble() {
+ SkColor text_color = SK_ColorBLACK;
+ ShowInfoBubbleImpl(ASCIIToWide(page_action_->tooltip()), text_color);
+}
+
+void LocationBarView::PageActionImageView::UpdateVisibility(
+ int tab_id, GURL url) {
+ current_tab_id_ = tab_id;
+ current_url_ = url;
+
+ SetVisible(page_action_->IsActive(current_tab_id_, current_url_));
+}
+
+void LocationBarView::PageActionImageView::OnIconLoaded(
+ IconManager::Handle handle, SkBitmap* icon) {
+ ImageView::SetImage(icon);
+ owner_->UpdatePageActions();
+}
+
bool LocationBarView::OverrideAccelerator(
const views::Accelerator& accelerator) {
return location_entry_->OverrideAccelerator(accelerator);
diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h
index 7251a85..58be56d 100644
--- a/chrome/browser/views/location_bar_view.h
+++ b/chrome/browser/views/location_bar_view.h
@@ -1,15 +1,17 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H__
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H__
+#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_
#include <string>
+#include <vector>
#include "base/gfx/rect.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
+#include "chrome/browser/icon_manager.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/toolbar_model.h"
@@ -23,6 +25,7 @@
class AutocompletePopupPositioner;
class CommandUpdater;
class GURL;
+class PageAction;
class Profile;
/////////////////////////////////////////////////////////////////////////////
@@ -54,7 +57,7 @@ class LocationBarView : public LocationBar,
Delegate* delegate,
bool popup_window_mode,
AutocompletePopupPositioner* popup_positioner);
- virtual ~LocationBarView() { }
+ virtual ~LocationBarView();
void Init();
@@ -124,6 +127,7 @@ class LocationBarView : public LocationBar,
virtual void FocusLocation();
virtual void FocusSearch();
virtual void UpdateFeedIcon();
+ virtual void UpdatePageActions();
virtual void SaveStateToContents(TabContents* contents);
static const int kVertMargin;
@@ -181,7 +185,7 @@ class LocationBarView : public LocationBar,
Profile* profile_;
- DISALLOW_EVIL_CONSTRUCTORS(SelectedKeywordView);
+ DISALLOW_COPY_AND_ASSIGN(SelectedKeywordView);
};
// KeywordHintView is used to display a hint to the user when the selected
@@ -221,7 +225,7 @@ class LocationBarView : public LocationBar,
Profile* profile_;
- DISALLOW_EVIL_CONSTRUCTORS(KeywordHintView);
+ DISALLOW_COPY_AND_ASSIGN(KeywordHintView);
};
@@ -304,7 +308,7 @@ class LocationBarView : public LocationBar,
ToolbarModel* model_;
- DISALLOW_EVIL_CONSTRUCTORS(SecurityImageView);
+ DISALLOW_COPY_AND_ASSIGN(SecurityImageView);
};
// RssImageView is used to display the RSS icon when the page has a feed that
@@ -331,6 +335,51 @@ class LocationBarView : public LocationBar,
DISALLOW_COPY_AND_ASSIGN(RssImageView);
};
+ // PageActionImageView is used to display the icon for a given PageAction
+ // and notify the extension when the icon is clicked.
+ class PageActionImageView : public LocationBarImageView {
+ public:
+ PageActionImageView(
+ LocationBarView* owner, Profile* profile,
+ const PageAction* page_action);
+ virtual ~PageActionImageView();
+
+ // Overridden from view for the mouse hovering.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+
+ // Overridden from LocationBarImageView.
+ virtual void ShowInfoBubble();
+
+ // Called to notify the PageAction that it should determine whether to be
+ // visible or hidden.
+ void UpdateVisibility(int tab_id, GURL url);
+
+ // Called when the IconManager has loaded our icon.
+ void OnIconLoaded(IconManager::Handle handle, SkBitmap* icon);
+
+ private:
+ // The location bar view that owns us.
+ LocationBarView* owner_;
+
+ // The current profile (not owned by us).
+ Profile* profile_;
+
+ // The PageAction that this view represents. The PageAction is not owned by
+ // us, it resides in the extension of this particular profile.
+ const PageAction* page_action_;
+
+ // The tab id we are currently showing the icon for.
+ int current_tab_id_;
+
+ // The URL we are currently showing the icon for.
+ GURL current_url_;
+
+ // For canceling an in progress icon request.
+ CancelableRequestConsumerT<int, 0> icon_consumer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageActionImageView);
+ };
+
// Both Layout and OnChanged call into this. This updates the contents
// of the 3 views: selected_keyword, keyword_hint and type_search_view. If
// force_layout is true, or one of these views has changed in such a way as
@@ -371,6 +420,17 @@ class LocationBarView : public LocationBar,
// Sets the RSS icon visibility.
void SetRssIconVisibility(FeedList* feeds);
+ // Delete all page action views that we have created.
+ void DeletePageActionViews();
+
+ // Retrieves a vector of all page actions, irrespective of which
+ // extension they belong to.
+ std::vector<PageAction*> LocationBarView::GetPageActions();
+
+ // Update the views for the Page Actions, to reflect state changes for
+ // PageActions.
+ void RefreshPageActionViews();
+
// Sets the text that should be displayed in the info label and its associated
// tooltip text. Call with an empty string if the info label should be
// hidden.
@@ -439,6 +499,9 @@ class LocationBarView : public LocationBar,
// The view that shows the RSS icon when the page has an RSS feed.
RssImageView rss_image_view_;
+ // The page action icon views.
+ std::vector<PageActionImageView*> page_action_image_views_;
+
// A label displayed after the lock icon to show some extra information.
views::Label info_label_;
@@ -453,4 +516,4 @@ class LocationBarView : public LocationBar,
AutocompletePopupPositioner* popup_positioner_;
};
-#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H__
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 3279f60..4a91257 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -272,6 +272,8 @@
'common/os_exchange_data.h',
'common/owned_widget_gtk.cc',
'common/owned_widget_gtk.h',
+ 'common/page_action.h',
+ 'common/page_action.cc',
'common/page_transition_types.h',
'common/page_zoom.h',
'common/platform_util.h',
@@ -726,6 +728,8 @@
'browser/extensions/extension_message_service.h',
'browser/extensions/extension_browser_event_router.cc',
'browser/extensions/extension_browser_event_router.h',
+ 'browser/extensions/extension_page_actions_module.h',
+ 'browser/extensions/extension_page_actions_module.cc',
'browser/extensions/extension_protocols.cc',
'browser/extensions/extension_protocols.h',
'browser/extensions/extension_tabs_module.cc',
diff --git a/chrome/common/common.vcproj b/chrome/common/common.vcproj
index 22258ed..fdf0ed3 100644
--- a/chrome/common/common.vcproj
+++ b/chrome/common/common.vcproj
@@ -650,6 +650,14 @@
>
</File>
<File
+ RelativePath=".\page_action.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\page_action.h"
+ >
+ </File>
+ <File
RelativePath=".\page_transition_types.h"
>
</File>
diff --git a/chrome/common/page_action.cc b/chrome/common/page_action.cc
new file mode 100644
index 0000000..1c8096f
--- /dev/null
+++ b/chrome/common/page_action.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/page_action.h"
+
+PageAction::PageAction()
+ : type_(PERMANENT),
+ active_tab_id_(-1) {
+}
+
+PageAction::~PageAction() {
+}
+
+// TODO(finnur): The tracking of active tab and url probably needs to change
+// but it is hard to test while we are hard coding the tab index, so I'll
+// leave it for later.
+void PageAction::SetActiveTabIdAndUrl(int tab_id, const GURL& url) {
+ active_tab_id_ = tab_id;
+ active_url_ = url;
+}
+
+bool PageAction::IsActive(int tab_id, const GURL& url) const {
+ return !active_url_.is_empty() &&
+ url == active_url_ &&
+ tab_id == active_tab_id_;
+}
diff --git a/chrome/common/page_action.h b/chrome/common/page_action.h
new file mode 100644
index 0000000..ea08da3
--- /dev/null
+++ b/chrome/common/page_action.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_PAGE_ACTION_H_
+#define CHROME_COMMON_PAGE_ACTION_H_
+
+#include <string>
+#include <map>
+
+#include "base/file_path.h"
+#include "googleurl/src/gurl.h"
+
+class PageAction {
+ public:
+ PageAction();
+ virtual ~PageAction();
+
+ typedef enum PageActionType {
+ PERMANENT = 0,
+ TAB = 1,
+ };
+
+ std::string id() const { return id_; }
+ void set_id(std::string id) { id_ = id; }
+
+ PageActionType type() const { return type_; }
+ void set_type(PageActionType type) { type_ = type; }
+
+ std::string extension_id() const { return extension_id_; }
+ void set_extension_id(std::string extension_id) {
+ extension_id_ = extension_id;
+ }
+
+ 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;
+ }
+
+ std::string tooltip() const { return tooltip_; }
+ void set_tooltip(const std::string& tooltip) {
+ tooltip_ = tooltip;
+ }
+
+ // Sets the active tab and url for this PageAction.
+ void SetActiveTabIdAndUrl(int tab_id, const GURL& url);
+ // Returns true if the PageAction is active in the specified |tab_id| & |url|.
+ bool IsActive(int tab_id, const GURL& url) const;
+
+ private:
+ // The id for the PageAction, for example: "RssPageAction".
+ std::string id_;
+
+ // The type of the PageAction.
+ PageActionType type_;
+
+ // The id for the extension this PageAction belongs to (as defined in the
+ // extension manifest).
+ std::string extension_id_;
+
+ // The name of the PageAction.
+ std::string name_;
+
+ // The icon that represents the PageIcon.
+ FilePath icon_path_;
+
+ // The tooltip to show when the mouse hovers over the icon of the page action.
+ std::string tooltip_;
+
+ // The url of the page which the PageAction is currently active in.
+ GURL active_url_;
+
+ // The tab ID for which the PageAction is currently active in.
+ int active_tab_id_;
+};
+
+typedef std::map<std::string, PageAction*> PageActionMap;
+
+#endif // CHROME_COMMON_PAGE_ACTION_H_
diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc
index e635901..172263a 100755
--- a/chrome/renderer/extensions/extension_api_client_unittest.cc
+++ b/chrome/renderer/extensions/extension_api_client_unittest.cc
@@ -237,3 +237,9 @@ TEST_F(ExtensionAPIClientTest, SetBookmarkTitle) {
"{\"id\":42,\"title\":\"x\"}");
}
+TEST_F(ExtensionAPIClientTest, EnablePageAction) {
+ ExpectJsPass("chromium.pageActions.enableForTab("
+ "\"dummy\", {tabId: 0, url: \"http://foo/\"});",
+ "EnablePageAction",
+ "[\"dummy\",{\"tabId\":0,\"url\":\"http://foo/\"}]");
+}
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index beb23b7..cda253b 100755
--- 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. 1 -->
+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 199f436..00bb0fa 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -19,6 +19,7 @@ var chromium;
native function UpdateTab();
native function MoveTab();
native function RemoveTab();
+ native function EnablePageAction();
native function GetBookmarks();
native function GetBookmarkChildren();
native function GetBookmarkTree();
@@ -62,7 +63,7 @@ var chromium;
}
}
- // callback handling
+ // Callback handling.
// TODO(aa): This function should not be publicly exposed. Pass it into V8
// instead and hold one per-context. See the way event_bindings.js works.
var callbacks = [];
@@ -91,7 +92,7 @@ var chromium;
//----------------------------------------------------------------------------
- // Windows
+ // Windows.
chromium.windows = {};
chromium.windows.getWindows = function(windowQuery, callback) {
@@ -237,34 +238,59 @@ var chromium;
chromium.types.pInt
];
- // sends ({tabId, windowId, index}).
- // will *NOT* be followed by tab-attached - it is implied.
+ // Sends ({tabId, windowId, index}).
+ // Will *NOT* be followed by tab-attached - it is implied.
// *MAY* be followed by tab-selection-changed.
chromium.tabs.onTabCreated = new chromium.Event("tab-created");
- // sends ({tabId, windowId, fromIndex, toIndex}).
- // tabs can only "move" within a window.
+ // Wends ({tabId, windowId, fromIndex, toIndex}).
+ // Tabs can only "move" within a window.
chromium.tabs.onTabMoved = new chromium.Event("tab-moved");
- // sends ({tabId, windowId, index}).
+ // Sends ({tabId, windowId, index}).
chromium.tabs.onTabSelectionChanged =
new chromium.Event("tab-selection-changed");
- // sends ({tabId, windowId, index}).
+ // Sends ({tabId, windowId, index}).
// *MAY* be followed by tab-selection-changed.
chromium.tabs.onTabAttached = new chromium.Event("tab-attached");
- // sends ({tabId, windowId, index}).
+ // Sends ({tabId, windowId, index}).
// *WILL* be followed by tab-selection-changed.
chromium.tabs.onTabDetached = new chromium.Event("tab-detached");
- // sends (tabId).
+ // Sends (tabId).
// *WILL* be followed by tab-selection-changed.
- // will *NOT* be followed or preceded by tab-detached.
+ // Will *NOT* be followed or preceded by tab-detached.
chromium.tabs.onTabRemoved = new chromium.Event("tab-removed");
//----------------------------------------------------------------------------
+ // PageActions.
+ chromium.pageActions = {};
+
+ chromium.pageActions.enableForTab = function(pageActionId, action) {
+ validate(arguments, arguments.callee.params);
+ sendRequest(EnablePageAction, [pageActionId, action]);
+ }
+
+ chromium.pageActions.enableForTab.params = [
+ chromium.types.str,
+ {
+ type: "object",
+ properties: {
+ tabId: chromium.types.pInt,
+ url: chromium.types.str
+ },
+ optional: false
+ }
+ ];
+
+ // Sends ({pageActionId, tabId, tabUrl}).
+ chromium.pageActions.onExecute =
+ new chromium.Event("page-action-executed");
+
+ //----------------------------------------------------------------------------
// Bookmarks
chromium.bookmarks = {};
@@ -401,7 +427,7 @@ var chromium;
//----------------------------------------------------------------------------
- // Self
+ // Self.
chromium.self = {};
chromium.self.onConnect = new chromium.Event("channel-connect");
})();
diff --git a/chrome/test/test_location_bar.h b/chrome/test/test_location_bar.h
index 29ba999..f6e94a3 100644
--- a/chrome/test/test_location_bar.h
+++ b/chrome/test/test_location_bar.h
@@ -17,13 +17,13 @@ class TestLocationBar : public LocationBar {
}
void set_input_string(const std::wstring& input_string) {
- input_string_ = input_string;
+ input_string_ = input_string;
}
void set_disposition(WindowOpenDisposition disposition) {
- disposition_ = disposition;
+ disposition_ = disposition;
}
void set_transition(PageTransition::Type transition) {
- transition_ = transition;
+ transition_ = transition;
}
// Overridden from LocationBar:
@@ -34,10 +34,11 @@ class TestLocationBar : public LocationBar {
}
virtual PageTransition::Type GetPageTransition() const { return transition_; }
virtual void AcceptInput() {}
- virtual void AcceptInputWithDisposition(WindowOpenDisposition) {};
+ virtual void AcceptInputWithDisposition(WindowOpenDisposition) {}
virtual void FocusLocation() {}
virtual void FocusSearch() {}
virtual void UpdateFeedIcon() {}
+ virtual void UpdatePageActions() {}
virtual void SaveStateToContents(TabContents* contents) {}
private:
@@ -52,4 +53,4 @@ class TestLocationBar : public LocationBar {
};
-#endif // #ifndef CHROME_TEST_TEST_LOCATION_BAR_H_
+#endif // CHROME_TEST_TEST_LOCATION_BAR_H_