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

Side by Side Diff: chrome/browser/extensions/extensions_ui.cc

Issue 360039: Fix bug where we were not displaying icons in the management (Closed)
Patch Set: update test data Created 11 years, 1 month 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) 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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698