Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/extension_action/extension_actions_api.h " | 5 #include "chrome/browser/extensions/api/extension_action/extension_actions_api.h " |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | |
| 9 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| 10 #include "base/string_piece.h" | 11 #include "base/string_piece.h" |
| 11 #include "base/values.h" | 12 #include "base/values.h" |
| 12 #include "chrome/browser/extensions/api/extension_action/extension_page_actions_ api_constants.h" | 13 #include "chrome/browser/extensions/api/extension_action/extension_page_actions_ api_constants.h" |
| 13 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 14 #include "chrome/browser/extensions/tab_helper.h" | 15 #include "chrome/browser/extensions/tab_helper.h" |
|
Yoyo Zhou
2012/08/08 01:21:06
nit: not in sorted order
Matt Perry
2012/08/08 01:40:08
Done.
| |
| 16 #include "chrome/browser/extensions/extension_system.h" | |
| 15 #include "chrome/browser/extensions/extension_tab_util.h" | 17 #include "chrome/browser/extensions/extension_tab_util.h" |
| 16 #include "chrome/browser/extensions/location_bar_controller.h" | 18 #include "chrome/browser/extensions/location_bar_controller.h" |
| 19 #include "chrome/browser/extensions/state_store.h" | |
| 17 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 21 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 19 #include "chrome/common/chrome_notification_types.h" | 22 #include "chrome/common/chrome_notification_types.h" |
| 20 #include "chrome/common/extensions/extension.h" | 23 #include "chrome/common/extensions/extension.h" |
| 21 #include "chrome/common/extensions/extension_action.h" | 24 #include "chrome/common/extensions/extension_action.h" |
| 22 #include "chrome/common/extensions/extension_error_utils.h" | 25 #include "chrome/common/extensions/extension_error_utils.h" |
| 23 #include "chrome/common/render_messages.h" | 26 #include "chrome/common/render_messages.h" |
| 24 #include "content/public/browser/navigation_entry.h" | 27 #include "content/public/browser/navigation_entry.h" |
| 25 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
| 26 | 29 |
| 27 namespace { | 30 namespace { |
| 28 | 31 |
| 32 const char kBrowserActionStorageKey[] = "browser_action"; | |
| 33 const char kPopupUrlStorageKey[] = "poupup_url"; | |
| 34 const char kTitleStorageKey[] = "title"; | |
| 35 const char kIconStorageKey[] = "icon"; | |
| 36 const char kBadgeTextStorageKey[] = "badge_text"; | |
| 37 const char kBadgeBackgroundColorStorageKey[] = "badge_background_color"; | |
| 38 const char kBadgeTextColorStorageKey[] = "badge_text_color"; | |
| 39 const char kAppearanceStorageKey[] = "appearance"; | |
| 40 | |
| 29 // Errors. | 41 // Errors. |
| 30 const char kNoExtensionActionError[] = | 42 const char kNoExtensionActionError[] = |
| 31 "This extension has no action specified."; | 43 "This extension has no action specified."; |
| 32 const char kNoTabError[] = "No tab with id: *."; | 44 const char kNoTabError[] = "No tab with id: *."; |
| 33 const char kIconIndexOutOfBounds[] = "Page action icon index out of bounds."; | 45 const char kIconIndexOutOfBounds[] = "Page action icon index out of bounds."; |
| 34 | 46 |
| 35 } | 47 // Conversion function for reading/writing to storage. |
| 48 SkColor RawStringToSkColor(const std::string& str) { | |
| 49 uint64 value = 0; | |
| 50 base::StringToUint64(str, &value); | |
|
Yoyo Zhou
2012/08/08 01:21:06
Why not check that this returns true?
Matt Perry
2012/08/08 01:40:08
We'll return 0 either way.
| |
| 51 SkColor color = static_cast<SkColor>(value); | |
| 52 DCHECK(value == color); | |
|
Yoyo Zhou
2012/08/08 01:21:06
This seems like overkill.
Matt Perry
2012/08/08 01:40:08
SkColor is 32-bit. I want to make sure the int con
| |
| 53 return color; | |
| 54 } | |
| 55 | |
| 56 // Conversion function for reading/writing to storage. | |
| 57 std::string SkColorToRawString(SkColor color) { | |
| 58 return base::Uint64ToString(color); | |
| 59 } | |
| 60 | |
| 61 // Conversion function for reading/writing to storage. | |
| 62 bool StringToSkBitmap(const std::string& str, SkBitmap* bitmap) { | |
| 63 // TODO(mpcomplete): Our state store can't hold binary data. | |
|
Yoyo Zhou
2012/08/08 01:21:06
nit: rephrase this as an action you could do.
Matt Perry
2012/08/08 01:40:08
Done.
| |
| 64 std::string raw_str; | |
| 65 if (!base::Base64Decode(str, &raw_str)) | |
| 66 return false; | |
| 67 IPC::Message bitmap_pickle(raw_str.data(), raw_str.size()); | |
| 68 PickleIterator iter(bitmap_pickle); | |
| 69 return IPC::ReadParam(&bitmap_pickle, &iter, bitmap); | |
| 70 } | |
| 71 | |
| 72 // Conversion function for reading/writing to storage. | |
| 73 std::string ImageToString(const gfx::Image& image) { | |
| 74 IPC::Message bitmap_pickle; | |
| 75 IPC::WriteParam(&bitmap_pickle, image.AsBitmap()); | |
| 76 std::string raw_str(static_cast<const char*>(bitmap_pickle.data()), | |
| 77 bitmap_pickle.size()); | |
| 78 std::string base64_str; | |
| 79 if (!base::Base64Encode(raw_str, &base64_str)) | |
| 80 return std::string(); | |
| 81 return base64_str; | |
| 82 } | |
| 83 | |
| 84 // Set |action|'s default values to those specified in |dict|. | |
| 85 void DefaultsFromValue(const base::DictionaryValue* dict, | |
|
Yoyo Zhou
2012/08/08 01:21:06
"SetDefaultsFromValue"?
Matt Perry
2012/08/08 01:40:08
Done.
| |
| 86 ExtensionAction* action) { | |
| 87 const int kTabId = ExtensionAction::kDefaultTabId; | |
| 88 std::string str_value; | |
| 89 int int_value; | |
| 90 SkBitmap bitmap; | |
| 91 | |
| 92 if (dict->GetString(kPopupUrlStorageKey, &str_value)) | |
| 93 action->SetPopupUrl(kTabId, GURL(str_value)); | |
| 94 if (dict->GetString(kTitleStorageKey, &str_value)) | |
| 95 action->SetTitle(kTabId, str_value); | |
| 96 if (dict->GetString(kBadgeTextStorageKey, &str_value)) | |
| 97 action->SetBadgeText(kTabId, str_value); | |
| 98 if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value)) | |
| 99 action->SetBadgeBackgroundColor(kTabId, RawStringToSkColor(str_value)); | |
| 100 if (dict->GetString(kBadgeTextColorStorageKey, &str_value)) | |
| 101 action->SetBadgeTextColor(kTabId, RawStringToSkColor(str_value)); | |
| 102 if (dict->GetInteger(kAppearanceStorageKey, &int_value)) | |
| 103 action->SetAppearance(kTabId, | |
| 104 static_cast<ExtensionAction::Appearance>(int_value)); | |
| 105 if (dict->GetString(kIconStorageKey, &str_value) && | |
| 106 StringToSkBitmap(str_value, &bitmap)) | |
| 107 action->SetIcon(kTabId, bitmap); | |
| 108 } | |
| 109 | |
| 110 // Store |action|'s default values in a DictionaryValue for use in storing to | |
| 111 // disk. | |
| 112 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) { | |
| 113 const int kTabId = ExtensionAction::kDefaultTabId; | |
| 114 scoped_ptr<base::DictionaryValue> dict(new DictionaryValue()); | |
| 115 | |
| 116 dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec()); | |
| 117 dict->SetString(kTitleStorageKey, action->GetTitle(kTabId)); | |
| 118 dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kTabId)); | |
| 119 dict->SetString(kBadgeBackgroundColorStorageKey, | |
| 120 SkColorToRawString(action->GetBadgeBackgroundColor(kTabId))); | |
| 121 dict->SetString(kBadgeTextColorStorageKey, | |
| 122 SkColorToRawString(action->GetBadgeTextColor(kTabId))); | |
| 123 dict->SetInteger(kAppearanceStorageKey, | |
| 124 action->GetIsVisible(kTabId) ? | |
| 125 ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE); | |
| 126 dict->SetString(kIconStorageKey, ImageToString(action->GetIcon(kTabId))); | |
| 127 | |
| 128 return dict.Pass(); | |
| 129 } | |
| 130 | |
| 131 } | |
|
Yoyo Zhou
2012/08/08 01:21:06
// namespace
Matt Perry
2012/08/08 01:40:08
Done.
| |
| 132 | |
| 133 namespace extensions { | |
| 134 | |
| 135 // | |
| 136 // ExtensionActionStorageManager | |
| 137 // | |
| 138 | |
| 139 ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile) | |
| 140 : profile_(profile) { | |
| 141 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 142 content::Source<Profile>(profile_)); | |
| 143 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, | |
| 144 content::NotificationService::AllBrowserContextsAndSources()); | |
| 145 | |
| 146 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); | |
| 147 if (storage) | |
| 148 storage->RegisterKey(kBrowserActionStorageKey); | |
| 149 } | |
| 150 | |
| 151 ExtensionActionStorageManager::~ExtensionActionStorageManager() { | |
| 152 } | |
| 153 | |
| 154 void ExtensionActionStorageManager::Observe( | |
| 155 int type, | |
| 156 const content::NotificationSource& source, | |
| 157 const content::NotificationDetails& details) { | |
| 158 switch (type) { | |
| 159 case chrome::NOTIFICATION_EXTENSION_LOADED: { | |
| 160 const Extension* extension = | |
| 161 content::Details<const Extension>(details).ptr(); | |
| 162 if (!extension->browser_action()) | |
| 163 break; | |
| 164 | |
| 165 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); | |
| 166 if (storage) { | |
| 167 storage->GetExtensionValue(extension->id(), kBrowserActionStorageKey, | |
| 168 base::Bind(&ExtensionActionStorageManager::ReadFromStorage, | |
| 169 AsWeakPtr(), extension->id())); | |
| 170 } | |
| 171 break; | |
| 172 } | |
| 173 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED: { | |
| 174 ExtensionAction* extension_action = | |
| 175 content::Source<ExtensionAction>(source).ptr(); | |
| 176 Profile* profile = content::Details<Profile>(details).ptr(); | |
| 177 if (profile != profile_) | |
| 178 break; | |
| 179 | |
| 180 extension_action->set_defaults_have_changed(true); | |
| 181 WriteToStorage(extension_action); | |
| 182 break; | |
| 183 } | |
| 184 default: | |
| 185 NOTREACHED(); | |
| 186 break; | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void ExtensionActionStorageManager::WriteToStorage( | |
| 191 ExtensionAction* extension_action) { | |
| 192 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); | |
| 193 if (!storage) | |
| 194 return; | |
| 195 | |
| 196 scoped_ptr<base::DictionaryValue> defaults = | |
| 197 DefaultsToValue(extension_action); | |
| 198 storage->SetExtensionValue(extension_action->extension_id(), | |
| 199 kBrowserActionStorageKey, | |
| 200 defaults.PassAs<base::Value>()); | |
| 201 } | |
| 202 | |
| 203 void ExtensionActionStorageManager::ReadFromStorage( | |
| 204 const std::string& extension_id, scoped_ptr<base::Value> value) { | |
| 205 const Extension* extension = | |
| 206 ExtensionSystem::Get(profile_)->extension_service()-> | |
| 207 GetExtensionById(extension_id, true); | |
| 208 if (!extension) | |
| 209 return; | |
| 210 | |
| 211 CHECK(extension->browser_action()); | |
| 212 | |
| 213 // Don't load values from storage if the extension has updated a value | |
| 214 // already. The extension may have only updated some of the values, but | |
| 215 // this is a good first approximation. If the extension is doing stuff | |
| 216 // to the browser action, we can assume it is ready to take over. | |
| 217 if (extension->browser_action()->defaults_have_changed()) | |
| 218 return; | |
| 219 | |
| 220 base::DictionaryValue* dict = NULL; | |
| 221 if (!value.get() || !value->GetAsDictionary(&dict)) | |
| 222 return; | |
| 223 | |
| 224 DefaultsFromValue(dict, extension->browser_action()); | |
| 225 } | |
| 226 | |
| 227 } // namespace extensions | |
| 228 | |
| 229 | |
| 230 // | |
| 231 // ExtensionActionFunction | |
| 232 // | |
| 36 | 233 |
| 37 ExtensionActionFunction::ExtensionActionFunction() | 234 ExtensionActionFunction::ExtensionActionFunction() |
| 38 : details_(NULL), | 235 : details_(NULL), |
| 39 tab_id_(ExtensionAction::kDefaultTabId), | 236 tab_id_(ExtensionAction::kDefaultTabId), |
| 40 contents_(NULL), | 237 contents_(NULL), |
| 41 extension_action_(NULL) { | 238 extension_action_(NULL) { |
| 42 } | 239 } |
| 43 | 240 |
| 44 ExtensionActionFunction::~ExtensionActionFunction() { | 241 ExtensionActionFunction::~ExtensionActionFunction() { |
| 45 } | 242 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 NotifyLocationBarChange(); | 327 NotifyLocationBarChange(); |
| 131 return; | 328 return; |
| 132 } | 329 } |
| 133 NOTREACHED(); | 330 NOTREACHED(); |
| 134 } | 331 } |
| 135 | 332 |
| 136 void ExtensionActionFunction::NotifyBrowserActionChange() { | 333 void ExtensionActionFunction::NotifyBrowserActionChange() { |
| 137 content::NotificationService::current()->Notify( | 334 content::NotificationService::current()->Notify( |
| 138 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, | 335 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, |
| 139 content::Source<ExtensionAction>(extension_action_), | 336 content::Source<ExtensionAction>(extension_action_), |
| 140 content::NotificationService::NoDetails()); | 337 content::Details<Profile>(profile())); |
| 141 } | 338 } |
| 142 | 339 |
| 143 void ExtensionActionFunction::NotifyLocationBarChange() { | 340 void ExtensionActionFunction::NotifyLocationBarChange() { |
| 144 contents_->extension_tab_helper()->location_bar_controller()->NotifyChange(); | 341 contents_->extension_tab_helper()->location_bar_controller()->NotifyChange(); |
| 145 } | 342 } |
| 146 | 343 |
| 147 // static | 344 // static |
| 148 bool ExtensionActionFunction::ParseCSSColorString( | 345 bool ExtensionActionFunction::ParseCSSColorString( |
| 149 const std::string& color_string, | 346 const std::string& color_string, |
| 150 SkColor* result) { | 347 SkColor* result) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 | 400 |
| 204 bool ExtensionActionSetIconFunction::RunExtensionAction() { | 401 bool ExtensionActionSetIconFunction::RunExtensionAction() { |
| 205 // setIcon can take a variant argument: either a canvas ImageData, or an | 402 // setIcon can take a variant argument: either a canvas ImageData, or an |
| 206 // icon index. | 403 // icon index. |
| 207 base::BinaryValue* binary = NULL; | 404 base::BinaryValue* binary = NULL; |
| 208 int icon_index; | 405 int icon_index; |
| 209 if (details_->GetBinary("imageData", &binary)) { | 406 if (details_->GetBinary("imageData", &binary)) { |
| 210 IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); | 407 IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); |
| 211 PickleIterator iter(bitmap_pickle); | 408 PickleIterator iter(bitmap_pickle); |
| 212 SkBitmap bitmap; | 409 SkBitmap bitmap; |
| 213 EXTENSION_FUNCTION_VALIDATE( | 410 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); |
| 214 IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); | |
| 215 extension_action_->SetIcon(tab_id_, bitmap); | 411 extension_action_->SetIcon(tab_id_, bitmap); |
| 216 } else if (details_->GetInteger("iconIndex", &icon_index)) { | 412 } else if (details_->GetInteger("iconIndex", &icon_index)) { |
| 217 // If --enable-script-badges is on there might legitimately be an iconIndex | 413 // If --enable-script-badges is on there might legitimately be an iconIndex |
| 218 // set. Until we decide what to do with that, ignore. | 414 // set. Until we decide what to do with that, ignore. |
| 219 if (!GetExtension()->page_action()) | 415 if (!GetExtension()->page_action()) |
| 220 return true; | 416 return true; |
| 221 if (icon_index < 0 || | 417 if (icon_index < 0 || |
| 222 static_cast<size_t>(icon_index) >= | 418 static_cast<size_t>(icon_index) >= |
| 223 extension_action_->icon_paths()->size()) { | 419 extension_action_->icon_paths()->size()) { |
| 224 error_ = kIconIndexOutOfBounds; | 420 error_ = kIconIndexOutOfBounds; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { | 505 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { |
| 310 ListValue* list = new ListValue(); | 506 ListValue* list = new ListValue(); |
| 311 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); | 507 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); |
| 312 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); | 508 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); |
| 313 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); | 509 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); |
| 314 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); | 510 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); |
| 315 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); | 511 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); |
| 316 SetResult(list); | 512 SetResult(list); |
| 317 return true; | 513 return true; |
| 318 } | 514 } |
| OLD | NEW |