Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: chrome/browser/extensions/api/extension_action/extension_action_api.cc

Issue 502033003: Move ExtensionActionStorageManager out of extension_action_api.* (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Latest master for CQ Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_action_api.h" 5 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
6 6
7 #include "base/base64.h"
8 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
9 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/values.h" 9 #include "base/values.h"
12 #include "chrome/browser/extensions/active_script_controller.h" 10 #include "chrome/browser/extensions/active_script_controller.h"
13 #include "chrome/browser/extensions/api/extension_action/extension_page_actions_ api_constants.h"
14 #include "chrome/browser/extensions/extension_action.h"
15 #include "chrome/browser/extensions/extension_action_manager.h" 11 #include "chrome/browser/extensions/extension_action_manager.h"
16 #include "chrome/browser/extensions/extension_tab_util.h" 12 #include "chrome/browser/extensions/extension_tab_util.h"
17 #include "chrome/browser/extensions/extension_toolbar_model.h" 13 #include "chrome/browser/extensions/extension_toolbar_model.h"
18 #include "chrome/browser/extensions/tab_helper.h" 14 #include "chrome/browser/extensions/tab_helper.h"
19 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/sessions/session_tab_helper.h" 16 #include "chrome/browser/sessions/session_tab_helper.h"
21 #include "chrome/browser/ui/browser.h" 17 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_finder.h" 18 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_window.h" 19 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/browser/ui/location_bar/location_bar.h" 20 #include "chrome/browser/ui/location_bar/location_bar.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h" 21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/common/extensions/api/extension_action/action_info.h" 22 #include "chrome/common/extensions/api/extension_action/action_info.h"
27 #include "chrome/common/render_messages.h" 23 #include "chrome/common/render_messages.h"
28 #include "content/public/browser/navigation_entry.h"
29 #include "content/public/browser/notification_service.h" 24 #include "content/public/browser/notification_service.h"
30 #include "extensions/browser/event_router.h" 25 #include "extensions/browser/event_router.h"
31 #include "extensions/browser/extension_function_registry.h" 26 #include "extensions/browser/extension_function_registry.h"
32 #include "extensions/browser/extension_host.h" 27 #include "extensions/browser/extension_host.h"
33 #include "extensions/browser/extension_registry.h" 28 #include "extensions/browser/extension_registry.h"
34 #include "extensions/browser/extension_system.h"
35 #include "extensions/browser/image_util.h" 29 #include "extensions/browser/image_util.h"
36 #include "extensions/browser/notification_types.h" 30 #include "extensions/browser/notification_types.h"
37 #include "extensions/browser/state_store.h"
38 #include "extensions/common/error_utils.h" 31 #include "extensions/common/error_utils.h"
39 #include "ui/gfx/codec/png_codec.h"
40 #include "ui/gfx/image/image.h" 32 #include "ui/gfx/image/image.h"
41 #include "ui/gfx/image/image_skia.h" 33 #include "ui/gfx/image/image_skia.h"
42 34
43 using content::WebContents; 35 using content::WebContents;
44 36
45 namespace page_actions_keys = extension_page_actions_api_constants;
46
47 namespace extensions { 37 namespace extensions {
48 38
49 namespace { 39 namespace {
50 40
51 const char kBrowserActionStorageKey[] = "browser_action";
52 const char kPopupUrlStorageKey[] = "poupup_url";
53 const char kTitleStorageKey[] = "title";
54 const char kIconStorageKey[] = "icon";
55 const char kBadgeTextStorageKey[] = "badge_text";
56 const char kBadgeBackgroundColorStorageKey[] = "badge_background_color";
57 const char kBadgeTextColorStorageKey[] = "badge_text_color";
58 const char kAppearanceStorageKey[] = "appearance";
59
60 // Only add values to the end of this enum, since it's stored in the user's
61 // Extension State, under the kAppearanceStorageKey. It represents the
62 // ExtensionAction's default visibility.
63 enum StoredAppearance {
64 // The action icon is hidden.
65 INVISIBLE = 0,
66 // The action is trying to get the user's attention but isn't yet
67 // running on the page. Was only used for script badges.
68 OBSOLETE_WANTS_ATTENTION = 1,
69 // The action icon is visible with its normal appearance.
70 ACTIVE = 2,
71 };
72
73 // Whether the browser action is visible in the toolbar. 41 // Whether the browser action is visible in the toolbar.
74 const char kBrowserActionVisible[] = "browser_action_visible"; 42 const char kBrowserActionVisible[] = "browser_action_visible";
75 43
76 // Errors. 44 // Errors.
77 const char kNoExtensionActionError[] = 45 const char kNoExtensionActionError[] =
78 "This extension has no action specified."; 46 "This extension has no action specified.";
79 const char kNoTabError[] = "No tab with id: *."; 47 const char kNoTabError[] = "No tab with id: *.";
80 const char kOpenPopupError[] = 48 const char kOpenPopupError[] =
81 "Failed to show popup either because there is an existing popup or another " 49 "Failed to show popup either because there is an existing popup or another "
82 "error occurred."; 50 "error occurred.";
83 const char kInternalError[] = "Internal error."; 51 const char kInternalError[] = "Internal error.";
84 52
85 struct IconRepresentationInfo {
86 // Size as a string that will be used to retrieve representation value from
87 // SetIcon function arguments.
88 const char* size_string;
89 // Scale factor for which the represantion should be used.
90 ui::ScaleFactor scale;
91 };
92
93 const IconRepresentationInfo kIconSizes[] = {
94 { "19", ui::SCALE_FACTOR_100P },
95 { "38", ui::SCALE_FACTOR_200P }
96 };
97
98 // Conversion function for reading/writing to storage.
99 SkColor RawStringToSkColor(const std::string& str) {
100 uint64 value = 0;
101 base::StringToUint64(str, &value);
102 SkColor color = static_cast<SkColor>(value);
103 DCHECK(value == color); // ensure value fits into color's 32 bits
104 return color;
105 }
106
107 // Conversion function for reading/writing to storage.
108 std::string SkColorToRawString(SkColor color) {
109 return base::Uint64ToString(color);
110 }
111
112 // Conversion function for reading/writing to storage.
113 bool StringToSkBitmap(const std::string& str, SkBitmap* bitmap) {
114 // TODO(mpcomplete): Remove the base64 encode/decode step when
115 // http://crbug.com/140546 is fixed.
116 std::string raw_str;
117 if (!base::Base64Decode(str, &raw_str))
118 return false;
119
120 bool success = gfx::PNGCodec::Decode(
121 reinterpret_cast<unsigned const char*>(raw_str.data()), raw_str.size(),
122 bitmap);
123 return success;
124 }
125
126 // Conversion function for reading/writing to storage.
127 std::string RepresentationToString(const gfx::ImageSkia& image, float scale) {
128 SkBitmap bitmap = image.GetRepresentation(scale).sk_bitmap();
129 SkAutoLockPixels lock_image(bitmap);
130 std::vector<unsigned char> data;
131 bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data);
132 if (!success)
133 return std::string();
134
135 base::StringPiece raw_str(
136 reinterpret_cast<const char*>(&data[0]), data.size());
137 std::string base64_str;
138 base::Base64Encode(raw_str, &base64_str);
139 return base64_str;
140 }
141
142 // Set |action|'s default values to those specified in |dict|.
143 void SetDefaultsFromValue(const base::DictionaryValue* dict,
144 ExtensionAction* action) {
145 const int kDefaultTabId = ExtensionAction::kDefaultTabId;
146 std::string str_value;
147 int int_value;
148 SkBitmap bitmap;
149 gfx::ImageSkia icon;
150
151 // For each value, don't set it if it has been modified already.
152 if (dict->GetString(kPopupUrlStorageKey, &str_value) &&
153 !action->HasPopupUrl(kDefaultTabId)) {
154 action->SetPopupUrl(kDefaultTabId, GURL(str_value));
155 }
156 if (dict->GetString(kTitleStorageKey, &str_value) &&
157 !action->HasTitle(kDefaultTabId)) {
158 action->SetTitle(kDefaultTabId, str_value);
159 }
160 if (dict->GetString(kBadgeTextStorageKey, &str_value) &&
161 !action->HasBadgeText(kDefaultTabId)) {
162 action->SetBadgeText(kDefaultTabId, str_value);
163 }
164 if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value) &&
165 !action->HasBadgeBackgroundColor(kDefaultTabId)) {
166 action->SetBadgeBackgroundColor(kDefaultTabId,
167 RawStringToSkColor(str_value));
168 }
169 if (dict->GetString(kBadgeTextColorStorageKey, &str_value) &&
170 !action->HasBadgeTextColor(kDefaultTabId)) {
171 action->SetBadgeTextColor(kDefaultTabId, RawStringToSkColor(str_value));
172 }
173 if (dict->GetInteger(kAppearanceStorageKey, &int_value) &&
174 !action->HasIsVisible(kDefaultTabId)) {
175 switch (int_value) {
176 case INVISIBLE:
177 case OBSOLETE_WANTS_ATTENTION:
178 action->SetIsVisible(kDefaultTabId, false);
179 break;
180 case ACTIVE:
181 action->SetIsVisible(kDefaultTabId, true);
182 break;
183 }
184 }
185
186 const base::DictionaryValue* icon_value = NULL;
187 if (dict->GetDictionary(kIconStorageKey, &icon_value) &&
188 !action->HasIcon(kDefaultTabId)) {
189 for (size_t i = 0; i < arraysize(kIconSizes); i++) {
190 if (icon_value->GetString(kIconSizes[i].size_string, &str_value) &&
191 StringToSkBitmap(str_value, &bitmap)) {
192 CHECK(!bitmap.isNull());
193 float scale = ui::GetScaleForScaleFactor(kIconSizes[i].scale);
194 icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
195 }
196 }
197 action->SetIcon(kDefaultTabId, gfx::Image(icon));
198 }
199 }
200
201 // Store |action|'s default values in a DictionaryValue for use in storing to
202 // disk.
203 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) {
204 const int kDefaultTabId = ExtensionAction::kDefaultTabId;
205 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
206
207 dict->SetString(kPopupUrlStorageKey,
208 action->GetPopupUrl(kDefaultTabId).spec());
209 dict->SetString(kTitleStorageKey, action->GetTitle(kDefaultTabId));
210 dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kDefaultTabId));
211 dict->SetString(
212 kBadgeBackgroundColorStorageKey,
213 SkColorToRawString(action->GetBadgeBackgroundColor(kDefaultTabId)));
214 dict->SetString(kBadgeTextColorStorageKey,
215 SkColorToRawString(action->GetBadgeTextColor(kDefaultTabId)));
216 dict->SetInteger(kAppearanceStorageKey,
217 action->GetIsVisible(kDefaultTabId) ? ACTIVE : INVISIBLE);
218
219 gfx::ImageSkia icon = action->GetExplicitlySetIcon(kDefaultTabId);
220 if (!icon.isNull()) {
221 base::DictionaryValue* icon_value = new base::DictionaryValue();
222 for (size_t i = 0; i < arraysize(kIconSizes); i++) {
223 float scale = ui::GetScaleForScaleFactor(kIconSizes[i].scale);
224 if (icon.HasRepresentation(scale)) {
225 icon_value->SetString(
226 kIconSizes[i].size_string,
227 RepresentationToString(icon, scale));
228 }
229 }
230 dict->Set(kIconStorageKey, icon_value);
231 }
232 return dict.Pass();
233 }
234
235 } // namespace 53 } // namespace
236 54
237 // 55 //
238 // ExtensionActionAPI::Observer 56 // ExtensionActionAPI::Observer
239 // 57 //
240 58
241 void ExtensionActionAPI::Observer::OnExtensionActionUpdated( 59 void ExtensionActionAPI::Observer::OnExtensionActionUpdated(
242 ExtensionAction* extension_action, 60 ExtensionAction* extension_action,
243 content::WebContents* web_contents, 61 content::WebContents* web_contents,
244 content::BrowserContext* browser_context) { 62 content::BrowserContext* browser_context) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 location_bar->UpdatePageActions(); 297 location_bar->UpdatePageActions();
480 298
481 FOR_EACH_OBSERVER(Observer, observers_, OnPageActionsUpdated(web_contents)); 299 FOR_EACH_OBSERVER(Observer, observers_, OnPageActionsUpdated(web_contents));
482 } 300 }
483 301
484 void ExtensionActionAPI::Shutdown() { 302 void ExtensionActionAPI::Shutdown() {
485 FOR_EACH_OBSERVER(Observer, observers_, OnExtensionActionAPIShuttingDown()); 303 FOR_EACH_OBSERVER(Observer, observers_, OnExtensionActionAPIShuttingDown());
486 } 304 }
487 305
488 // 306 //
489 // ExtensionActionStorageManager
490 //
491
492 ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile)
493 : profile_(profile),
494 extension_action_observer_(this),
495 extension_registry_observer_(this) {
496 extension_action_observer_.Add(ExtensionActionAPI::Get(profile_));
497 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
498
499 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
500 if (storage)
501 storage->RegisterKey(kBrowserActionStorageKey);
502 }
503
504 ExtensionActionStorageManager::~ExtensionActionStorageManager() {
505 }
506
507 void ExtensionActionStorageManager::OnExtensionLoaded(
508 content::BrowserContext* browser_context,
509 const Extension* extension) {
510 if (!ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension))
511 return;
512
513 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
514 if (storage) {
515 storage->GetExtensionValue(
516 extension->id(),
517 kBrowserActionStorageKey,
518 base::Bind(&ExtensionActionStorageManager::ReadFromStorage,
519 AsWeakPtr(),
520 extension->id()));
521 }
522 }
523
524 void ExtensionActionStorageManager::OnExtensionActionUpdated(
525 ExtensionAction* extension_action,
526 content::WebContents* web_contents,
527 content::BrowserContext* browser_context) {
528 if (profile_ == browser_context &&
529 extension_action->action_type() == ActionInfo::TYPE_BROWSER)
530 WriteToStorage(extension_action);
531 }
532
533 void ExtensionActionStorageManager::OnExtensionActionAPIShuttingDown() {
534 extension_action_observer_.RemoveAll();
535 }
536
537 void ExtensionActionStorageManager::WriteToStorage(
538 ExtensionAction* extension_action) {
539 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
540 if (!storage)
541 return;
542
543 scoped_ptr<base::DictionaryValue> defaults =
544 DefaultsToValue(extension_action);
545 storage->SetExtensionValue(extension_action->extension_id(),
546 kBrowserActionStorageKey,
547 defaults.PassAs<base::Value>());
548 }
549
550 void ExtensionActionStorageManager::ReadFromStorage(
551 const std::string& extension_id, scoped_ptr<base::Value> value) {
552 const Extension* extension = ExtensionRegistry::Get(profile_)->
553 enabled_extensions().GetByID(extension_id);
554 if (!extension)
555 return;
556
557 ExtensionAction* browser_action =
558 ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension);
559 if (!browser_action) {
560 // This can happen if the extension is updated between startup and when the
561 // storage read comes back, and the update removes the browser action.
562 // http://crbug.com/349371
563 return;
564 }
565
566 const base::DictionaryValue* dict = NULL;
567 if (!value.get() || !value->GetAsDictionary(&dict))
568 return;
569
570 SetDefaultsFromValue(dict, browser_action);
571 }
572
573 //
574 // ExtensionActionFunction 307 // ExtensionActionFunction
575 // 308 //
576 309
577 ExtensionActionFunction::ExtensionActionFunction() 310 ExtensionActionFunction::ExtensionActionFunction()
578 : details_(NULL), 311 : details_(NULL),
579 tab_id_(ExtensionAction::kDefaultTabId), 312 tab_id_(ExtensionAction::kDefaultTabId),
580 contents_(NULL), 313 contents_(NULL),
581 extension_action_(NULL) { 314 extension_action_(NULL) {
582 } 315 }
583 316
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 } 415 }
683 416
684 bool ExtensionActionFunction::SetVisible(bool visible) { 417 bool ExtensionActionFunction::SetVisible(bool visible) {
685 if (extension_action_->GetIsVisible(tab_id_) == visible) 418 if (extension_action_->GetIsVisible(tab_id_) == visible)
686 return true; 419 return true;
687 extension_action_->SetIsVisible(tab_id_, visible); 420 extension_action_->SetIsVisible(tab_id_, visible);
688 NotifyChange(); 421 NotifyChange();
689 return true; 422 return true;
690 } 423 }
691 424
692 TabHelper& ExtensionActionFunction::tab_helper() const {
693 CHECK(contents_);
694 return *TabHelper::FromWebContents(contents_);
695 }
696
697 bool ExtensionActionShowFunction::RunExtensionAction() { 425 bool ExtensionActionShowFunction::RunExtensionAction() {
698 return SetVisible(true); 426 return SetVisible(true);
699 } 427 }
700 428
701 bool ExtensionActionHideFunction::RunExtensionAction() { 429 bool ExtensionActionHideFunction::RunExtensionAction() {
702 return SetVisible(false); 430 return SetVisible(false);
703 } 431 }
704 432
705 bool ExtensionActionSetIconFunction::RunExtensionAction() { 433 bool ExtensionActionSetIconFunction::RunExtensionAction() {
706 EXTENSION_FUNCTION_VALIDATE(details_); 434 EXTENSION_FUNCTION_VALIDATE(details_);
707 435
708 // setIcon can take a variant argument: either a dictionary of canvas 436 // setIcon can take a variant argument: either a dictionary of canvas
709 // ImageData, or an icon index. 437 // ImageData, or an icon index.
710 base::DictionaryValue* canvas_set = NULL; 438 base::DictionaryValue* canvas_set = NULL;
711 int icon_index; 439 int icon_index;
712 if (details_->GetDictionary("imageData", &canvas_set)) { 440 if (details_->GetDictionary("imageData", &canvas_set)) {
713 gfx::ImageSkia icon; 441 gfx::ImageSkia icon;
714 // Extract icon representations from the ImageDataSet dictionary. 442 // Extract icon representations from the ImageDataSet dictionary.
715 for (size_t i = 0; i < arraysize(kIconSizes); i++) { 443 for (size_t i = 0; i < extension_misc::kNumExtensionActionIconSizes; i++) {
716 base::BinaryValue* binary; 444 base::BinaryValue* binary = NULL;
717 if (canvas_set->GetBinary(kIconSizes[i].size_string, &binary)) { 445 const extension_misc::IconRepresentationInfo& icon_info =
446 extension_misc::kExtensionActionIconSizes[i];
447 if (canvas_set->GetBinary(icon_info.size_string, &binary)) {
718 IPC::Message pickle(binary->GetBuffer(), binary->GetSize()); 448 IPC::Message pickle(binary->GetBuffer(), binary->GetSize());
719 PickleIterator iter(pickle); 449 PickleIterator iter(pickle);
720 SkBitmap bitmap; 450 SkBitmap bitmap;
721 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&pickle, &iter, &bitmap)); 451 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&pickle, &iter, &bitmap));
722 CHECK(!bitmap.isNull()); 452 CHECK(!bitmap.isNull());
723 float scale = ui::GetScaleForScaleFactor(kIconSizes[i].scale); 453 float scale = ui::GetScaleForScaleFactor(icon_info.scale);
724 icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); 454 icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
725 } 455 }
726 } 456 }
727 457
728 extension_action_->SetIcon(tab_id_, gfx::Image(icon)); 458 extension_action_->SetIcon(tab_id_, gfx::Image(icon));
729 } else if (details_->GetInteger("iconIndex", &icon_index)) { 459 } else if (details_->GetInteger("iconIndex", &icon_index)) {
730 // Obsolete argument: ignore it. 460 // Obsolete argument: ignore it.
731 return true; 461 return true;
732 } else { 462 } else {
733 EXTENSION_FUNCTION_VALIDATE(false); 463 EXTENSION_FUNCTION_VALIDATE(false);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 if (host->extension_host_type() != VIEW_TYPE_EXTENSION_POPUP || 611 if (host->extension_host_type() != VIEW_TYPE_EXTENSION_POPUP ||
882 host->extension()->id() != extension_->id()) 612 host->extension()->id() != extension_->id())
883 return; 613 return;
884 614
885 SendResponse(true); 615 SendResponse(true);
886 response_sent_ = true; 616 response_sent_ = true;
887 registrar_.RemoveAll(); 617 registrar_.RemoveAll();
888 } 618 }
889 619
890 } // namespace extensions 620 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/extension_action/extension_action_api.h ('k') | chrome/browser/extensions/extension_action.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698