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

Side by Side Diff: chrome/browser/ui/webui/options2/extension_settings_handler.cc

Issue 8930012: Revert 114236 - Options2: Pull the trigger. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/options2/extension_settings_handler.h"
6
7 #include "base/auto_reset.h"
8 #include "base/base64.h"
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/file_util.h"
13 #include "base/string_number_conversions.h"
14 #include "base/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "base/version.h"
17 #include "chrome/browser/debugger/devtools_window.h"
18 #include "chrome/browser/extensions/crx_installer.h"
19 #include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_updater.h"
22 #include "chrome/browser/extensions/extension_warning_set.h"
23 #include "chrome/browser/extensions/unpacked_installer.h"
24 #include "chrome/browser/google/google_util.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/tab_contents/background_contents.h"
27 #include "chrome/browser/ui/webui/extension_icon_source.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/chrome_view_type.h"
30 #include "chrome/common/extensions/extension.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "content/browser/browsing_instance.h"
34 #include "content/browser/renderer_host/render_view_host.h"
35 #include "content/browser/tab_contents/tab_contents.h"
36 #include "content/browser/tab_contents/tab_contents_view.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/notification_types.h"
39 #include "grit/browser_resources.h"
40 #include "grit/chromium_strings.h"
41 #include "grit/generated_resources.h"
42 #include "grit/theme_resources.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h"
45
46 namespace {
47
48 bool ShouldShowExtension(const Extension* extension) {
49 // Don't show themes since this page's UI isn't really useful for themes.
50 if (extension->is_theme())
51 return false;
52
53 // Don't show component extensions because they are only extensions as an
54 // implementation detail of Chrome.
55 if (extension->location() == Extension::COMPONENT &&
56 !CommandLine::ForCurrentProcess()->HasSwitch(
57 switches::kShowComponentExtensionOptions))
58 return false;
59
60 // Always show unpacked extensions and apps.
61 if (extension->location() == Extension::LOAD)
62 return true;
63
64 // Unless they are unpacked, never show hosted apps.
65 if (extension->is_hosted_app())
66 return false;
67
68 return true;
69 }
70
71 } // namespace
72
73 ///////////////////////////////////////////////////////////////////////////////
74 //
75 // ExtensionSettingsHandler
76 //
77 ///////////////////////////////////////////////////////////////////////////////
78
79 ExtensionSettingsHandler::ExtensionSettingsHandler()
80 : extension_service_(NULL),
81 ignore_notifications_(false),
82 deleting_rvh_(NULL),
83 registered_for_notifications_(false) {
84 }
85
86 ExtensionSettingsHandler::~ExtensionSettingsHandler() {
87 // There may be pending file dialogs, we need to tell them that we've gone
88 // away so they don't try and call back to us.
89 if (load_extension_dialog_.get())
90 load_extension_dialog_->ListenerDestroyed();
91
92 registrar_.RemoveAll();
93 }
94
95 // static
96 void ExtensionSettingsHandler::RegisterUserPrefs(PrefService* prefs) {
97 prefs->RegisterBooleanPref(prefs::kExtensionsUIDeveloperMode,
98 false,
99 PrefService::SYNCABLE_PREF);
100 }
101
102 void ExtensionSettingsHandler::RegisterMessages() {
103 web_ui_->RegisterMessageCallback("extensionSettingsRequestExtensionsData",
104 base::Bind(&ExtensionSettingsHandler::HandleRequestExtensionsData,
105 base::Unretained(this)));
106 web_ui_->RegisterMessageCallback("extensionSettingsToggleDeveloperMode",
107 base::Bind(&ExtensionSettingsHandler::HandleToggleDeveloperMode,
108 base::Unretained(this)));
109 web_ui_->RegisterMessageCallback("extensionSettingsInspect",
110 base::Bind(&ExtensionSettingsHandler::HandleInspectMessage,
111 base::Unretained(this)));
112 web_ui_->RegisterMessageCallback("extensionSettingsReload",
113 base::Bind(&ExtensionSettingsHandler::HandleReloadMessage,
114 base::Unretained(this)));
115 web_ui_->RegisterMessageCallback("extensionSettingsEnable",
116 base::Bind(&ExtensionSettingsHandler::HandleEnableMessage,
117 base::Unretained(this)));
118 web_ui_->RegisterMessageCallback("extensionSettingsEnableIncognito",
119 base::Bind(&ExtensionSettingsHandler::HandleEnableIncognitoMessage,
120 base::Unretained(this)));
121 web_ui_->RegisterMessageCallback("extensionSettingsAllowFileAccess",
122 base::Bind(&ExtensionSettingsHandler::HandleAllowFileAccessMessage,
123 base::Unretained(this)));
124 web_ui_->RegisterMessageCallback("extensionSettingsUninstall",
125 base::Bind(&ExtensionSettingsHandler::HandleUninstallMessage,
126 base::Unretained(this)));
127 web_ui_->RegisterMessageCallback("extensionSettingsOptions",
128 base::Bind(&ExtensionSettingsHandler::HandleOptionsMessage,
129 base::Unretained(this)));
130 web_ui_->RegisterMessageCallback("extensionSettingsShowButton",
131 base::Bind(&ExtensionSettingsHandler::HandleShowButtonMessage,
132 base::Unretained(this)));
133 web_ui_->RegisterMessageCallback("extensionSettingsLoad",
134 base::Bind(&ExtensionSettingsHandler::HandleLoadMessage,
135 base::Unretained(this)));
136 web_ui_->RegisterMessageCallback("extensionSettingsAutoupdate",
137 base::Bind(&ExtensionSettingsHandler::HandleAutoUpdateMessage,
138 base::Unretained(this)));
139 web_ui_->RegisterMessageCallback("extensionSettingsSelectFilePath",
140 base::Bind(&ExtensionSettingsHandler::HandleSelectFilePathMessage,
141 base::Unretained(this)));
142 }
143
144 void ExtensionSettingsHandler::HandleRequestExtensionsData(
145 const ListValue* args) {
146 DictionaryValue results;
147
148 // Add the extensions to the results structure.
149 ListValue *extensions_list = new ListValue();
150
151 ExtensionWarningSet* warnings = extension_service_->extension_warnings();
152
153 const ExtensionSet* extensions = extension_service_->extensions();
154 for (ExtensionSet::const_iterator extension = extensions->begin();
155 extension != extensions->end(); ++extension) {
156 if (ShouldShowExtension(*extension)) {
157 extensions_list->Append(CreateExtensionDetailValue(
158 extension_service_,
159 *extension,
160 GetActivePagesForExtension(*extension),
161 warnings,
162 true, false)); // enabled, terminated
163 }
164 }
165 extensions = extension_service_->disabled_extensions();
166 for (ExtensionSet::const_iterator extension = extensions->begin();
167 extension != extensions->end(); ++extension) {
168 if (ShouldShowExtension(*extension)) {
169 extensions_list->Append(CreateExtensionDetailValue(
170 extension_service_,
171 *extension,
172 GetActivePagesForExtension(*extension),
173 warnings,
174 false, false)); // enabled, terminated
175 }
176 }
177 extensions = extension_service_->terminated_extensions();
178 std::vector<ExtensionPage> empty_pages;
179 for (ExtensionSet::const_iterator extension = extensions->begin();
180 extension != extensions->end(); ++extension) {
181 if (ShouldShowExtension(*extension)) {
182 extensions_list->Append(CreateExtensionDetailValue(
183 extension_service_,
184 *extension,
185 empty_pages, // Terminated process has no active pages.
186 warnings,
187 false, true)); // enabled, terminated
188 }
189 }
190 results.Set("extensions", extensions_list);
191
192 Profile* profile = Profile::FromWebUI(web_ui_);
193 bool developer_mode =
194 profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
195 results.SetBoolean("developerMode", developer_mode);
196
197 web_ui_->CallJavascriptFunction("ExtensionSettings.returnExtensionsData",
198 results);
199
200 MaybeRegisterForNotifications();
201 }
202
203 void ExtensionSettingsHandler::MaybeRegisterForNotifications() {
204 if (registered_for_notifications_)
205 return;
206
207 registered_for_notifications_ = true;
208 Profile* profile = Profile::FromWebUI(web_ui_);
209
210 // Register for notifications that we need to reload the page.
211 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
212 content::Source<Profile>(profile));
213 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
214 content::Source<Profile>(profile));
215 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
216 content::Source<Profile>(profile));
217 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED,
218 content::Source<Profile>(profile));
219 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
220 content::NotificationService::AllBrowserContextsAndSources());
221 registrar_.Add(this,
222 content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
223 content::NotificationService::AllBrowserContextsAndSources());
224 registrar_.Add(this,
225 content::NOTIFICATION_RENDER_VIEW_HOST_DELETED,
226 content::NotificationService::AllBrowserContextsAndSources());
227 registrar_.Add(this,
228 chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
229 content::NotificationService::AllBrowserContextsAndSources());
230 registrar_.Add(this,
231 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
232 content::NotificationService::AllBrowserContextsAndSources());
233 registrar_.Add(
234 this,
235 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
236 content::Source<ExtensionPrefs>(profile->GetExtensionService()->
237 extension_prefs()));
238 }
239
240 ExtensionUninstallDialog*
241 ExtensionSettingsHandler::GetExtensionUninstallDialog() {
242 if (!extension_uninstall_dialog_.get()) {
243 extension_uninstall_dialog_.reset(
244 ExtensionUninstallDialog::Create(Profile::FromWebUI(web_ui_), this));
245 }
246 return extension_uninstall_dialog_.get();
247 }
248
249 void ExtensionSettingsHandler::HandleToggleDeveloperMode(
250 const ListValue* args) {
251 Profile* profile = Profile::FromWebUI(web_ui_);
252 bool developer_mode =
253 profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
254 profile->GetPrefs()->SetBoolean(
255 prefs::kExtensionsUIDeveloperMode, !developer_mode);
256 HandleRequestExtensionsData(NULL);
257 }
258
259 void ExtensionSettingsHandler::HandleInspectMessage(const ListValue* args) {
260 std::string render_process_id_str;
261 std::string render_view_id_str;
262 int render_process_id;
263 int render_view_id;
264 CHECK_EQ(2U, args->GetSize());
265 CHECK(args->GetString(0, &render_process_id_str));
266 CHECK(args->GetString(1, &render_view_id_str));
267 CHECK(base::StringToInt(render_process_id_str, &render_process_id));
268 CHECK(base::StringToInt(render_view_id_str, &render_view_id));
269 RenderViewHost* host = RenderViewHost::FromID(render_process_id,
270 render_view_id);
271 if (!host) {
272 // This can happen if the host has gone away since the page was displayed.
273 return;
274 }
275
276 DevToolsWindow::OpenDevToolsWindow(host);
277 }
278
279 void ExtensionSettingsHandler::HandleReloadMessage(const ListValue* args) {
280 std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
281 CHECK(!extension_id.empty());
282 extension_service_->ReloadExtension(extension_id);
283 }
284
285 void ExtensionSettingsHandler::HandleEnableMessage(const ListValue* args) {
286 CHECK_EQ(2U, args->GetSize());
287 std::string extension_id, enable_str;
288 CHECK(args->GetString(0, &extension_id));
289 CHECK(args->GetString(1, &enable_str));
290
291 const Extension* extension =
292 extension_service_->GetExtensionById(extension_id, true);
293 if (!Extension::UserMayDisable(extension->location())) {
294 LOG(ERROR) << "Attempt to enable an extension that is non-usermanagable was"
295 << "made. Extension id: " << extension->id();
296 return;
297 }
298
299 if (enable_str == "true") {
300 ExtensionPrefs* prefs = extension_service_->extension_prefs();
301 if (prefs->DidExtensionEscalatePermissions(extension_id)) {
302 ShowExtensionDisabledDialog(extension_service_,
303 Profile::FromWebUI(web_ui_), extension);
304 } else {
305 extension_service_->EnableExtension(extension_id);
306 }
307 } else {
308 extension_service_->DisableExtension(extension_id);
309 }
310 }
311
312 void ExtensionSettingsHandler::HandleEnableIncognitoMessage(
313 const ListValue* args) {
314 CHECK_EQ(2U, args->GetSize());
315 std::string extension_id, enable_str;
316 CHECK(args->GetString(0, &extension_id));
317 CHECK(args->GetString(1, &enable_str));
318 const Extension* extension =
319 extension_service_->GetExtensionById(extension_id, true);
320 DCHECK(extension);
321
322 // Flipping the incognito bit will generate unload/load notifications for the
323 // extension, but we don't want to reload the page, because a) we've already
324 // updated the UI to reflect the change, and b) we want the yellow warning
325 // text to stay until the user has left the page.
326 //
327 // TODO(aa): This creates crapiness in some cases. For example, in a main
328 // window, when toggling this, the browser action will flicker because it gets
329 // unloaded, then reloaded. It would be better to have a dedicated
330 // notification for this case.
331 //
332 // Bug: http://crbug.com/41384
333 AutoReset<bool> auto_reset_ignore_notifications(&ignore_notifications_, true);
334 extension_service_->SetIsIncognitoEnabled(extension->id(),
335 enable_str == "true");
336 }
337
338 void ExtensionSettingsHandler::HandleAllowFileAccessMessage(
339 const ListValue* args) {
340 CHECK_EQ(2U, args->GetSize());
341 std::string extension_id, allow_str;
342 CHECK(args->GetString(0, &extension_id));
343 CHECK(args->GetString(1, &allow_str));
344 const Extension* extension =
345 extension_service_->GetExtensionById(extension_id, true);
346 DCHECK(extension);
347
348 if (!Extension::UserMayDisable(extension->location())) {
349 LOG(ERROR) << "Attempt to change allow file access of an extension that is "
350 << "non-usermanagable was made. Extension id : "
351 << extension->id();
352 return;
353 }
354
355 extension_service_->SetAllowFileAccess(extension, allow_str == "true");
356 }
357
358 void ExtensionSettingsHandler::HandleUninstallMessage(const ListValue* args) {
359 std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
360 CHECK(!extension_id.empty());
361 const Extension* extension =
362 extension_service_->GetExtensionById(extension_id, true);
363 if (!extension)
364 extension = extension_service_->GetTerminatedExtension(extension_id);
365 if (!extension)
366 return;
367
368 if (!Extension::UserMayDisable(extension->location())) {
369 LOG(ERROR) << "Attempt to uninstall an extension that is non-usermanagable "
370 << "was made. Extension id : " << extension->id();
371 return;
372 }
373
374 if (!extension_id_prompting_.empty())
375 return; // Only one prompt at a time.
376
377 extension_id_prompting_ = extension_id;
378
379 GetExtensionUninstallDialog()->ConfirmUninstall(extension);
380 }
381
382 void ExtensionSettingsHandler::ExtensionUninstallAccepted() {
383 DCHECK(!extension_id_prompting_.empty());
384
385 bool was_terminated = false;
386
387 // The extension can be uninstalled in another window while the UI was
388 // showing. Do nothing in that case.
389 const Extension* extension =
390 extension_service_->GetExtensionById(extension_id_prompting_, true);
391 if (!extension) {
392 extension = extension_service_->GetTerminatedExtension(
393 extension_id_prompting_);
394 was_terminated = true;
395 }
396 if (!extension)
397 return;
398
399 extension_service_->UninstallExtension(extension_id_prompting_,
400 false, // External uninstall.
401 NULL); // Error.
402 extension_id_prompting_ = "";
403
404 // There will be no EXTENSION_UNLOADED notification for terminated
405 // extensions as they were already unloaded.
406 if (was_terminated)
407 HandleRequestExtensionsData(NULL);
408 }
409
410 void ExtensionSettingsHandler::ExtensionUninstallCanceled() {
411 extension_id_prompting_ = "";
412 }
413
414 void ExtensionSettingsHandler::HandleOptionsMessage(const ListValue* args) {
415 const Extension* extension = GetExtension(args);
416 if (!extension || extension->options_url().is_empty())
417 return;
418 Profile::FromWebUI(web_ui_)->GetExtensionProcessManager()->OpenOptionsPage(
419 extension, NULL);
420 }
421
422 void ExtensionSettingsHandler::HandleShowButtonMessage(const ListValue* args) {
423 const Extension* extension = GetExtension(args);
424 extension_service_->SetBrowserActionVisibility(extension, true);
425 }
426
427 void ExtensionSettingsHandler::HandleLoadMessage(const ListValue* args) {
428 FilePath::StringType string_path;
429 CHECK_EQ(1U, args->GetSize()) << args->GetSize();
430 CHECK(args->GetString(0, &string_path));
431 extensions::UnpackedInstaller::Create(extension_service_)->
432 Load(FilePath(string_path));
433 }
434
435 void ExtensionSettingsHandler::ShowAlert(const std::string& message) {
436 ListValue arguments;
437 arguments.Append(Value::CreateStringValue(message));
438 web_ui_->CallJavascriptFunction("alert", arguments);
439 }
440
441 void ExtensionSettingsHandler::HandleAutoUpdateMessage(const ListValue* args) {
442 ExtensionUpdater* updater = extension_service_->updater();
443 if (updater)
444 updater->CheckNow();
445 }
446
447 void ExtensionSettingsHandler::HandleSelectFilePathMessage(
448 const ListValue* args) {
449 std::string select_type;
450 std::string operation;
451 CHECK_EQ(2U, args->GetSize());
452 CHECK(args->GetString(0, &select_type));
453 CHECK(args->GetString(1, &operation));
454
455 SelectFileDialog::Type type = SelectFileDialog::SELECT_FOLDER;
456 SelectFileDialog::FileTypeInfo info;
457 int file_type_index = 0;
458 if (select_type == "file")
459 type = SelectFileDialog::SELECT_OPEN_FILE;
460
461 string16 select_title;
462 if (operation == "load") {
463 select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
464 } else if (operation == "packRoot") {
465 select_title = l10n_util::GetStringUTF16(
466 IDS_EXTENSION_PACK_DIALOG_SELECT_ROOT);
467 } else if (operation == "pem") {
468 select_title = l10n_util::GetStringUTF16(
469 IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
470 info.extensions.push_back(std::vector<FilePath::StringType>());
471 info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
472 info.extension_description_overrides.push_back(
473 l10n_util::GetStringUTF16(
474 IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
475 info.include_all_files = true;
476 file_type_index = 1;
477 } else {
478 NOTREACHED();
479 return;
480 }
481
482 load_extension_dialog_ = SelectFileDialog::Create(this);
483 load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info,
484 file_type_index, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
485 web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
486 }
487
488
489 void ExtensionSettingsHandler::FileSelected(const FilePath& path, int index,
490 void* params) {
491 // Add the extensions to the results structure.
492 ListValue results;
493 results.Append(Value::CreateStringValue(path.value()));
494 web_ui_->CallJavascriptFunction("window.handleFilePathSelected", results);
495 }
496
497 void ExtensionSettingsHandler::MultiFilesSelected(
498 const std::vector<FilePath>& files, void* params) {
499 NOTREACHED();
500 }
501
502 void ExtensionSettingsHandler::GetLocalizedValues(
503 DictionaryValue* localized_strings) {
504 DCHECK(localized_strings);
505
506 RegisterTitle(localized_strings, "extensionSettings",
507 IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);
508
509 localized_strings->SetString("extensionSettingsVisitWebsite",
510 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE));
511
512 localized_strings->SetString("extensionSettingsDeveloperMode",
513 l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_LINK));
514 localized_strings->SetString("extensionSettingsNoExtensions",
515 l10n_util::GetStringUTF16(IDS_EXTENSIONS_NONE_INSTALLED));
516 localized_strings->SetString("extensionSettingsSuggestGallery",
517 l10n_util::GetStringFUTF16(IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY,
518 ASCIIToUTF16("<a href='") +
519 ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
520 GURL(extension_urls::GetWebstoreLaunchURL())).spec()) +
521 ASCIIToUTF16("'>"),
522 ASCIIToUTF16("</a>")));
523 localized_strings->SetString("extensionSettingsGetMoreExtensions",
524 ASCIIToUTF16("<a href='") +
525 ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
526 GURL(extension_urls::GetWebstoreLaunchURL())).spec()) +
527 ASCIIToUTF16("'>") +
528 l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS) +
529 ASCIIToUTF16("</a>"));
530 localized_strings->SetString("extensionSettingsExtensionId",
531 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID));
532 localized_strings->SetString("extensionSettingsExtensionPath",
533 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PATH));
534 localized_strings->SetString("extensionSettingsInspectViews",
535 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_VIEWS));
536 localized_strings->SetString("viewIncognito",
537 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO));
538 localized_strings->SetString("extensionSettingsEnable",
539 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE));
540 localized_strings->SetString("extensionSettingsEnabled",
541 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLED));
542 localized_strings->SetString("extensionSettingsRemove",
543 l10n_util::GetStringUTF16(IDS_EXTENSIONS_REMOVE));
544 localized_strings->SetString("extensionSettingsEnableIncognito",
545 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_INCOGNITO));
546 localized_strings->SetString("extensionSettingsAllowFileAccess",
547 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_FILE_ACCESS));
548 localized_strings->SetString("extensionSettingsIncognitoWarning",
549 l10n_util::GetStringFUTF16(IDS_EXTENSIONS_INCOGNITO_WARNING,
550 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
551 localized_strings->SetString("extensionSettingsReload",
552 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD));
553 localized_strings->SetString("extensionSettingsOptions",
554 l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS));
555 localized_strings->SetString("extensionSettingsPolicyControlled",
556 l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED));
557 localized_strings->SetString("extensionSettingsShowButton",
558 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON));
559 localized_strings->SetString("extensionSettingsLoadUnpackedButton",
560 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON));
561 localized_strings->SetString("extensionSettingsPackButton",
562 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PACK_BUTTON));
563 localized_strings->SetString("extensionSettingsUpdateButton",
564 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UPDATE_BUTTON));
565 localized_strings->SetString("extensionSettingsCrashMessage",
566 l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION));
567 localized_strings->SetString("extensionSettingsInDevelopment",
568 l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT));
569 localized_strings->SetString("extensionSettingsWarningsTitle",
570 l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_TITLE));
571 localized_strings->SetString("extensionSettingsShowDetails",
572 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS));
573 localized_strings->SetString("extensionSettingsHideDetails",
574 l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS));
575 }
576
577 void ExtensionSettingsHandler::Initialize() {
578 }
579
580 WebUIMessageHandler* ExtensionSettingsHandler::Attach(WebUI* web_ui) {
581 // Call through to superclass.
582 WebUIMessageHandler* handler = OptionsPage2UIHandler::Attach(web_ui);
583
584 extension_service_ = Profile::FromWebUI(web_ui_)
585 ->GetOriginalProfile()->GetExtensionService();
586
587 // Return result from the superclass.
588 return handler;
589 }
590
591 void ExtensionSettingsHandler::Observe(
592 int type,
593 const content::NotificationSource& source,
594 const content::NotificationDetails& details) {
595 Profile* profile = Profile::FromWebUI(web_ui_);
596 Profile* source_profile = NULL;
597 switch (type) {
598 // We listen for notifications that will result in the page being
599 // repopulated with data twice for the same event in certain cases.
600 // For instance, EXTENSION_LOADED & EXTENSION_HOST_CREATED because
601 // we don't know about the views for an extension at EXTENSION_LOADED, but
602 // if we only listen to EXTENSION_HOST_CREATED, we'll miss extensions
603 // that don't have a process at startup.
604 //
605 // Doing it this way gets everything but causes the page to be rendered
606 // more than we need. It doesn't seem to result in any noticeable flicker.
607 case content::NOTIFICATION_RENDER_VIEW_HOST_DELETED:
608 deleting_rvh_ = content::Source<RenderViewHost>(source).ptr();
609 // Fall through.
610 case content::NOTIFICATION_RENDER_VIEW_HOST_CREATED:
611 source_profile = Profile::FromBrowserContext(
612 content::Source<RenderViewHost>(source)->site_instance()->
613 browsing_instance()->browser_context());
614 if (!profile->IsSameProfile(source_profile))
615 return;
616 MaybeUpdateAfterNotification();
617 break;
618 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED:
619 deleting_rvh_ = content::Details<BackgroundContents>(details)->
620 tab_contents()->render_view_host();
621 // Fall through.
622 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED:
623 case chrome::NOTIFICATION_EXTENSION_HOST_CREATED:
624 source_profile = content::Source<Profile>(source).ptr();
625 if (!profile->IsSameProfile(source_profile))
626 return;
627 MaybeUpdateAfterNotification();
628 break;
629 case chrome::NOTIFICATION_EXTENSION_LOADED:
630 case chrome::NOTIFICATION_EXTENSION_UNLOADED:
631 case chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED:
632 case chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED:
633 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED:
634 MaybeUpdateAfterNotification();
635 break;
636 default:
637 NOTREACHED();
638 }
639 }
640
641 const Extension* ExtensionSettingsHandler::GetExtension(const ListValue* args) {
642 std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
643 CHECK(!extension_id.empty());
644 return extension_service_->GetExtensionById(extension_id, true);
645 }
646
647 void ExtensionSettingsHandler::MaybeUpdateAfterNotification() {
648 TabContents* contents = web_ui_->tab_contents();
649 if (!ignore_notifications_ && contents && contents->render_view_host())
650 HandleRequestExtensionsData(NULL);
651 deleting_rvh_ = NULL;
652 }
653
654 // Static
655 DictionaryValue* ExtensionSettingsHandler::CreateExtensionDetailValue(
656 ExtensionService* service, const Extension* extension,
657 const std::vector<ExtensionPage>& pages,
658 const ExtensionWarningSet* warnings_set,
659 bool enabled, bool terminated) {
660 DictionaryValue* extension_data = new DictionaryValue();
661 GURL icon =
662 ExtensionIconSource::GetIconURL(extension,
663 Extension::EXTENSION_ICON_MEDIUM,
664 ExtensionIconSet::MATCH_BIGGER,
665 !enabled, NULL);
666 extension_data->SetString("id", extension->id());
667 extension_data->SetString("name", extension->name());
668 extension_data->SetString("description", extension->description());
669 if (extension->location() == Extension::LOAD)
670 extension_data->SetString("path", extension->path().value());
671 extension_data->SetString("version", extension->version()->GetString());
672 extension_data->SetString("icon", icon.spec());
673 extension_data->SetBoolean("isUnpacked",
674 extension->location() == Extension::LOAD);
675 extension_data->SetBoolean("mayDisable",
676 Extension::UserMayDisable(extension->location()));
677 extension_data->SetBoolean("enabled", enabled);
678 extension_data->SetBoolean("terminated", terminated);
679 extension_data->SetBoolean("enabledIncognito",
680 service ? service->IsIncognitoEnabled(extension->id()) : false);
681 extension_data->SetBoolean("wantsFileAccess", extension->wants_file_access());
682 extension_data->SetBoolean("allowFileAccess",
683 service ? service->AllowFileAccess(extension) : false);
684 extension_data->SetBoolean("allow_reload",
685 extension->location() == Extension::LOAD);
686 extension_data->SetBoolean("is_hosted_app", extension->is_hosted_app());
687
688 // Determine the sort order: Extensions loaded through --load-extensions show
689 // up at the top. Disabled extensions show up at the bottom.
690 if (extension->location() == Extension::LOAD)
691 extension_data->SetInteger("order", 1);
692 else
693 extension_data->SetInteger("order", 2);
694
695 if (!extension->options_url().is_empty() && enabled)
696 extension_data->SetString("options_url", extension->options_url().spec());
697
698 if (service && !service->GetBrowserActionVisibility(extension))
699 extension_data->SetBoolean("enable_show_button", true);
700
701 // Add views
702 ListValue* views = new ListValue;
703 for (std::vector<ExtensionPage>::const_iterator iter = pages.begin();
704 iter != pages.end(); ++iter) {
705 DictionaryValue* view_value = new DictionaryValue;
706 if (iter->url.scheme() == chrome::kExtensionScheme) {
707 // No leading slash.
708 view_value->SetString("path", iter->url.path().substr(1));
709 } else {
710 // For live pages, use the full URL.
711 view_value->SetString("path", iter->url.spec());
712 }
713 view_value->SetInteger("renderViewId", iter->render_view_id);
714 view_value->SetInteger("renderProcessId", iter->render_process_id);
715 view_value->SetBoolean("incognito", iter->incognito);
716 views->Append(view_value);
717 }
718 extension_data->Set("views", views);
719 extension_data->SetBoolean("hasPopupAction",
720 extension->browser_action() || extension->page_action());
721 extension_data->SetString("homepageUrl", extension->GetHomepageURL().spec());
722
723 // Add warnings.
724 ListValue* warnings_list = new ListValue;
725 if (warnings_set) {
726 std::set<ExtensionWarningSet::WarningType> warnings;
727 warnings_set->GetWarningsAffectingExtension(extension->id(), &warnings);
728
729 for (std::set<ExtensionWarningSet::WarningType>::const_iterator iter =
730 warnings.begin();
731 iter != warnings.end();
732 ++iter) {
733 string16 warning_string(ExtensionWarningSet::GetLocalizedWarning(*iter));
734 warnings_list->Append(Value::CreateStringValue(warning_string));
735 }
736 }
737 extension_data->Set("warnings", warnings_list);
738
739 return extension_data;
740 }
741
742 std::vector<ExtensionPage> ExtensionSettingsHandler::GetActivePagesForExtension(
743 const Extension* extension) {
744 std::vector<ExtensionPage> result;
745
746 // Get the extension process's active views.
747 ExtensionProcessManager* process_manager =
748 extension_service_->profile()->GetExtensionProcessManager();
749 GetActivePagesForExtensionProcess(
750 process_manager->GetRenderViewHostsForExtension(
751 extension->id()), &result);
752
753 // Repeat for the incognito process, if applicable.
754 if (extension_service_->profile()->HasOffTheRecordProfile() &&
755 extension->incognito_split_mode()) {
756 ExtensionProcessManager* process_manager =
757 extension_service_->profile()->GetOffTheRecordProfile()->
758 GetExtensionProcessManager();
759 GetActivePagesForExtensionProcess(
760 process_manager->GetRenderViewHostsForExtension(
761 extension->id()), &result);
762 }
763
764 return result;
765 }
766
767 void ExtensionSettingsHandler::GetActivePagesForExtensionProcess(
768 const std::set<RenderViewHost*>& views,
769 std::vector<ExtensionPage> *result) {
770 for (std::set<RenderViewHost*>::const_iterator iter = views.begin();
771 iter != views.end(); ++iter) {
772 RenderViewHost* host = *iter;
773 int host_type = host->delegate()->GetRenderViewType();
774 if (host == deleting_rvh_ ||
775 chrome::VIEW_TYPE_EXTENSION_POPUP == host_type ||
776 chrome::VIEW_TYPE_EXTENSION_DIALOG == host_type)
777 continue;
778
779 GURL url = host->delegate()->GetURL();
780 content::RenderProcessHost* process = host->process();
781 result->push_back(
782 ExtensionPage(url, process->GetID(), host->routing_id(),
783 process->GetBrowserContext()->IsOffTheRecord()));
784 }
785 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698