OLD | NEW |
---|---|
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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/extensions_ui.h" | 5 #include "chrome/browser/extensions/extensions_ui.h" |
6 | 6 |
7 #include "app/gfx/codec/png_codec.h" | |
8 #include "app/gfx/color_utils.h" | |
9 #include "app/gfx/skbitmap_operations.h" | |
7 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 11 #include "app/resource_bundle.h" |
12 #include "base/file_util.h" | |
9 #include "base/string_util.h" | 13 #include "base/string_util.h" |
10 #include "base/thread.h" | 14 #include "base/thread.h" |
11 #include "chrome/browser/browser.h" | 15 #include "chrome/browser/browser.h" |
12 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/debugger/devtools_manager.h" | 17 #include "chrome/browser/debugger/devtools_manager.h" |
14 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 18 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
15 #include "chrome/browser/extensions/extension_message_service.h" | 19 #include "chrome/browser/extensions/extension_message_service.h" |
16 #include "chrome/browser/extensions/extensions_service.h" | 20 #include "chrome/browser/extensions/extensions_service.h" |
17 #include "chrome/browser/extensions/extension_updater.h" | 21 #include "chrome/browser/extensions/extension_updater.h" |
18 #include "chrome/browser/profile.h" | 22 #include "chrome/browser/profile.h" |
19 #include "chrome/browser/renderer_host/render_process_host.h" | 23 #include "chrome/browser/renderer_host/render_process_host.h" |
20 #include "chrome/browser/renderer_host/render_widget_host.h" | 24 #include "chrome/browser/renderer_host/render_widget_host.h" |
21 #include "chrome/browser/renderer_host/render_view_host.h" | 25 #include "chrome/browser/renderer_host/render_view_host.h" |
22 #include "chrome/browser/tab_contents/tab_contents.h" | 26 #include "chrome/browser/tab_contents/tab_contents.h" |
23 #include "chrome/browser/tab_contents/tab_contents_view.h" | 27 #include "chrome/browser/tab_contents/tab_contents_view.h" |
24 #include "chrome/common/extensions/extension.h" | 28 #include "chrome/common/extensions/extension.h" |
25 #include "chrome/common/extensions/extension_error_reporter.h" | 29 #include "chrome/common/extensions/extension_error_reporter.h" |
26 #include "chrome/common/extensions/user_script.h" | 30 #include "chrome/common/extensions/user_script.h" |
27 #include "chrome/common/extensions/url_pattern.h" | 31 #include "chrome/common/extensions/url_pattern.h" |
28 #include "chrome/common/jstemplate_builder.h" | 32 #include "chrome/common/jstemplate_builder.h" |
29 #include "chrome/common/notification_service.h" | 33 #include "chrome/common/notification_service.h" |
30 #include "chrome/common/notification_type.h" | 34 #include "chrome/common/notification_type.h" |
31 #include "chrome/common/pref_names.h" | 35 #include "chrome/common/pref_names.h" |
32 #include "chrome/common/pref_service.h" | 36 #include "chrome/common/pref_service.h" |
33 #include "chrome/common/url_constants.h" | 37 #include "chrome/common/url_constants.h" |
38 #include "net/base/base64.h" | |
34 #include "net/base/net_util.h" | 39 #include "net/base/net_util.h" |
35 | |
Finnur
2009/11/05 03:55:08
nit: Did you delete this line on purpose?
I think
| |
36 #include "grit/browser_resources.h" | 40 #include "grit/browser_resources.h" |
37 #include "grit/generated_resources.h" | 41 #include "grit/generated_resources.h" |
38 #include "grit/theme_resources.h" | 42 #include "grit/theme_resources.h" |
43 #include "webkit/glue/image_decoder.h" | |
39 | 44 |
40 //////////////////////////////////////////////////////////////////////////////// | 45 //////////////////////////////////////////////////////////////////////////////// |
41 // | 46 // |
42 // ExtensionsHTMLSource | 47 // ExtensionsHTMLSource |
43 // | 48 // |
44 //////////////////////////////////////////////////////////////////////////////// | 49 //////////////////////////////////////////////////////////////////////////////// |
45 | 50 |
46 ExtensionsUIHTMLSource::ExtensionsUIHTMLSource() | 51 ExtensionsUIHTMLSource::ExtensionsUIHTMLSource() |
47 : DataSource(chrome::kChromeUIExtensionsHost, MessageLoop::current()) { | 52 : DataSource(chrome::kChromeUIExtensionsHost, MessageLoop::current()) { |
48 } | 53 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html); | 113 jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html); |
109 jstemplate_builder::AppendJsTemplateSourceHtml(&full_html); | 114 jstemplate_builder::AppendJsTemplateSourceHtml(&full_html); |
110 | 115 |
111 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); | 116 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
112 html_bytes->data.resize(full_html.size()); | 117 html_bytes->data.resize(full_html.size()); |
113 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); | 118 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); |
114 | 119 |
115 SendResponse(request_id, html_bytes); | 120 SendResponse(request_id, html_bytes); |
116 } | 121 } |
117 | 122 |
123 | |
124 /////////////////////////////////////////////////////////////////////////////// | |
125 // | |
126 // ExtensionsDOMHandler::IconLoader | |
127 // | |
128 /////////////////////////////////////////////////////////////////////////////// | |
Finnur
2009/11/05 03:55:08
nit: Add one more / to complete 80 columns. :)
| |
129 | |
130 ExtensionsDOMHandler::IconLoader::IconLoader(ExtensionsDOMHandler* handler) | |
131 : handler_(handler) { | |
132 } | |
133 | |
134 void ExtensionsDOMHandler::IconLoader::LoadIcons( | |
135 std::vector<ExtensionResource>* icons, DictionaryValue* json) { | |
136 ChromeThread::PostTask( | |
137 ChromeThread::FILE, FROM_HERE, | |
138 NewRunnableMethod(this, | |
139 &IconLoader::LoadIconsOnFileThread, icons, json)); | |
140 } | |
141 | |
142 void ExtensionsDOMHandler::IconLoader::Cancel() { | |
143 handler_ = NULL; | |
144 } | |
145 | |
146 void ExtensionsDOMHandler::IconLoader::LoadIconsOnFileThread( | |
147 std::vector<ExtensionResource>* icons, DictionaryValue* json) { | |
148 scoped_ptr<std::vector<ExtensionResource> > icons_deleter(icons); | |
149 scoped_ptr<DictionaryValue> json_deleter(json); | |
150 | |
151 ListValue* extensions = NULL; | |
152 CHECK(json->GetList(L"extensions", &extensions)); | |
153 | |
154 for (size_t i = 0; i < icons->size(); ++i) { | |
155 DictionaryValue* extension = NULL; | |
156 CHECK(extensions->GetDictionary(static_cast<int>(i), &extension)); | |
157 | |
158 // Read the file. | |
159 std::string file_contents; | |
160 if (icons->at(i).relative_path().empty() || | |
161 !file_util::ReadFileToString(icons->at(i).GetFilePath(), | |
162 &file_contents)) { | |
163 // If there's no icon, default to the puzzle icon. This is safe to do from | |
164 // the file thread. | |
165 file_contents = ResourceBundle::GetSharedInstance().GetDataResource( | |
166 IDR_INFOBAR_PLUGIN_INSTALL); | |
167 } | |
168 | |
169 // If the extension is disabled, we desaturate the icon to add to the | |
170 // disabledness effect. | |
171 bool enabled = false; | |
172 CHECK(extension->GetBoolean(L"enabled", &enabled)); | |
Finnur
2009/11/05 03:55:08
nit: Why CHECK here instead of DCHECK?
| |
173 if (!enabled) { | |
174 const unsigned char* data = | |
175 reinterpret_cast<const unsigned char*>(file_contents.data()); | |
176 webkit_glue::ImageDecoder decoder; | |
177 scoped_ptr<SkBitmap> decoded(new SkBitmap()); | |
178 *decoded = decoder.Decode(data, file_contents.length()); | |
179 | |
180 // Desaturate the icon and lighten it a bit. | |
181 color_utils::HSL shift = {-1, 0, 0.6}; | |
182 *decoded = SkBitmapOperations::CreateHSLShiftedBitmap(*decoded, shift); | |
183 | |
184 std::vector<unsigned char> output; | |
185 gfx::PNGCodec::EncodeBGRASkBitmap(*decoded, false, &output); | |
186 | |
187 // Lame, but we must make a copy of this now, because base64 doesn't take | |
188 // the same input type. | |
189 file_contents.assign(reinterpret_cast<char*>(&output.front()), | |
190 output.size()); | |
191 } | |
192 | |
193 // Create a data URL (all icons are converted to PNGs during unpacking). | |
194 std::string base64_encoded; | |
195 net::Base64Encode(file_contents, &base64_encoded); | |
196 GURL icon_url("data:image/png;base64," + base64_encoded); | |
197 | |
198 extension->SetString(L"icon", icon_url.spec()); | |
199 } | |
200 | |
201 ChromeThread::PostTask( | |
202 ChromeThread::UI, FROM_HERE, | |
203 NewRunnableMethod(this, &IconLoader::ReportResultOnUIThread, | |
204 json_deleter.release())); | |
205 } | |
206 | |
207 void ExtensionsDOMHandler::IconLoader::ReportResultOnUIThread( | |
208 DictionaryValue* json) { | |
209 if (handler_) | |
210 handler_->OnIconsLoaded(json); | |
211 } | |
212 | |
213 | |
118 /////////////////////////////////////////////////////////////////////////////// | 214 /////////////////////////////////////////////////////////////////////////////// |
119 // | 215 // |
120 // ExtensionsDOMHandler | 216 // ExtensionsDOMHandler |
121 // | 217 // |
122 /////////////////////////////////////////////////////////////////////////////// | 218 /////////////////////////////////////////////////////////////////////////////// |
123 | 219 |
124 ExtensionsDOMHandler::ExtensionsDOMHandler(ExtensionsService* extension_service) | 220 ExtensionsDOMHandler::ExtensionsDOMHandler(ExtensionsService* extension_service) |
125 : extensions_service_(extension_service) { | 221 : extensions_service_(extension_service) { |
126 } | 222 } |
127 | 223 |
(...skipping 16 matching lines...) Expand all Loading... | |
144 NewCallback(this, &ExtensionsDOMHandler::HandleLoadMessage)); | 240 NewCallback(this, &ExtensionsDOMHandler::HandleLoadMessage)); |
145 dom_ui_->RegisterMessageCallback("pack", | 241 dom_ui_->RegisterMessageCallback("pack", |
146 NewCallback(this, &ExtensionsDOMHandler::HandlePackMessage)); | 242 NewCallback(this, &ExtensionsDOMHandler::HandlePackMessage)); |
147 dom_ui_->RegisterMessageCallback("autoupdate", | 243 dom_ui_->RegisterMessageCallback("autoupdate", |
148 NewCallback(this, &ExtensionsDOMHandler::HandleAutoUpdateMessage)); | 244 NewCallback(this, &ExtensionsDOMHandler::HandleAutoUpdateMessage)); |
149 dom_ui_->RegisterMessageCallback("selectFilePath", | 245 dom_ui_->RegisterMessageCallback("selectFilePath", |
150 NewCallback(this, &ExtensionsDOMHandler::HandleSelectFilePathMessage)); | 246 NewCallback(this, &ExtensionsDOMHandler::HandleSelectFilePathMessage)); |
151 } | 247 } |
152 | 248 |
153 void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) { | 249 void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) { |
154 DictionaryValue results; | 250 DictionaryValue* results = new DictionaryValue(); |
155 | 251 |
156 // Add the extensions to the results structure. | 252 // Add the extensions to the results structure. |
157 ListValue *extensions_list = new ListValue(); | 253 ListValue *extensions_list = new ListValue(); |
254 | |
255 // Stores the icon resource for each of the extensions in extensions_list. We | |
256 // build up a list of them here, then load them on the file thread in | |
257 // ::LoadIcons(). | |
258 std::vector<ExtensionResource>* extension_icons = | |
259 new std::vector<ExtensionResource>(); | |
260 | |
158 const ExtensionList* extensions = extensions_service_->extensions(); | 261 const ExtensionList* extensions = extensions_service_->extensions(); |
159 for (ExtensionList::const_iterator extension = extensions->begin(); | 262 for (ExtensionList::const_iterator extension = extensions->begin(); |
160 extension != extensions->end(); ++extension) { | 263 extension != extensions->end(); ++extension) { |
161 // Don't show the themes since this page's UI isn't really useful for | 264 // Don't show the themes since this page's UI isn't really useful for |
162 // themes. | 265 // themes. |
163 if (!(*extension)->IsTheme()) { | 266 if (!(*extension)->IsTheme()) { |
164 extensions_list->Append(CreateExtensionDetailValue( | 267 extensions_list->Append(CreateExtensionDetailValue( |
165 *extension, GetActivePagesForExtension((*extension)->id()), true)); | 268 *extension, GetActivePagesForExtension((*extension)->id()), true)); |
269 extension_icons->push_back(PickExtensionIcon(*extension)); | |
166 } | 270 } |
167 } | 271 } |
168 extensions = extensions_service_->disabled_extensions(); | 272 extensions = extensions_service_->disabled_extensions(); |
169 for (ExtensionList::const_iterator extension = extensions->begin(); | 273 for (ExtensionList::const_iterator extension = extensions->begin(); |
170 extension != extensions->end(); ++extension) { | 274 extension != extensions->end(); ++extension) { |
171 if (!(*extension)->IsTheme()) { | 275 if (!(*extension)->IsTheme()) { |
172 extensions_list->Append(CreateExtensionDetailValue( | 276 extensions_list->Append(CreateExtensionDetailValue( |
173 *extension, GetActivePagesForExtension((*extension)->id()), false)); | 277 *extension, GetActivePagesForExtension((*extension)->id()), false)); |
278 extension_icons->push_back(PickExtensionIcon(*extension)); | |
174 } | 279 } |
175 } | 280 } |
176 results.Set(L"extensions", extensions_list); | 281 results->Set(L"extensions", extensions_list); |
177 | 282 |
178 bool developer_mode = dom_ui_->GetProfile()->GetPrefs() | 283 bool developer_mode = dom_ui_->GetProfile()->GetPrefs() |
179 ->GetBoolean(prefs::kExtensionsUIDeveloperMode); | 284 ->GetBoolean(prefs::kExtensionsUIDeveloperMode); |
180 results.SetBoolean(L"developerMode", developer_mode); | 285 results->SetBoolean(L"developerMode", developer_mode); |
181 | 286 |
182 dom_ui_->CallJavascriptFunction(L"returnExtensionsData", results); | 287 if (icon_loader_.get()) |
288 icon_loader_->Cancel(); | |
289 | |
290 icon_loader_ = new IconLoader(this); | |
291 icon_loader_->LoadIcons(extension_icons, results); | |
292 } | |
293 | |
294 void ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) { | |
295 dom_ui_->CallJavascriptFunction(L"returnExtensionsData", *json); | |
296 delete json; | |
183 | 297 |
184 // Register for notifications that we need to reload the page. | 298 // Register for notifications that we need to reload the page. |
185 registrar_.RemoveAll(); | 299 registrar_.RemoveAll(); |
186 registrar_.Add(this, NotificationType::EXTENSION_LOADED, | 300 registrar_.Add(this, NotificationType::EXTENSION_LOADED, |
187 NotificationService::AllSources()); | 301 NotificationService::AllSources()); |
188 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, | 302 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, |
189 NotificationService::AllSources()); | 303 NotificationService::AllSources()); |
190 registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED, | 304 registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED, |
191 NotificationService::AllSources()); | 305 NotificationService::AllSources()); |
192 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED, | 306 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED, |
193 NotificationService::AllSources()); | 307 NotificationService::AllSources()); |
194 } | 308 } |
195 | 309 |
310 ExtensionResource ExtensionsDOMHandler::PickExtensionIcon( | |
311 Extension* extension) { | |
312 // Try to fetch the medium sized icon, then (if missing) go for the large one. | |
313 const std::map<int, std::string>& icons = extension->icons(); | |
314 std::map<int, std::string>::const_iterator iter = | |
315 icons.find(Extension::EXTENSION_ICON_MEDIUM); | |
316 if (iter == icons.end()) | |
317 iter = icons.find(Extension::EXTENSION_ICON_LARGE); | |
318 if (iter != icons.end()) | |
319 return extension->GetResource(iter->second); | |
320 else | |
321 return ExtensionResource(); | |
322 } | |
323 | |
196 void ExtensionsDOMHandler::HandleToggleDeveloperMode(const Value* value) { | 324 void ExtensionsDOMHandler::HandleToggleDeveloperMode(const Value* value) { |
197 bool developer_mode = dom_ui_->GetProfile()->GetPrefs() | 325 bool developer_mode = dom_ui_->GetProfile()->GetPrefs() |
198 ->GetBoolean(prefs::kExtensionsUIDeveloperMode); | 326 ->GetBoolean(prefs::kExtensionsUIDeveloperMode); |
199 dom_ui_->GetProfile()->GetPrefs()->SetBoolean( | 327 dom_ui_->GetProfile()->GetPrefs()->SetBoolean( |
200 prefs::kExtensionsUIDeveloperMode, !developer_mode); | 328 prefs::kExtensionsUIDeveloperMode, !developer_mode); |
201 } | 329 } |
202 | 330 |
203 void ExtensionsDOMHandler::HandleInspectMessage(const Value* value) { | 331 void ExtensionsDOMHandler::HandleInspectMessage(const Value* value) { |
204 std::string render_process_id_str; | 332 std::string render_process_id_str; |
205 std::string render_view_id_str; | 333 std::string render_view_id_str; |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
474 // Determine the sort order: Extensions loaded through --load-extensions show | 602 // Determine the sort order: Extensions loaded through --load-extensions show |
475 // up at the top. Disabled extensions show up at the bottom. | 603 // up at the top. Disabled extensions show up at the bottom. |
476 if (extension->location() == Extension::LOAD) | 604 if (extension->location() == Extension::LOAD) |
477 extension_data->SetInteger(L"order", 1); | 605 extension_data->SetInteger(L"order", 1); |
478 else | 606 else |
479 extension_data->SetInteger(L"order", 2); | 607 extension_data->SetInteger(L"order", 2); |
480 | 608 |
481 if (!extension->options_url().is_empty()) | 609 if (!extension->options_url().is_empty()) |
482 extension_data->SetString(L"options_url", extension->options_url().spec()); | 610 extension_data->SetString(L"options_url", extension->options_url().spec()); |
483 | 611 |
484 // Try to fetch the medium sized icon, then (if missing) go for the large one. | |
485 const std::map<int, std::string>& icons = extension->icons(); | |
486 std::map<int, std::string>::const_iterator iter = | |
487 icons.find(Extension::EXTENSION_ICON_MEDIUM); | |
488 if (iter == icons.end()) | |
489 iter = icons.find(Extension::EXTENSION_ICON_LARGE); | |
490 if (iter != icons.end()) | |
491 extension_data->SetString(L"icon", iter->second); | |
492 else | |
493 extension_data->SetString(L"icon", ""); | |
494 | |
495 // Add list of content_script detail DictionaryValues | 612 // Add list of content_script detail DictionaryValues |
496 ListValue *content_script_list = new ListValue(); | 613 ListValue *content_script_list = new ListValue(); |
497 UserScriptList content_scripts = extension->content_scripts(); | 614 UserScriptList content_scripts = extension->content_scripts(); |
498 for (UserScriptList::const_iterator script = content_scripts.begin(); | 615 for (UserScriptList::const_iterator script = content_scripts.begin(); |
499 script != content_scripts.end(); ++script) { | 616 script != content_scripts.end(); ++script) { |
500 content_script_list->Append( | 617 content_script_list->Append( |
501 CreateContentScriptDetailValue(*script, extension->path())); | 618 CreateContentScriptDetailValue(*script, extension->path())); |
502 } | 619 } |
503 extension_data->Set(L"content_scripts", content_script_list); | 620 extension_data->Set(L"content_scripts", content_script_list); |
504 | 621 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 view->routing_id())); | 660 view->routing_id())); |
544 } | 661 } |
545 } | 662 } |
546 | 663 |
547 return result; | 664 return result; |
548 } | 665 } |
549 | 666 |
550 ExtensionsDOMHandler::~ExtensionsDOMHandler() { | 667 ExtensionsDOMHandler::~ExtensionsDOMHandler() { |
551 if (pack_job_.get()) | 668 if (pack_job_.get()) |
552 pack_job_->ClearClient(); | 669 pack_job_->ClearClient(); |
670 | |
671 if (icon_loader_.get()) | |
672 icon_loader_->Cancel(); | |
553 } | 673 } |
554 | 674 |
555 // ExtensionsDOMHandler, public: ----------------------------------------------- | 675 // ExtensionsDOMHandler, public: ----------------------------------------------- |
556 | 676 |
557 ExtensionsUI::ExtensionsUI(TabContents* contents) : DOMUI(contents) { | 677 ExtensionsUI::ExtensionsUI(TabContents* contents) : DOMUI(contents) { |
558 ExtensionsService *exstension_service = | 678 ExtensionsService *exstension_service = |
559 GetProfile()->GetOriginalProfile()->GetExtensionsService(); | 679 GetProfile()->GetOriginalProfile()->GetExtensionsService(); |
560 | 680 |
561 ExtensionsDOMHandler* handler = new ExtensionsDOMHandler(exstension_service); | 681 ExtensionsDOMHandler* handler = new ExtensionsDOMHandler(exstension_service); |
562 AddMessageHandler(handler); | 682 AddMessageHandler(handler); |
(...skipping 13 matching lines...) Expand all Loading... | |
576 // static | 696 // static |
577 RefCountedMemory* ExtensionsUI::GetFaviconResourceBytes() { | 697 RefCountedMemory* ExtensionsUI::GetFaviconResourceBytes() { |
578 return ResourceBundle::GetSharedInstance(). | 698 return ResourceBundle::GetSharedInstance(). |
579 LoadImageResourceBytes(IDR_PLUGIN); | 699 LoadImageResourceBytes(IDR_PLUGIN); |
580 } | 700 } |
581 | 701 |
582 // static | 702 // static |
583 void ExtensionsUI::RegisterUserPrefs(PrefService* prefs) { | 703 void ExtensionsUI::RegisterUserPrefs(PrefService* prefs) { |
584 prefs->RegisterBooleanPref(prefs::kExtensionsUIDeveloperMode, false); | 704 prefs->RegisterBooleanPref(prefs::kExtensionsUIDeveloperMode, false); |
585 } | 705 } |
OLD | NEW |