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/extension_system.h" |
15 #include "chrome/browser/extensions/extension_tab_util.h" | 16 #include "chrome/browser/extensions/extension_tab_util.h" |
16 #include "chrome/browser/extensions/location_bar_controller.h" | 17 #include "chrome/browser/extensions/location_bar_controller.h" |
| 18 #include "chrome/browser/extensions/state_store.h" |
| 19 #include "chrome/browser/extensions/tab_helper.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); |
| 51 SkColor color = static_cast<SkColor>(value); |
| 52 DCHECK(value == color); // ensure value fits into color's 32 bits |
| 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): Remove the base64 encode/decode step when |
| 64 // http://crbug.com/140546 is fixed. |
| 65 std::string raw_str; |
| 66 if (!base::Base64Decode(str, &raw_str)) |
| 67 return false; |
| 68 IPC::Message bitmap_pickle(raw_str.data(), raw_str.size()); |
| 69 PickleIterator iter(bitmap_pickle); |
| 70 return IPC::ReadParam(&bitmap_pickle, &iter, bitmap); |
| 71 } |
| 72 |
| 73 // Conversion function for reading/writing to storage. |
| 74 std::string ImageToString(const gfx::Image& image) { |
| 75 IPC::Message bitmap_pickle; |
| 76 IPC::WriteParam(&bitmap_pickle, image.AsBitmap()); |
| 77 std::string raw_str(static_cast<const char*>(bitmap_pickle.data()), |
| 78 bitmap_pickle.size()); |
| 79 std::string base64_str; |
| 80 if (!base::Base64Encode(raw_str, &base64_str)) |
| 81 return std::string(); |
| 82 return base64_str; |
| 83 } |
| 84 |
| 85 // Set |action|'s default values to those specified in |dict|. |
| 86 void SetDefaultsFromValue(const base::DictionaryValue* dict, |
| 87 ExtensionAction* action) { |
| 88 const int kTabId = ExtensionAction::kDefaultTabId; |
| 89 std::string str_value; |
| 90 int int_value; |
| 91 SkBitmap bitmap; |
| 92 |
| 93 if (dict->GetString(kPopupUrlStorageKey, &str_value)) |
| 94 action->SetPopupUrl(kTabId, GURL(str_value)); |
| 95 if (dict->GetString(kTitleStorageKey, &str_value)) |
| 96 action->SetTitle(kTabId, str_value); |
| 97 if (dict->GetString(kBadgeTextStorageKey, &str_value)) |
| 98 action->SetBadgeText(kTabId, str_value); |
| 99 if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value)) |
| 100 action->SetBadgeBackgroundColor(kTabId, RawStringToSkColor(str_value)); |
| 101 if (dict->GetString(kBadgeTextColorStorageKey, &str_value)) |
| 102 action->SetBadgeTextColor(kTabId, RawStringToSkColor(str_value)); |
| 103 if (dict->GetInteger(kAppearanceStorageKey, &int_value)) |
| 104 action->SetAppearance(kTabId, |
| 105 static_cast<ExtensionAction::Appearance>(int_value)); |
| 106 if (dict->GetString(kIconStorageKey, &str_value) && |
| 107 StringToSkBitmap(str_value, &bitmap)) |
| 108 action->SetIcon(kTabId, bitmap); |
| 109 } |
| 110 |
| 111 // Store |action|'s default values in a DictionaryValue for use in storing to |
| 112 // disk. |
| 113 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) { |
| 114 const int kTabId = ExtensionAction::kDefaultTabId; |
| 115 scoped_ptr<base::DictionaryValue> dict(new DictionaryValue()); |
| 116 |
| 117 dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec()); |
| 118 dict->SetString(kTitleStorageKey, action->GetTitle(kTabId)); |
| 119 dict->SetString(kBadgeTextStorageKey, action->GetBadgeText(kTabId)); |
| 120 dict->SetString(kBadgeBackgroundColorStorageKey, |
| 121 SkColorToRawString(action->GetBadgeBackgroundColor(kTabId))); |
| 122 dict->SetString(kBadgeTextColorStorageKey, |
| 123 SkColorToRawString(action->GetBadgeTextColor(kTabId))); |
| 124 dict->SetInteger(kAppearanceStorageKey, |
| 125 action->GetIsVisible(kTabId) ? |
| 126 ExtensionAction::ACTIVE : ExtensionAction::INVISIBLE); |
| 127 dict->SetString(kIconStorageKey, ImageToString(action->GetIcon(kTabId))); |
| 128 |
| 129 return dict.Pass(); |
| 130 } |
| 131 |
| 132 } // namespace |
| 133 |
| 134 namespace extensions { |
| 135 |
| 136 // |
| 137 // ExtensionActionStorageManager |
| 138 // |
| 139 |
| 140 ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile) |
| 141 : profile_(profile) { |
| 142 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 143 content::Source<Profile>(profile_)); |
| 144 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, |
| 145 content::NotificationService::AllBrowserContextsAndSources()); |
| 146 |
| 147 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); |
| 148 if (storage) |
| 149 storage->RegisterKey(kBrowserActionStorageKey); |
| 150 } |
| 151 |
| 152 ExtensionActionStorageManager::~ExtensionActionStorageManager() { |
| 153 } |
| 154 |
| 155 void ExtensionActionStorageManager::Observe( |
| 156 int type, |
| 157 const content::NotificationSource& source, |
| 158 const content::NotificationDetails& details) { |
| 159 switch (type) { |
| 160 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 161 const Extension* extension = |
| 162 content::Details<const Extension>(details).ptr(); |
| 163 if (!extension->browser_action()) |
| 164 break; |
| 165 |
| 166 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); |
| 167 if (storage) { |
| 168 storage->GetExtensionValue(extension->id(), kBrowserActionStorageKey, |
| 169 base::Bind(&ExtensionActionStorageManager::ReadFromStorage, |
| 170 AsWeakPtr(), extension->id())); |
| 171 } |
| 172 break; |
| 173 } |
| 174 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED: { |
| 175 ExtensionAction* extension_action = |
| 176 content::Source<ExtensionAction>(source).ptr(); |
| 177 Profile* profile = content::Details<Profile>(details).ptr(); |
| 178 if (profile != profile_) |
| 179 break; |
| 180 |
| 181 extension_action->set_has_changed(true); |
| 182 WriteToStorage(extension_action); |
| 183 break; |
| 184 } |
| 185 default: |
| 186 NOTREACHED(); |
| 187 break; |
| 188 } |
| 189 } |
| 190 |
| 191 void ExtensionActionStorageManager::WriteToStorage( |
| 192 ExtensionAction* extension_action) { |
| 193 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); |
| 194 if (!storage) |
| 195 return; |
| 196 |
| 197 scoped_ptr<base::DictionaryValue> defaults = |
| 198 DefaultsToValue(extension_action); |
| 199 storage->SetExtensionValue(extension_action->extension_id(), |
| 200 kBrowserActionStorageKey, |
| 201 defaults.PassAs<base::Value>()); |
| 202 } |
| 203 |
| 204 void ExtensionActionStorageManager::ReadFromStorage( |
| 205 const std::string& extension_id, scoped_ptr<base::Value> value) { |
| 206 const Extension* extension = |
| 207 ExtensionSystem::Get(profile_)->extension_service()-> |
| 208 GetExtensionById(extension_id, true); |
| 209 if (!extension) |
| 210 return; |
| 211 |
| 212 CHECK(extension->browser_action()); |
| 213 |
| 214 // Don't load values from storage if the extension has updated a value |
| 215 // already. The extension may have only updated some of the values, but |
| 216 // this is a good first approximation. If the extension is doing stuff |
| 217 // to the browser action, we can assume it is ready to take over. |
| 218 if (extension->browser_action()->has_changed()) |
| 219 return; |
| 220 |
| 221 base::DictionaryValue* dict = NULL; |
| 222 if (!value.get() || !value->GetAsDictionary(&dict)) |
| 223 return; |
| 224 |
| 225 SetDefaultsFromValue(dict, extension->browser_action()); |
| 226 } |
| 227 |
| 228 } // namespace extensions |
| 229 |
| 230 |
| 231 // |
| 232 // ExtensionActionFunction |
| 233 // |
36 | 234 |
37 ExtensionActionFunction::ExtensionActionFunction() | 235 ExtensionActionFunction::ExtensionActionFunction() |
38 : details_(NULL), | 236 : details_(NULL), |
39 tab_id_(ExtensionAction::kDefaultTabId), | 237 tab_id_(ExtensionAction::kDefaultTabId), |
40 contents_(NULL), | 238 contents_(NULL), |
41 extension_action_(NULL) { | 239 extension_action_(NULL) { |
42 } | 240 } |
43 | 241 |
44 ExtensionActionFunction::~ExtensionActionFunction() { | 242 ExtensionActionFunction::~ExtensionActionFunction() { |
45 } | 243 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 NotifyLocationBarChange(); | 328 NotifyLocationBarChange(); |
131 return; | 329 return; |
132 } | 330 } |
133 NOTREACHED(); | 331 NOTREACHED(); |
134 } | 332 } |
135 | 333 |
136 void ExtensionActionFunction::NotifyBrowserActionChange() { | 334 void ExtensionActionFunction::NotifyBrowserActionChange() { |
137 content::NotificationService::current()->Notify( | 335 content::NotificationService::current()->Notify( |
138 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, | 336 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, |
139 content::Source<ExtensionAction>(extension_action_), | 337 content::Source<ExtensionAction>(extension_action_), |
140 content::NotificationService::NoDetails()); | 338 content::Details<Profile>(profile())); |
141 } | 339 } |
142 | 340 |
143 void ExtensionActionFunction::NotifyLocationBarChange() { | 341 void ExtensionActionFunction::NotifyLocationBarChange() { |
144 contents_->extension_tab_helper()->location_bar_controller()->NotifyChange(); | 342 contents_->extension_tab_helper()->location_bar_controller()->NotifyChange(); |
145 } | 343 } |
146 | 344 |
147 // static | 345 // static |
148 bool ExtensionActionFunction::ParseCSSColorString( | 346 bool ExtensionActionFunction::ParseCSSColorString( |
149 const std::string& color_string, | 347 const std::string& color_string, |
150 SkColor* result) { | 348 SkColor* result) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 | 401 |
204 bool ExtensionActionSetIconFunction::RunExtensionAction() { | 402 bool ExtensionActionSetIconFunction::RunExtensionAction() { |
205 // setIcon can take a variant argument: either a canvas ImageData, or an | 403 // setIcon can take a variant argument: either a canvas ImageData, or an |
206 // icon index. | 404 // icon index. |
207 base::BinaryValue* binary = NULL; | 405 base::BinaryValue* binary = NULL; |
208 int icon_index; | 406 int icon_index; |
209 if (details_->GetBinary("imageData", &binary)) { | 407 if (details_->GetBinary("imageData", &binary)) { |
210 IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); | 408 IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); |
211 PickleIterator iter(bitmap_pickle); | 409 PickleIterator iter(bitmap_pickle); |
212 SkBitmap bitmap; | 410 SkBitmap bitmap; |
213 EXTENSION_FUNCTION_VALIDATE( | 411 EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); |
214 IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); | |
215 extension_action_->SetIcon(tab_id_, bitmap); | 412 extension_action_->SetIcon(tab_id_, bitmap); |
216 } else if (details_->GetInteger("iconIndex", &icon_index)) { | 413 } else if (details_->GetInteger("iconIndex", &icon_index)) { |
217 // If --enable-script-badges is on there might legitimately be an iconIndex | 414 // If --enable-script-badges is on there might legitimately be an iconIndex |
218 // set. Until we decide what to do with that, ignore. | 415 // set. Until we decide what to do with that, ignore. |
219 if (!GetExtension()->page_action()) | 416 if (!GetExtension()->page_action()) |
220 return true; | 417 return true; |
221 if (icon_index < 0 || | 418 if (icon_index < 0 || |
222 static_cast<size_t>(icon_index) >= | 419 static_cast<size_t>(icon_index) >= |
223 extension_action_->icon_paths()->size()) { | 420 extension_action_->icon_paths()->size()) { |
224 error_ = kIconIndexOutOfBounds; | 421 error_ = kIconIndexOutOfBounds; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { | 506 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { |
310 ListValue* list = new ListValue(); | 507 ListValue* list = new ListValue(); |
311 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); | 508 SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_); |
312 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); | 509 list->Append(Value::CreateIntegerValue(SkColorGetR(color))); |
313 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); | 510 list->Append(Value::CreateIntegerValue(SkColorGetG(color))); |
314 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); | 511 list->Append(Value::CreateIntegerValue(SkColorGetB(color))); |
315 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); | 512 list->Append(Value::CreateIntegerValue(SkColorGetA(color))); |
316 SetResult(list); | 513 SetResult(list); |
317 return true; | 514 return true; |
318 } | 515 } |
OLD | NEW |