#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
-#include "base/base64.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/api/extension_action/extension_page_actions_api_constants.h"
-#include "chrome/browser/extensions/event_router.h"
-#include "chrome/browser/extensions/extension_action.h"
+#include "chrome/browser/extensions/active_script_controller.h"
#include "chrome/browser/extensions/extension_action_manager.h"
-#include "chrome/browser/extensions/extension_function_registry.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/location_bar_controller.h"
-#include "chrome/browser/extensions/state_store.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/location_bar/location_bar.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/api/extension_action/action_info.h"
#include "chrome/common/render_messages.h"
-#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function_registry.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/image_util.h"
+#include "extensions/browser/notification_types.h"
#include "extensions/common/error_utils.h"
+#include "extensions/common/feature_switch.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
using content::WebContents;
-namespace page_actions_keys = extension_page_actions_api_constants;
-
namespace extensions {
namespace {
-const char kBrowserActionStorageKey[] = "browser_action";
-const char kPopupUrlStorageKey[] = "poupup_url";
-const char kTitleStorageKey[] = "title";
-const char kIconStorageKey[] = "icon";
-const char kBadgeTextStorageKey[] = "badge_text";
-const char kBadgeBackgroundColorStorageKey[] = "badge_background_color";
-const char kBadgeTextColorStorageKey[] = "badge_text_color";
-const char kAppearanceStorageKey[] = "appearance";
-
// Whether the browser action is visible in the toolbar.
const char kBrowserActionVisible[] = "browser_action_visible";
const char kNoExtensionActionError[] =
"This extension has no action specified.";
const char kNoTabError[] = "No tab with id: *.";
-const char kNoPageActionError[] =
- "This extension has no page action specified.";
-const char kUrlNotActiveError[] = "This url is no longer active: *.";
const char kOpenPopupError[] =
"Failed to show popup either because there is an existing popup or another "
"error occurred.";
-const char kInternalError[] = "Internal error.";
-
-struct IconRepresentationInfo {
- // Size as a string that will be used to retrieve representation value from
- // SetIcon function arguments.
- const char* size_string;
- // Scale factor for which the represantion should be used.
- ui::ScaleFactor scale;
-};
-
-const IconRepresentationInfo kIconSizes[] = {
- { "19", ui::SCALE_FACTOR_100P },
- { "38", ui::SCALE_FACTOR_200P }
-};
-
-// Conversion function for reading/writing to storage.
-SkColor RawStringToSkColor(const std::string& str) {
- uint64 value = 0;
- base::StringToUint64(str, &value);
- SkColor color = static_cast<SkColor>(value);
- DCHECK(value == color); // ensure value fits into color's 32 bits
- return color;
-}
-
-// Conversion function for reading/writing to storage.
-std::string SkColorToRawString(SkColor color) {
- return base::Uint64ToString(color);
-}
-
-// Conversion function for reading/writing to storage.
-bool StringToSkBitmap(const std::string& str, SkBitmap* bitmap) {
- // TODO(mpcomplete): Remove the base64 encode/decode step when
- // http://crbug.com/140546 is fixed.
- std::string raw_str;
- if (!base::Base64Decode(str, &raw_str))
- return false;
- IPC::Message bitmap_pickle(raw_str.data(), raw_str.size());
- PickleIterator iter(bitmap_pickle);
- return IPC::ReadParam(&bitmap_pickle, &iter, bitmap);
-}
-
-// Conversion function for reading/writing to storage.
-std::string RepresentationToString(const gfx::ImageSkia& image, float scale) {
- SkBitmap bitmap = image.GetRepresentation(scale).sk_bitmap();
- IPC::Message bitmap_pickle;
- // Clear the header values so they don't vary in serialization.
- bitmap_pickle.SetHeaderValues(0, 0, 0);
- IPC::WriteParam(&bitmap_pickle, bitmap);
- std::string raw_str(static_cast<const char*>(bitmap_pickle.data()),
- bitmap_pickle.size());
- std::string base64_str;
- if (!base::Base64Encode(raw_str, &base64_str))
- return std::string();
- return base64_str;
-}
-
-// Set |action|'s default values to those specified in |dict|.
-void SetDefaultsFromValue(const base::DictionaryValue* dict,
- ExtensionAction* action) {
- const int kTabId = ExtensionAction::kDefaultTabId;
- std::string str_value;
- int int_value;
- SkBitmap bitmap;
- gfx::ImageSkia icon;
-
- if (dict->GetString(kPopupUrlStorageKey, &str_value))
- action->SetPopupUrl(kTabId, GURL(str_value));
- if (dict->GetString(kTitleStorageKey, &str_value))
- action->SetTitle(kTabId, str_value);
- if (dict->GetString(kBadgeTextStorageKey, &str_value))
- action->SetBadgeText(kTabId, str_value);
- if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value))
- action->SetBadgeBackgroundColor(kTabId, RawStringToSkColor(str_value));
- if (dict->GetString(kBadgeTextColorStorageKey, &str_value))
- action->SetBadgeTextColor(kTabId, RawStringToSkColor(str_value));
- if (dict->GetInteger(kAppearanceStorageKey, &int_value))
- action->SetAppearance(kTabId,
- static_cast<ExtensionAction::Appearance>(int_value));
-
- const base::DictionaryValue* icon_value = NULL;
- if (dict->GetDictionary(kIconStorageKey, &icon_value)) {
- for (size_t i = 0; i < arraysize(kIconSizes); i++) {
- if (icon_value->GetString(kIconSizes[i].size_string, &str_value) &&
- StringToSkBitmap(str_value, &bitmap)) {
- CHECK(!bitmap.isNull());
- float scale = ui::GetImageScale(kIconSizes[i].scale);
- icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
- }
- }
- action->SetIcon(kTabId, gfx::Image(icon));
- }
+
+} // namespace
+
+//
+// ExtensionActionAPI::Observer
+//
+
+void ExtensionActionAPI::Observer::OnExtensionActionUpdated(
+ ExtensionAction* extension_action,
+ content::WebContents* web_contents,
+ content::BrowserContext* browser_context) {
}
-// Store |action|'s default values in a DictionaryValue for use in storing to
-// disk.
-scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) {
- const int kTabId = ExtensionAction::kDefaultTabId;
- scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-
- dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec());
- dict->SetString(kTitleStorageKey, action->GetTitle(kTabId));
- dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kTabId));
- dict->SetString(kBadgeBackgroundColorStorageKey,
- SkColorToRawString(action->GetBadgeBackgroundColor(kTabId)));
- dict->SetString(kBadgeTextColorStorageKey,
- SkColorToRawString(action->GetBadgeTextColor(kTabId)));
- dict->SetInteger(kAppearanceStorageKey,
- action->GetIsVisible(kTabId) ?
- ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE);
-
- gfx::ImageSkia icon = action->GetExplicitlySetIcon(kTabId);
- if (!icon.isNull()) {
- base::DictionaryValue* icon_value = new base::DictionaryValue();
- for (size_t i = 0; i < arraysize(kIconSizes); i++) {
- float scale = ui::GetImageScale(kIconSizes[i].scale);
- if (icon.HasRepresentation(scale)) {
- icon_value->SetString(
- kIconSizes[i].size_string,
- RepresentationToString(icon, scale));
- }
- }
- dict->Set(kIconStorageKey, icon_value);
- }
- return dict.Pass();
+void ExtensionActionAPI::Observer::OnPageActionsUpdated(
+ content::WebContents* web_contents) {
}
-} // namespace
+void ExtensionActionAPI::Observer::OnExtensionActionAPIShuttingDown() {
+}
+
+ExtensionActionAPI::Observer::~Observer() {
+}
//
// ExtensionActionAPI
//
-static base::LazyInstance<ProfileKeyedAPIFactory<ExtensionActionAPI> >
+static base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionActionAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;
-ExtensionActionAPI::ExtensionActionAPI(Profile* profile) {
+ExtensionActionAPI::ExtensionActionAPI(content::BrowserContext* context)
+ : browser_context_(context) {
ExtensionFunctionRegistry* registry =
ExtensionFunctionRegistry::GetInstance();
registry->RegisterFunction<BrowserActionOpenPopupFunction>();
// Page Actions
- registry->RegisterFunction<EnablePageActionsFunction>();
- registry->RegisterFunction<DisablePageActionsFunction>();
registry->RegisterFunction<PageActionShowFunction>();
registry->RegisterFunction<PageActionHideFunction>();
registry->RegisterFunction<PageActionSetIconFunction>();
registry->RegisterFunction<PageActionSetPopupFunction>();
registry->RegisterFunction<PageActionGetTitleFunction>();
registry->RegisterFunction<PageActionGetPopupFunction>();
-
- // Script Badges
- registry->RegisterFunction<ScriptBadgeGetAttentionFunction>();
- registry->RegisterFunction<ScriptBadgeGetPopupFunction>();
- registry->RegisterFunction<ScriptBadgeSetPopupFunction>();
}
ExtensionActionAPI::~ExtensionActionAPI() {
}
// static
-ProfileKeyedAPIFactory<ExtensionActionAPI>*
+BrowserContextKeyedAPIFactory<ExtensionActionAPI>*
ExtensionActionAPI::GetFactoryInstance() {
- return &g_factory.Get();
+ return g_factory.Pointer();
}
// static
-ExtensionActionAPI* ExtensionActionAPI::Get(Profile* profile) {
- return ProfileKeyedAPIFactory<ExtensionActionAPI>::GetForProfile(profile);
+ExtensionActionAPI* ExtensionActionAPI::Get(content::BrowserContext* context) {
+ return BrowserContextKeyedAPIFactory<ExtensionActionAPI>::Get(context);
}
// static
kBrowserActionVisible,
new base::FundamentalValue(visible));
content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
+ NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
content::Source<ExtensionPrefs>(prefs),
content::Details<const std::string>(&extension_id));
}
-// static
-void ExtensionActionAPI::BrowserActionExecuted(
- Profile* profile,
- const ExtensionAction& browser_action,
- WebContents* web_contents) {
- ExtensionActionExecuted(profile, browser_action, web_contents);
+void ExtensionActionAPI::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
}
-// static
-void ExtensionActionAPI::PageActionExecuted(Profile* profile,
- const ExtensionAction& page_action,
- int tab_id,
- const std::string& url,
- int button) {
- DispatchOldPageActionEvent(profile, page_action.extension_id(),
- page_action.id(), tab_id, url, button);
- WebContents* web_contents = NULL;
- if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(),
- NULL, NULL, &web_contents, NULL)) {
- return;
+void ExtensionActionAPI::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+ExtensionAction::ShowAction ExtensionActionAPI::ExecuteExtensionAction(
+ const Extension* extension,
+ Browser* browser,
+ bool grant_active_tab_permissions) {
+ content::WebContents* web_contents =
+ browser->tab_strip_model()->GetActiveWebContents();
+ if (!web_contents)
+ return ExtensionAction::ACTION_NONE;
+
+ int tab_id = SessionTabHelper::IdForTab(web_contents);
+
+ ActiveScriptController* active_script_controller =
+ ActiveScriptController::GetForWebContents(web_contents);
+ bool has_pending_scripts = false;
+ if (active_script_controller &&
+ active_script_controller->WantsToRun(extension)) {
+ has_pending_scripts = true;
}
- ExtensionActionExecuted(profile, page_action, web_contents);
+
+ // Grant active tab if appropriate.
+ if (grant_active_tab_permissions) {
+ TabHelper::FromWebContents(web_contents)->active_tab_permission_granter()->
+ GrantIfRequested(extension);
+ }
+
+ // If this was a request to run a script, it will have been run once active
+ // tab was granted. Return without executing the action, since we should only
+ // run pending scripts OR the extension action, not both.
+ if (has_pending_scripts)
+ return ExtensionAction::ACTION_NONE;
+
+ ExtensionAction* extension_action =
+ ExtensionActionManager::Get(browser_context_)->GetExtensionAction(
+ *extension);
+
+ // Anything that gets here should have a page or browser action.
+ DCHECK(extension_action);
+ if (!extension_action->GetIsVisible(tab_id))
+ return ExtensionAction::ACTION_NONE;
+
+ if (extension_action->HasPopup(tab_id))
+ return ExtensionAction::ACTION_SHOW_POPUP;
+
+ ExtensionActionExecuted(*extension_action, web_contents);
+ return ExtensionAction::ACTION_NONE;
}
-// static
-void ExtensionActionAPI::ScriptBadgeExecuted(
- Profile* profile,
- const ExtensionAction& script_badge,
- int tab_id) {
- WebContents* web_contents = NULL;
- if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(),
- NULL, NULL, &web_contents, NULL)) {
- return;
+bool ExtensionActionAPI::ShowExtensionActionPopup(
+ const Extension* extension,
+ Browser* browser,
+ bool grant_active_tab_permissions) {
+ ExtensionAction* extension_action =
+ ExtensionActionManager::Get(browser_context_)->GetExtensionAction(
+ *extension);
+ if (!extension_action)
+ return false;
+
+ if (extension_action->action_type() == ActionInfo::TYPE_PAGE &&
+ !FeatureSwitch::extension_action_redesign()->IsEnabled()) {
+ // We show page actions in the location bar unless the new toolbar is
+ // enabled.
+ return browser->window()->GetLocationBar()->ShowPageActionPopup(
+ extension, grant_active_tab_permissions);
+ } else {
+ return ExtensionToolbarModel::Get(browser->profile())->
+ ShowExtensionActionPopup(
+ extension, browser, grant_active_tab_permissions);
+ }
+}
+
+bool ExtensionActionAPI::ExtensionWantsToRun(
+ const Extension* extension, content::WebContents* web_contents) {
+ // An extension wants to act if it has a visible page action on the given
+ // page...
+ ExtensionAction* page_action =
+ ExtensionActionManager::Get(browser_context_)->GetPageAction(*extension);
+ if (page_action &&
+ page_action->GetIsVisible(SessionTabHelper::IdForTab(web_contents)))
+ return true;
+
+ // ... Or if it has pending scripts that need approval for execution.
+ ActiveScriptController* active_script_controller =
+ ActiveScriptController::GetForWebContents(web_contents);
+ if (active_script_controller &&
+ active_script_controller->WantsToRun(extension))
+ return true;
+
+ return false;
+}
+
+void ExtensionActionAPI::NotifyChange(ExtensionAction* extension_action,
+ content::WebContents* web_contents,
+ content::BrowserContext* context) {
+ FOR_EACH_OBSERVER(
+ Observer,
+ observers_,
+ OnExtensionActionUpdated(extension_action, web_contents, context));
+
+ if (extension_action->action_type() == ActionInfo::TYPE_PAGE)
+ NotifyPageActionsChanged(web_contents);
+}
+
+void ExtensionActionAPI::ClearAllValuesForTab(
+ content::WebContents* web_contents) {
+ DCHECK(web_contents);
+ int tab_id = SessionTabHelper::IdForTab(web_contents);
+ content::BrowserContext* browser_context = web_contents->GetBrowserContext();
+ const ExtensionSet& enabled_extensions =
+ ExtensionRegistry::Get(browser_context_)->enabled_extensions();
+ ExtensionActionManager* action_manager =
+ ExtensionActionManager::Get(browser_context_);
+
+ for (ExtensionSet::const_iterator iter = enabled_extensions.begin();
+ iter != enabled_extensions.end(); ++iter) {
+ ExtensionAction* extension_action =
+ action_manager->GetExtensionAction(**iter);
+ if (extension_action) {
+ extension_action->ClearAllValuesForTab(tab_id);
+ NotifyChange(extension_action, web_contents, browser_context);
+ }
}
- ExtensionActionExecuted(profile, script_badge, web_contents);
}
-// static
void ExtensionActionAPI::DispatchEventToExtension(
- Profile* profile,
+ content::BrowserContext* context,
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args) {
- if (!extensions::ExtensionSystem::Get(profile)->event_router())
+ if (!EventRouter::Get(context))
return;
scoped_ptr<Event> event(new Event(event_name, event_args.Pass()));
- event->restrict_to_profile = profile;
+ event->restrict_to_browser_context = context;
event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
- ExtensionSystem::Get(profile)->event_router()->
- DispatchEventToExtension(extension_id, event.Pass());
-}
-
-// static
-void ExtensionActionAPI::DispatchOldPageActionEvent(
- Profile* profile,
- const std::string& extension_id,
- const std::string& page_action_id,
- int tab_id,
- const std::string& url,
- int button) {
- scoped_ptr<base::ListValue> args(new base::ListValue());
- args->Append(new base::StringValue(page_action_id));
-
- DictionaryValue* data = new DictionaryValue();
- data->Set(page_actions_keys::kTabIdKey, new base::FundamentalValue(tab_id));
- data->Set(page_actions_keys::kTabUrlKey, new base::StringValue(url));
- data->Set(page_actions_keys::kButtonKey,
- new base::FundamentalValue(button));
- args->Append(data);
-
- DispatchEventToExtension(profile, extension_id, "pageActions", args.Pass());
+ EventRouter::Get(context)
+ ->DispatchEventToExtension(extension_id, event.Pass());
}
-// static
void ExtensionActionAPI::ExtensionActionExecuted(
- Profile* profile,
const ExtensionAction& extension_action,
WebContents* web_contents) {
const char* event_name = NULL;
case ActionInfo::TYPE_PAGE:
event_name = "pageAction.onClicked";
break;
- case ActionInfo::TYPE_SCRIPT_BADGE:
- event_name = "scriptBadge.onClicked";
- break;
case ActionInfo::TYPE_SYSTEM_INDICATOR:
// The System Indicator handles its own clicks.
break;
if (event_name) {
scoped_ptr<base::ListValue> args(new base::ListValue());
- DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue(
- web_contents);
+ base::DictionaryValue* tab_value =
+ ExtensionTabUtil::CreateTabValue(web_contents);
args->Append(tab_value);
- DispatchEventToExtension(profile,
- extension_action.extension_id(),
- event_name,
- args.Pass());
- }
-}
-
-//
-// ExtensionActionStorageManager
-//
-
-ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile)
- : profile_(profile) {
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
- content::NotificationService::AllBrowserContextsAndSources());
-
- StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
- if (storage)
- storage->RegisterKey(kBrowserActionStorageKey);
-}
-
-ExtensionActionStorageManager::~ExtensionActionStorageManager() {
-}
-
-void ExtensionActionStorageManager::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_EXTENSION_LOADED: {
- const Extension* extension =
- content::Details<const Extension>(details).ptr();
- if (!ExtensionActionManager::Get(profile_)->
- GetBrowserAction(*extension)) {
- break;
- }
-
- StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
- if (storage) {
- storage->GetExtensionValue(extension->id(), kBrowserActionStorageKey,
- base::Bind(&ExtensionActionStorageManager::ReadFromStorage,
- AsWeakPtr(), extension->id()));
- }
- break;
- }
- case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED: {
- ExtensionAction* extension_action =
- content::Source<ExtensionAction>(source).ptr();
- Profile* profile = content::Details<Profile>(details).ptr();
- if (profile != profile_)
- break;
-
- extension_action->set_has_changed(true);
- WriteToStorage(extension_action);
- break;
- }
- default:
- NOTREACHED();
- break;
+ DispatchEventToExtension(
+ web_contents->GetBrowserContext(),
+ extension_action.extension_id(),
+ event_name,
+ args.Pass());
}
}
-void ExtensionActionStorageManager::WriteToStorage(
- ExtensionAction* extension_action) {
- StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
- if (!storage)
- return;
-
- scoped_ptr<base::DictionaryValue> defaults =
- DefaultsToValue(extension_action);
- storage->SetExtensionValue(extension_action->extension_id(),
- kBrowserActionStorageKey,
- defaults.PassAs<base::Value>());
-}
-
-void ExtensionActionStorageManager::ReadFromStorage(
- const std::string& extension_id, scoped_ptr<base::Value> value) {
- const Extension* extension =
- ExtensionSystem::Get(profile_)->extension_service()->
- extensions()->GetByID(extension_id);
- if (!extension)
+void ExtensionActionAPI::NotifyPageActionsChanged(
+ content::WebContents* web_contents) {
+ Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+ if (!browser)
return;
-
- ExtensionAction* browser_action =
- ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension);
- CHECK(browser_action);
-
- // Don't load values from storage if the extension has updated a value
- // already. The extension may have only updated some of the values, but
- // this is a good first approximation. If the extension is doing stuff
- // to the browser action, we can assume it is ready to take over.
- if (browser_action->has_changed())
+ LocationBar* location_bar =
+ browser->window() ? browser->window()->GetLocationBar() : NULL;
+ if (!location_bar)
return;
+ location_bar->UpdatePageActions();
- const base::DictionaryValue* dict = NULL;
- if (!value.get() || !value->GetAsDictionary(&dict))
- return;
+ FOR_EACH_OBSERVER(Observer, observers_, OnPageActionsUpdated(web_contents));
+}
- SetDefaultsFromValue(dict, browser_action);
+void ExtensionActionAPI::Shutdown() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnExtensionActionAPIShuttingDown());
}
//
ExtensionActionFunction::~ExtensionActionFunction() {
}
-bool ExtensionActionFunction::RunImpl() {
+bool ExtensionActionFunction::RunSync() {
ExtensionActionManager* manager = ExtensionActionManager::Get(GetProfile());
- const Extension* extension = GetExtension();
- if (StartsWithASCII(name(), "scriptBadge.", false)) {
- extension_action_ = manager->GetScriptBadge(*extension);
- } else if (StartsWithASCII(name(), "systemIndicator.", false)) {
- extension_action_ = manager->GetSystemIndicator(*extension);
+ if (StartsWithASCII(name(), "systemIndicator.", false)) {
+ extension_action_ = manager->GetSystemIndicator(*extension());
} else {
- extension_action_ = manager->GetBrowserAction(*extension);
+ extension_action_ = manager->GetBrowserAction(*extension());
if (!extension_action_) {
- extension_action_ = manager->GetPageAction(*extension);
+ extension_action_ = manager->GetPageAction(*extension());
}
}
if (!extension_action_) {
return true;
switch (first_arg->GetType()) {
- case Value::TYPE_INTEGER:
+ case base::Value::TYPE_INTEGER:
CHECK(first_arg->GetAsInteger(&tab_id_));
break;
- case Value::TYPE_DICTIONARY: {
+ case base::Value::TYPE_DICTIONARY: {
// Found the details argument.
details_ = static_cast<base::DictionaryValue*>(first_arg);
// Still need to check for the tabId within details.
base::Value* tab_id_value = NULL;
if (details_->Get("tabId", &tab_id_value)) {
switch (tab_id_value->GetType()) {
- case Value::TYPE_NULL:
+ case base::Value::TYPE_NULL:
// OK; tabId is optional, leave it default.
return true;
- case Value::TYPE_INTEGER:
+ case base::Value::TYPE_INTEGER:
CHECK(tab_id_value->GetAsInteger(&tab_id_));
return true;
default:
break;
}
- case Value::TYPE_NULL:
+ case base::Value::TYPE_NULL:
// The tabId might be an optional argument.
break;
}
void ExtensionActionFunction::NotifyChange() {
- switch (extension_action_->action_type()) {
- case ActionInfo::TYPE_BROWSER:
- case ActionInfo::TYPE_PAGE:
- if (ExtensionActionManager::Get(GetProfile())
- ->GetBrowserAction(*extension_.get())) {
- NotifyBrowserActionChange();
- } else if (ExtensionActionManager::Get(GetProfile())
- ->GetPageAction(*extension_.get())) {
- NotifyLocationBarChange();
- }
- return;
- case ActionInfo::TYPE_SCRIPT_BADGE:
- NotifyLocationBarChange();
- return;
- case ActionInfo::TYPE_SYSTEM_INDICATOR:
- NotifySystemIndicatorChange();
- return;
- }
- NOTREACHED();
-}
-
-void ExtensionActionFunction::NotifyBrowserActionChange() {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
- content::Source<ExtensionAction>(extension_action_),
- content::Details<Profile>(GetProfile()));
-}
-
-void ExtensionActionFunction::NotifyLocationBarChange() {
- TabHelper::FromWebContents(contents_)->
- location_bar_controller()->NotifyChange();
-}
-
-void ExtensionActionFunction::NotifySystemIndicatorChange() {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
- content::Source<Profile>(GetProfile()),
- content::Details<ExtensionAction>(extension_action_));
-}
-
-// static
-bool ExtensionActionFunction::ParseCSSColorString(
- const std::string& color_string,
- SkColor* result) {
- std::string formatted_color = "#";
- // Check the string for incorrect formatting.
- if (color_string[0] != '#')
- return false;
-
- // Convert the string from #FFF format to #FFFFFF format.
- if (color_string.length() == 4) {
- for (size_t i = 1; i < color_string.length(); i++) {
- formatted_color += color_string[i];
- formatted_color += color_string[i];
- }
- } else {
- formatted_color = color_string;
- }
-
- if (formatted_color.length() != 7)
- return false;
-
- // Convert the string to an integer and make sure it is in the correct value
- // range.
- int color_ints[3] = {0};
- for (int i = 0; i < 3; i++) {
- if (!base::HexStringToInt(formatted_color.substr(1 + (2 * i), 2),
- color_ints + i))
- return false;
- if (color_ints[i] > 255 || color_ints[i] < 0)
- return false;
- }
-
- *result = SkColorSetARGB(255, color_ints[0], color_ints[1], color_ints[2]);
- return true;
+ ExtensionActionAPI::Get(GetProfile())->NotifyChange(
+ extension_action_, contents_, GetProfile());
}
bool ExtensionActionFunction::SetVisible(bool visible) {
if (extension_action_->GetIsVisible(tab_id_) == visible)
return true;
- extension_action_->SetAppearance(
- tab_id_, visible ? ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE);
+ extension_action_->SetIsVisible(tab_id_, visible);
NotifyChange();
return true;
}
-TabHelper& ExtensionActionFunction::tab_helper() const {
- CHECK(contents_);
- return *TabHelper::FromWebContents(contents_);
-}
-
bool ExtensionActionShowFunction::RunExtensionAction() {
return SetVisible(true);
}
int icon_index;
if (details_->GetDictionary("imageData", &canvas_set)) {
gfx::ImageSkia icon;
- // Extract icon representations from the ImageDataSet dictionary.
- for (size_t i = 0; i < arraysize(kIconSizes); i++) {
- base::BinaryValue* binary;
- if (canvas_set->GetBinary(kIconSizes[i].size_string, &binary)) {
- IPC::Message pickle(binary->GetBuffer(), binary->GetSize());
- PickleIterator iter(pickle);
- SkBitmap bitmap;
- EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&pickle, &iter, &bitmap));
- CHECK(!bitmap.isNull());
- float scale = ui::GetImageScale(kIconSizes[i].scale);
- icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
- }
- }
+
+ EXTENSION_FUNCTION_VALIDATE(
+ ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon));
extension_action_->SetIcon(tab_id_, gfx::Image(icon));
} else if (details_->GetInteger("iconIndex", &icon_index)) {
GURL popup_url;
if (!popup_string.empty())
- popup_url = GetExtension()->GetResourceURL(popup_string);
+ popup_url = extension()->GetResourceURL(popup_string);
extension_action_->SetPopupUrl(tab_id_, popup_url);
NotifyChange();
bool ExtensionActionSetBadgeBackgroundColorFunction::RunExtensionAction() {
EXTENSION_FUNCTION_VALIDATE(details_);
- Value* color_value = NULL;
+ base::Value* color_value = NULL;
EXTENSION_FUNCTION_VALIDATE(details_->Get("color", &color_value));
SkColor color = 0;
- if (color_value->IsType(Value::TYPE_LIST)) {
+ if (color_value->IsType(base::Value::TYPE_LIST)) {
base::ListValue* list = NULL;
EXTENSION_FUNCTION_VALIDATE(details_->GetList("color", &list));
EXTENSION_FUNCTION_VALIDATE(list->GetSize() == 4);
color = SkColorSetARGB(color_array[3], color_array[0],
color_array[1], color_array[2]);
- } else if (color_value->IsType(Value::TYPE_STRING)) {
+ } else if (color_value->IsType(base::Value::TYPE_STRING)) {
std::string color_string;
EXTENSION_FUNCTION_VALIDATE(details_->GetString("color", &color_string));
- if (!ParseCSSColorString(color_string, &color))
+ if (!image_util::ParseCSSColorString(color_string, &color))
return false;
}
: response_sent_(false) {
}
-bool BrowserActionOpenPopupFunction::RunImpl() {
- ExtensionToolbarModel* model = extensions::ExtensionSystem::Get(GetProfile())
- ->extension_service()
- ->toolbar_model();
- if (!model) {
- error_ = kInternalError;
- return false;
- }
-
- if (!model->ShowBrowserActionPopup(extension_)) {
+bool BrowserActionOpenPopupFunction::RunAsync() {
+ // We only allow the popup in the active window.
+ Browser* browser = chrome::FindLastActiveWithProfile(
+ GetProfile(), chrome::GetActiveDesktop());
+
+ // If there's no active browser, or the Toolbar isn't visible, abort.
+ // Otherwise, try to open a popup in the active browser.
+ // TODO(justinlin): Remove toolbar check when http://crbug.com/308645 is
+ // fixed.
+ if (!browser ||
+ !browser->window()->IsActive() ||
+ !browser->window()->IsToolbarVisible() ||
+ !ExtensionActionAPI::Get(GetProfile())->ShowExtensionActionPopup(
+ extension_.get(), browser, false)) {
error_ = kOpenPopupError;
return false;
}
registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
+ NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
content::Source<Profile>(GetProfile()));
// Set a timeout for waiting for the notification that the popup is loaded.
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, type);
+ DCHECK_EQ(NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, type);
if (response_sent_)
return;
registrar_.RemoveAll();
}
-//
-// ScriptBadgeGetAttentionFunction
-//
-
-ScriptBadgeGetAttentionFunction::~ScriptBadgeGetAttentionFunction() {}
-
-bool ScriptBadgeGetAttentionFunction::RunExtensionAction() {
- tab_helper().location_bar_controller()->GetAttentionFor(extension_id());
- return true;
-}
-
} // namespace extensions
-
-//
-// PageActionsFunction (deprecated)
-//
-
-PageActionsFunction::PageActionsFunction() {
-}
-
-PageActionsFunction::~PageActionsFunction() {
-}
-
-bool PageActionsFunction::SetPageActionEnabled(bool enable) {
- std::string extension_action_id;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_action_id));
- DictionaryValue* action = NULL;
- EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &action));
-
- int tab_id;
- EXTENSION_FUNCTION_VALIDATE(action->GetInteger(
- page_actions_keys::kTabIdKey, &tab_id));
- std::string url;
- EXTENSION_FUNCTION_VALIDATE(action->GetString(
- page_actions_keys::kUrlKey, &url));
-
- std::string title;
- if (enable) {
- if (action->HasKey(page_actions_keys::kTitleKey))
- EXTENSION_FUNCTION_VALIDATE(action->GetString(
- page_actions_keys::kTitleKey, &title));
- }
-
- ExtensionAction* page_action = extensions::ExtensionActionManager::Get(
- GetProfile())->GetPageAction(*GetExtension());
- if (!page_action) {
- error_ = extensions::kNoPageActionError;
- return false;
- }
-
- // Find the WebContents that contains this tab id.
- WebContents* contents = NULL;
- bool result = ExtensionTabUtil::GetTabById(
- tab_id, GetProfile(), include_incognito(), NULL, NULL, &contents, NULL);
- if (!result || !contents) {
- error_ = extensions::ErrorUtils::FormatErrorMessage(
- extensions::kNoTabError, base::IntToString(tab_id));
- return false;
- }
-
- // Make sure the URL hasn't changed.
- content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
- if (!entry || url != entry->GetURL().spec()) {
- error_ = extensions::ErrorUtils::FormatErrorMessage(
- extensions::kUrlNotActiveError, url);
- return false;
- }
-
- // Set visibility and broadcast notifications that the UI should be updated.
- page_action->SetAppearance(
- tab_id, enable ? ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE);
- page_action->SetTitle(tab_id, title);
- extensions::TabHelper::FromWebContents(contents)->
- location_bar_controller()->NotifyChange();
-
- return true;
-}
-
-bool EnablePageActionsFunction::RunImpl() {
- return SetPageActionEnabled(true);
-}
-
-bool DisablePageActionsFunction::RunImpl() {
- return SetPageActionEnabled(false);
-}