| 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/base64.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 const char kBadgeBackgroundColorStorageKey[] = "badge_background_color"; | 37 const char kBadgeBackgroundColorStorageKey[] = "badge_background_color"; |
| 38 const char kBadgeTextColorStorageKey[] = "badge_text_color"; | 38 const char kBadgeTextColorStorageKey[] = "badge_text_color"; |
| 39 const char kAppearanceStorageKey[] = "appearance"; | 39 const char kAppearanceStorageKey[] = "appearance"; |
| 40 | 40 |
| 41 // Errors. | 41 // Errors. |
| 42 const char kNoExtensionActionError[] = | 42 const char kNoExtensionActionError[] = |
| 43 "This extension has no action specified."; | 43 "This extension has no action specified."; |
| 44 const char kNoTabError[] = "No tab with id: *."; | 44 const char kNoTabError[] = "No tab with id: *."; |
| 45 const char kIconIndexOutOfBounds[] = "Page action icon index out of bounds."; | 45 const char kIconIndexOutOfBounds[] = "Page action icon index out of bounds."; |
| 46 | 46 |
| 47 struct IconRepresentationInfo { |
| 48 // Size as a string that will be used to retrieve representation value from |
| 49 // SetIcon function arguments. |
| 50 const char* size_string; |
| 51 // Scale factor for which the represantion should be used. |
| 52 ui::ScaleFactor scale; |
| 53 }; |
| 54 |
| 55 |
| 56 const IconRepresentationInfo kIconSizes[] = { |
| 57 { "19", ui::SCALE_FACTOR_100P }, |
| 58 { "38", ui::SCALE_FACTOR_200P } |
| 59 }; |
| 60 |
| 47 // Conversion function for reading/writing to storage. | 61 // Conversion function for reading/writing to storage. |
| 48 SkColor RawStringToSkColor(const std::string& str) { | 62 SkColor RawStringToSkColor(const std::string& str) { |
| 49 uint64 value = 0; | 63 uint64 value = 0; |
| 50 base::StringToUint64(str, &value); | 64 base::StringToUint64(str, &value); |
| 51 SkColor color = static_cast<SkColor>(value); | 65 SkColor color = static_cast<SkColor>(value); |
| 52 DCHECK(value == color); // ensure value fits into color's 32 bits | 66 DCHECK(value == color); // ensure value fits into color's 32 bits |
| 53 return color; | 67 return color; |
| 54 } | 68 } |
| 55 | 69 |
| 56 // Conversion function for reading/writing to storage. | 70 // Conversion function for reading/writing to storage. |
| 57 std::string SkColorToRawString(SkColor color) { | 71 std::string SkColorToRawString(SkColor color) { |
| 58 return base::Uint64ToString(color); | 72 return base::Uint64ToString(color); |
| 59 } | 73 } |
| 60 | 74 |
| 61 // Conversion function for reading/writing to storage. | 75 // Conversion function for reading/writing to storage. |
| 62 bool StringToSkBitmap(const std::string& str, SkBitmap* bitmap) { | 76 bool StringToSkBitmap(const std::string& str, SkBitmap* bitmap) { |
| 63 // TODO(mpcomplete): Remove the base64 encode/decode step when | 77 // TODO(mpcomplete): Remove the base64 encode/decode step when |
| 64 // http://crbug.com/140546 is fixed. | 78 // http://crbug.com/140546 is fixed. |
| 65 std::string raw_str; | 79 std::string raw_str; |
| 66 if (!base::Base64Decode(str, &raw_str)) | 80 if (!base::Base64Decode(str, &raw_str)) |
| 67 return false; | 81 return false; |
| 68 IPC::Message bitmap_pickle(raw_str.data(), raw_str.size()); | 82 IPC::Message bitmap_pickle(raw_str.data(), raw_str.size()); |
| 69 PickleIterator iter(bitmap_pickle); | 83 PickleIterator iter(bitmap_pickle); |
| 70 return IPC::ReadParam(&bitmap_pickle, &iter, bitmap); | 84 return IPC::ReadParam(&bitmap_pickle, &iter, bitmap); |
| 71 } | 85 } |
| 72 | 86 |
| 73 // Conversion function for reading/writing to storage. | 87 // Conversion function for reading/writing to storage. |
| 74 std::string ImageToString(const gfx::Image& image) { | 88 std::string RepresentationToString(const gfx::ImageSkia& image, |
| 89 ui::ScaleFactor scale) { |
| 90 SkBitmap bitmap = image.GetRepresentation(scale).sk_bitmap(); |
| 75 IPC::Message bitmap_pickle; | 91 IPC::Message bitmap_pickle; |
| 76 IPC::WriteParam(&bitmap_pickle, image.AsBitmap()); | 92 IPC::WriteParam(&bitmap_pickle, bitmap); |
| 77 std::string raw_str(static_cast<const char*>(bitmap_pickle.data()), | 93 std::string raw_str(static_cast<const char*>(bitmap_pickle.data()), |
| 78 bitmap_pickle.size()); | 94 bitmap_pickle.size()); |
| 79 std::string base64_str; | 95 std::string base64_str; |
| 80 if (!base::Base64Encode(raw_str, &base64_str)) | 96 if (!base::Base64Encode(raw_str, &base64_str)) |
| 81 return std::string(); | 97 return std::string(); |
| 82 return base64_str; | 98 return base64_str; |
| 83 } | 99 } |
| 84 | 100 |
| 85 // Set |action|'s default values to those specified in |dict|. | 101 // Set |action|'s default values to those specified in |dict|. |
| 86 void SetDefaultsFromValue(const base::DictionaryValue* dict, | 102 void SetDefaultsFromValue(const base::DictionaryValue* dict, |
| 87 ExtensionAction* action) { | 103 ExtensionAction* action) { |
| 88 const int kTabId = ExtensionAction::kDefaultTabId; | 104 const int kTabId = ExtensionAction::kDefaultTabId; |
| 89 std::string str_value; | 105 std::string str_value; |
| 90 int int_value; | 106 int int_value; |
| 91 SkBitmap bitmap; | 107 SkBitmap bitmap; |
| 108 gfx::ImageSkia icon; |
| 92 | 109 |
| 93 if (dict->GetString(kPopupUrlStorageKey, &str_value)) | 110 if (dict->GetString(kPopupUrlStorageKey, &str_value)) |
| 94 action->SetPopupUrl(kTabId, GURL(str_value)); | 111 action->SetPopupUrl(kTabId, GURL(str_value)); |
| 95 if (dict->GetString(kTitleStorageKey, &str_value)) | 112 if (dict->GetString(kTitleStorageKey, &str_value)) |
| 96 action->SetTitle(kTabId, str_value); | 113 action->SetTitle(kTabId, str_value); |
| 97 if (dict->GetString(kBadgeTextStorageKey, &str_value)) | 114 if (dict->GetString(kBadgeTextStorageKey, &str_value)) |
| 98 action->SetBadgeText(kTabId, str_value); | 115 action->SetBadgeText(kTabId, str_value); |
| 99 if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value)) | 116 if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value)) |
| 100 action->SetBadgeBackgroundColor(kTabId, RawStringToSkColor(str_value)); | 117 action->SetBadgeBackgroundColor(kTabId, RawStringToSkColor(str_value)); |
| 101 if (dict->GetString(kBadgeTextColorStorageKey, &str_value)) | 118 if (dict->GetString(kBadgeTextColorStorageKey, &str_value)) |
| 102 action->SetBadgeTextColor(kTabId, RawStringToSkColor(str_value)); | 119 action->SetBadgeTextColor(kTabId, RawStringToSkColor(str_value)); |
| 103 if (dict->GetInteger(kAppearanceStorageKey, &int_value)) | 120 if (dict->GetInteger(kAppearanceStorageKey, &int_value)) |
| 104 action->SetAppearance(kTabId, | 121 action->SetAppearance(kTabId, |
| 105 static_cast<ExtensionAction::Appearance>(int_value)); | 122 static_cast<ExtensionAction::Appearance>(int_value)); |
| 106 if (dict->GetString(kIconStorageKey, &str_value) && | 123 |
| 107 StringToSkBitmap(str_value, &bitmap)) { | 124 const base::DictionaryValue* icon_value = NULL; |
| 108 CHECK(!bitmap.isNull()); | 125 if (dict->GetDictionary(kIconStorageKey, &icon_value)) { |
| 109 action->SetIcon(kTabId, gfx::Image(bitmap)); | 126 for (size_t i = 0; i < arraysize(kIconSizes); i++) { |
| 127 if (icon_value->GetString(kIconSizes[i].size_string, &str_value) && |
| 128 StringToSkBitmap(str_value, &bitmap)) { |
| 129 CHECK(!bitmap.isNull()); |
| 130 icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, kIconSizes[i].scale)); |
| 131 } |
| 132 } |
| 133 action->SetIcon(kTabId, gfx::Image(icon)); |
| 110 } | 134 } |
| 111 } | 135 } |
| 112 | 136 |
| 113 // Store |action|'s default values in a DictionaryValue for use in storing to | 137 // Store |action|'s default values in a DictionaryValue for use in storing to |
| 114 // disk. | 138 // disk. |
| 115 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) { | 139 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) { |
| 116 const int kTabId = ExtensionAction::kDefaultTabId; | 140 const int kTabId = ExtensionAction::kDefaultTabId; |
| 117 scoped_ptr<base::DictionaryValue> dict(new DictionaryValue()); | 141 scoped_ptr<base::DictionaryValue> dict(new DictionaryValue()); |
| 118 | 142 |
| 119 dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec()); | 143 dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec()); |
| 120 dict->SetString(kTitleStorageKey, action->GetTitle(kTabId)); | 144 dict->SetString(kTitleStorageKey, action->GetTitle(kTabId)); |
| 121 dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kTabId)); | 145 dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kTabId)); |
| 122 dict->SetString(kBadgeBackgroundColorStorageKey, | 146 dict->SetString(kBadgeBackgroundColorStorageKey, |
| 123 SkColorToRawString(action->GetBadgeBackgroundColor(kTabId))); | 147 SkColorToRawString(action->GetBadgeBackgroundColor(kTabId))); |
| 124 dict->SetString(kBadgeTextColorStorageKey, | 148 dict->SetString(kBadgeTextColorStorageKey, |
| 125 SkColorToRawString(action->GetBadgeTextColor(kTabId))); | 149 SkColorToRawString(action->GetBadgeTextColor(kTabId))); |
| 126 dict->SetInteger(kAppearanceStorageKey, | 150 dict->SetInteger(kAppearanceStorageKey, |
| 127 action->GetIsVisible(kTabId) ? | 151 action->GetIsVisible(kTabId) ? |
| 128 ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE); | 152 ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE); |
| 129 dict->SetString(kIconStorageKey, ImageToString(action->GetIcon(kTabId))); | |
| 130 | 153 |
| 154 gfx::ImageSkia icon = action->GetExplicitlySetIcon(kTabId); |
| 155 if (!icon.empty()) { |
| 156 base::DictionaryValue* icon_value = new base::DictionaryValue(); |
| 157 for (size_t i = 0; i < arraysize(kIconSizes); i++) { |
| 158 if (icon.HasRepresentation(kIconSizes[i].scale)) { |
| 159 icon_value->SetString( |
| 160 kIconSizes[i].size_string, |
| 161 RepresentationToString(icon, kIconSizes[i].scale)); |
| 162 } |
| 163 } |
| 164 dict->Set(kIconStorageKey, icon_value); |
| 165 } |
| 131 return dict.Pass(); | 166 return dict.Pass(); |
| 132 } | 167 } |
| 133 | 168 |
| 134 } // namespace | 169 } // namespace |
| 135 | 170 |
| 136 namespace extensions { | 171 namespace extensions { |
| 137 | 172 |
| 138 // | 173 // |
| 139 // ExtensionActionStorageManager | 174 // ExtensionActionStorageManager |
| 140 // | 175 // |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 | 248 |
| 214 CHECK(extension->browser_action()); | 249 CHECK(extension->browser_action()); |
| 215 | 250 |
| 216 // Don't load values from storage if the extension has updated a value | 251 // Don't load values from storage if the extension has updated a value |
| 217 // already. The extension may have only updated some of the values, but | 252 // already. The extension may have only updated some of the values, but |
| 218 // this is a good first approximation. If the extension is doing stuff | 253 // this is a good first approximation. If the extension is doing stuff |
| 219 // to the browser action, we can assume it is ready to take over. | 254 // to the browser action, we can assume it is ready to take over. |
| 220 if (extension->browser_action()->has_changed()) | 255 if (extension->browser_action()->has_changed()) |
| 221 return; | 256 return; |
| 222 | 257 |
| 223 base::DictionaryValue* dict = NULL; | 258 const base::DictionaryValue* dict = NULL; |
| 224 if (!value.get() || !value->GetAsDictionary(&dict)) | 259 if (!value.get() || !value->GetAsDictionary(&dict)) |
| 225 return; | 260 return; |
| 226 | 261 |
| 227 SetDefaultsFromValue(dict, extension->browser_action()); | 262 SetDefaultsFromValue(dict, extension->browser_action()); |
| 228 } | 263 } |
| 229 | 264 |
| 230 } // namespace extensions | 265 } // namespace extensions |
| 231 | 266 |
| 232 | 267 |
| 233 // | 268 // |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 430 |
| 396 bool ExtensionActionShowFunction::RunExtensionAction() { | 431 bool ExtensionActionShowFunction::RunExtensionAction() { |
| 397 return SetVisible(true); | 432 return SetVisible(true); |
| 398 } | 433 } |
| 399 | 434 |
| 400 bool ExtensionActionHideFunction::RunExtensionAction() { | 435 bool ExtensionActionHideFunction::RunExtensionAction() { |
| 401 return SetVisible(false); | 436 return SetVisible(false); |
| 402 } | 437 } |
| 403 | 438 |
| 404 bool ExtensionActionSetIconFunction::RunExtensionAction() { | 439 bool ExtensionActionSetIconFunction::RunExtensionAction() { |
| 405 // setIcon can take a variant argument: either a canvas ImageData, or an | 440 // setIcon can take a variant argument: either a dictionary of canvases |
| 406 // icon index. | 441 // ImageDataSet, or an icon index. |
| 407 base::BinaryValue* binary = NULL; | |
| 408 int icon_index; | 442 int icon_index; |
| 409 if (details_->GetBinary("imageData", &binary)) { | 443 base::DictionaryValue* canvas_set = NULL; |
| 410 IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); | 444 if (details_->GetDictionary("imageData", &canvas_set)) { |
| 411 PickleIterator iter(bitmap_pickle); | 445 gfx::ImageSkia icon; |
| 412 SkBitmap bitmap; | 446 // Extract icon representations from the ImageDataSet dictionary. |
| 413 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); | 447 for (size_t i = 0; i < arraysize(kIconSizes); i++) { |
| 414 CHECK(!bitmap.isNull()); | 448 base::BinaryValue* binary; |
| 415 extension_action_->SetIcon(tab_id_, gfx::Image(bitmap)); | 449 if (canvas_set->GetBinary(kIconSizes[i].size_string, &binary)) { |
| 450 IPC::Message pickle(binary->GetBuffer(), binary->GetSize()); |
| 451 PickleIterator iter(pickle); |
| 452 SkBitmap bitmap; |
| 453 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&pickle, &iter, &bitmap)); |
| 454 CHECK(!bitmap.isNull()); |
| 455 icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, kIconSizes[i].scale)); |
| 456 } |
| 457 } |
| 458 |
| 459 extension_action_->SetIcon(tab_id_, gfx::Image(icon)); |
| 416 } else if (details_->GetInteger("iconIndex", &icon_index)) { | 460 } else if (details_->GetInteger("iconIndex", &icon_index)) { |
| 417 // If --enable-script-badges is on there might legitimately be an iconIndex | 461 // If --enable-script-badges is on there might legitimately be an iconIndex |
| 418 // set. Until we decide what to do with that, ignore. | 462 // set. Until we decide what to do with that, ignore. |
| 419 if (!GetExtension()->page_action()) | 463 if (!GetExtension()->page_action()) |
| 420 return true; | 464 return true; |
| 421 if (icon_index < 0 || | 465 if (icon_index < 0 || |
| 422 static_cast<size_t>(icon_index) >= | 466 static_cast<size_t>(icon_index) >= |
| 423 extension_action_->icon_paths()->size()) { | 467 extension_action_->icon_paths()->size()) { |
| 424 error_ = kIconIndexOutOfBounds; | 468 error_ = kIconIndexOutOfBounds; |
| 425 return false; | 469 return false; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { | 553 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { |
| 510 ListValue* list = new ListValue(); | 554 ListValue* list = new ListValue(); |
| 511 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); | 555 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); |
| 512 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); | 556 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); |
| 513 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); | 557 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); |
| 514 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); | 558 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); |
| 515 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); | 559 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); |
| 516 SetResult(list); | 560 SetResult(list); |
| 517 return true; | 561 return true; |
| 518 } | 562 } |
| OLD | NEW |