extension_settings_handler.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/webui/extensions/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/prefs/pref_service.h" 14#include "base/string_util.h" 15#include "base/strings/string_number_conversions.h" 16#include "base/utf_string_conversions.h" 17#include "base/values.h" 18#include "base/version.h" 19#include "chrome/browser/browser_process.h" 20#include "chrome/browser/devtools/devtools_window.h" 21#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 22#include "chrome/browser/extensions/crx_installer.h" 23#include "chrome/browser/extensions/extension_action_manager.h" 24#include "chrome/browser/extensions/extension_disabled_ui.h" 25#include "chrome/browser/extensions/extension_error_reporter.h" 26#include "chrome/browser/extensions/extension_host.h" 27#include "chrome/browser/extensions/extension_service.h" 28#include "chrome/browser/extensions/extension_system.h" 29#include "chrome/browser/extensions/extension_tab_util.h" 30#include "chrome/browser/extensions/extension_warning_set.h" 31#include "chrome/browser/extensions/lazy_background_task_queue.h" 32#include "chrome/browser/extensions/management_policy.h" 33#include "chrome/browser/extensions/shell_window_registry.h" 34#include "chrome/browser/extensions/unpacked_installer.h" 35#include "chrome/browser/extensions/updater/extension_updater.h" 36#include "chrome/browser/google/google_util.h" 37#include "chrome/browser/managed_mode/managed_mode_navigation_observer.h" 38#include "chrome/browser/managed_mode/managed_user_service.h" 39#include "chrome/browser/managed_mode/managed_user_service_factory.h" 40#include "chrome/browser/profiles/profile.h" 41#include "chrome/browser/tab_contents/background_contents.h" 42#include "chrome/browser/ui/browser_finder.h" 43#include "chrome/browser/ui/chrome_select_file_policy.h" 44#include "chrome/browser/ui/extensions/application_launch.h" 45#include "chrome/browser/ui/extensions/shell_window.h" 46#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 47#include "chrome/common/chrome_notification_types.h" 48#include "chrome/common/chrome_switches.h" 49#include "chrome/common/extensions/background_info.h" 50#include "chrome/common/extensions/extension.h" 51#include "chrome/common/extensions/extension_constants.h" 52#include "chrome/common/extensions/extension_icon_set.h" 53#include "chrome/common/extensions/extension_set.h" 54#include "chrome/common/extensions/feature_switch.h" 55#include "chrome/common/extensions/incognito_handler.h" 56#include "chrome/common/extensions/manifest_url_handler.h" 57#include "chrome/common/pref_names.h" 58#include "chrome/common/url_constants.h" 59#include "components/user_prefs/pref_registry_syncable.h" 60#include "content/public/browser/notification_service.h" 61#include "content/public/browser/notification_source.h" 62#include "content/public/browser/notification_types.h" 63#include "content/public/browser/render_process_host.h" 64#include "content/public/browser/render_view_host.h" 65#include "content/public/browser/site_instance.h" 66#include "content/public/browser/web_contents.h" 67#include "content/public/browser/web_contents_view.h" 68#include "content/public/browser/web_ui.h" 69#include "content/public/browser/web_ui_data_source.h" 70#include "extensions/browser/view_type_utils.h" 71#include "extensions/common/constants.h" 72#include "grit/browser_resources.h" 73#include "grit/chromium_strings.h" 74#include "grit/generated_resources.h" 75#include "grit/theme_resources.h" 76#include "ui/base/l10n/l10n_util.h" 77#include "ui/base/resource/resource_bundle.h" 78 79 80using content::RenderViewHost; 81using content::WebContents; 82using extensions::Extension; 83using extensions::ExtensionUpdater; 84using extensions::ExtensionWarning; 85using extensions::ManagementPolicy; 86using extensions::Manifest; 87 88/////////////////////////////////////////////////////////////////////////////// 89// 90// ExtensionSettingsHandler 91// 92/////////////////////////////////////////////////////////////////////////////// 93 94ExtensionSettingsHandler::ExtensionSettingsHandler() 95 : extension_service_(NULL), 96 management_policy_(NULL), 97 ignore_notifications_(false), 98 deleting_rvh_(NULL), 99 registered_for_notifications_(false), 100 rvh_created_callback_( 101 base::Bind(&ExtensionSettingsHandler::RenderViewHostCreated, 102 base::Unretained(this))), 103 warning_service_observer_(this) { 104} 105 106ExtensionSettingsHandler::~ExtensionSettingsHandler() { 107 content::RenderViewHost::RemoveCreatedCallback(rvh_created_callback_); 108 109 // There may be pending file dialogs, we need to tell them that we've gone 110 // away so they don't try and call back to us. 111 if (load_extension_dialog_) 112 load_extension_dialog_->ListenerDestroyed(); 113} 114 115ExtensionSettingsHandler::ExtensionSettingsHandler(ExtensionService* service, 116 ManagementPolicy* policy) 117 : extension_service_(service), 118 management_policy_(policy), 119 ignore_notifications_(false), 120 deleting_rvh_(NULL), 121 registered_for_notifications_(false), 122 warning_service_observer_(this) { 123} 124 125// static 126void ExtensionSettingsHandler::RegisterUserPrefs( 127 user_prefs::PrefRegistrySyncable* registry) { 128 registry->RegisterBooleanPref( 129 prefs::kExtensionsUIDeveloperMode, 130 false, 131 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 132} 133 134DictionaryValue* ExtensionSettingsHandler::CreateExtensionDetailValue( 135 const Extension* extension, 136 const std::vector<ExtensionPage>& pages, 137 const extensions::ExtensionWarningService* warning_service) { 138 DictionaryValue* extension_data = new DictionaryValue(); 139 bool enabled = extension_service_->IsExtensionEnabled(extension->id()); 140 extension->GetBasicInfo(enabled, extension_data); 141 142 extension_data->SetBoolean("userModifiable", 143 CheckUserMayModifySettings(extension)); 144 145 GURL icon = 146 ExtensionIconSource::GetIconURL(extension, 147 extension_misc::EXTENSION_ICON_MEDIUM, 148 ExtensionIconSet::MATCH_BIGGER, 149 !enabled, NULL); 150 if (Manifest::IsUnpackedLocation(extension->location())) 151 extension_data->SetString("path", extension->path().value()); 152 extension_data->SetString("icon", icon.spec()); 153 extension_data->SetBoolean("isUnpacked", 154 Manifest::IsUnpackedLocation(extension->location())); 155 extension_data->SetBoolean("terminated", 156 extension_service_->terminated_extensions()->Contains(extension->id())); 157 extension_data->SetBoolean("enabledIncognito", 158 extension_service_->IsIncognitoEnabled(extension->id())); 159 extension_data->SetBoolean("incognitoCanBeEnabled", 160 extension->can_be_incognito_enabled()); 161 extension_data->SetBoolean("wantsFileAccess", extension->wants_file_access()); 162 extension_data->SetBoolean("allowFileAccess", 163 extension_service_->AllowFileAccess(extension)); 164 extension_data->SetBoolean("allow_activity", 165 enabled && CommandLine::ForCurrentProcess()->HasSwitch( 166 switches::kEnableExtensionActivityUI)); 167 extension_data->SetBoolean("allow_reload", 168 Manifest::IsUnpackedLocation(extension->location())); 169 extension_data->SetBoolean("is_hosted_app", extension->is_hosted_app()); 170 extension_data->SetBoolean("is_platform_app", extension->is_platform_app()); 171 extension_data->SetBoolean("homepageProvided", 172 extensions::ManifestURL::GetHomepageURL(extension).is_valid()); 173 174 // Determine the sort order: Extensions loaded through --load-extensions show 175 // up at the top. Disabled extensions show up at the bottom. 176 if (Manifest::IsUnpackedLocation(extension->location())) 177 extension_data->SetInteger("order", 1); 178 else 179 extension_data->SetInteger("order", 2); 180 181 if (!extensions::ExtensionActionAPI::GetBrowserActionVisibility( 182 extension_service_->extension_prefs(), extension->id())) { 183 extension_data->SetBoolean("enable_show_button", true); 184 } 185 186 // Add views 187 ListValue* views = new ListValue; 188 for (std::vector<ExtensionPage>::const_iterator iter = pages.begin(); 189 iter != pages.end(); ++iter) { 190 DictionaryValue* view_value = new DictionaryValue; 191 if (iter->url.scheme() == extensions::kExtensionScheme) { 192 // No leading slash. 193 view_value->SetString("path", iter->url.path().substr(1)); 194 } else { 195 // For live pages, use the full URL. 196 view_value->SetString("path", iter->url.spec()); 197 } 198 view_value->SetInteger("renderViewId", iter->render_view_id); 199 view_value->SetInteger("renderProcessId", iter->render_process_id); 200 view_value->SetBoolean("incognito", iter->incognito); 201 views->Append(view_value); 202 } 203 extension_data->Set("views", views); 204 extensions::ExtensionActionManager* extension_action_manager = 205 extensions::ExtensionActionManager::Get(extension_service_->profile()); 206 extension_data->SetBoolean( 207 "hasPopupAction", 208 extension_action_manager->GetBrowserAction(*extension) || 209 extension_action_manager->GetPageAction(*extension)); 210 211 // Add warnings. 212 if (warning_service) { 213 std::vector<std::string> warnings = 214 warning_service->GetWarningMessagesForExtension(extension->id()); 215 216 if (!warnings.empty()) { 217 ListValue* warnings_list = new ListValue; 218 for (std::vector<std::string>::const_iterator iter = warnings.begin(); 219 iter != warnings.end(); ++iter) { 220 warnings_list->Append(Value::CreateStringValue(*iter)); 221 } 222 extension_data->Set("warnings", warnings_list); 223 } 224 } 225 226 // Add install warnings (these are not the same as warnings!). 227 if (Manifest::IsUnpackedLocation(extension->location())) { 228 const std::vector<extensions::InstallWarning>& install_warnings = 229 extension->install_warnings(); 230 if (!install_warnings.empty()) { 231 scoped_ptr<ListValue> list(new ListValue()); 232 for (std::vector<extensions::InstallWarning>::const_iterator it = 233 install_warnings.begin(); it != install_warnings.end(); ++it) { 234 DictionaryValue* item = new DictionaryValue(); 235 item->SetBoolean("isHTML", 236 it->format == extensions::InstallWarning::FORMAT_HTML); 237 item->SetString("message", it->message); 238 list->Append(item); 239 } 240 extension_data->Set("installWarnings", list.release()); 241 } 242 } 243 244 return extension_data; 245} 246 247void ExtensionSettingsHandler::GetLocalizedValues( 248 content::WebUIDataSource* source) { 249 source->AddString("extensionSettings", 250 l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE)); 251 252 source->AddString("extensionSettingsDeveloperMode", 253 l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_LINK)); 254 source->AddString("extensionSettingsNoExtensions", 255 l10n_util::GetStringUTF16(IDS_EXTENSIONS_NONE_INSTALLED)); 256 source->AddString("extensionSettingsSuggestGallery", 257 l10n_util::GetStringFUTF16(IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY, 258 ASCIIToUTF16(google_util::AppendGoogleLocaleParam( 259 GURL(extension_urls::GetExtensionGalleryURL())).spec()))); 260 source->AddString("extensionSettingsGetMoreExtensions", 261 l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS)); 262 source->AddString("extensionSettingsGetMoreExtensionsUrl", 263 ASCIIToUTF16(google_util::AppendGoogleLocaleParam( 264 GURL(extension_urls::GetExtensionGalleryURL())).spec())); 265 source->AddString("extensionSettingsExtensionId", 266 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID)); 267 source->AddString("extensionSettingsExtensionPath", 268 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PATH)); 269 source->AddString("extensionSettingsInspectViews", 270 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_VIEWS)); 271 source->AddString("extensionSettingsInstallWarnings", 272 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALL_WARNINGS)); 273 source->AddString("viewIncognito", 274 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO)); 275 source->AddString("viewInactive", 276 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INACTIVE)); 277 source->AddString("extensionSettingsEnable", 278 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE)); 279 source->AddString("extensionSettingsEnabled", 280 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLED)); 281 source->AddString("extensionSettingsRemove", 282 l10n_util::GetStringUTF16(IDS_EXTENSIONS_REMOVE)); 283 source->AddString("extensionSettingsEnableIncognito", 284 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_INCOGNITO)); 285 source->AddString("extensionSettingsAllowFileAccess", 286 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_FILE_ACCESS)); 287 source->AddString("extensionSettingsIncognitoWarning", 288 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INCOGNITO_WARNING)); 289 source->AddString("extensionSettingsReloadTerminated", 290 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD_TERMINATED)); 291 source->AddString("extensionSettingsLaunch", 292 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LAUNCH)); 293 source->AddString("extensionSettingsRestart", 294 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RESTART)); 295 source->AddString("extensionSettingsReloadUnpacked", 296 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD_UNPACKED)); 297 source->AddString("extensionSettingsOptions", 298 l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS_LINK)); 299 source->AddString("extensionSettingsPermissions", 300 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PERMISSIONS_LINK)); 301 source->AddString("extensionSettingsActivity", 302 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ACTIVITY_LINK)); 303 source->AddString("extensionSettingsVisitWebsite", 304 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE)); 305 source->AddString("extensionSettingsVisitWebStore", 306 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSTORE)); 307 source->AddString("extensionSettingsPolicyControlled", 308 l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED)); 309 source->AddString("extensionSettingsManagedMode", 310 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE)); 311 source->AddString("sideloadWipeoutUrl", 312 chrome::kSideloadWipeoutHelpURL); 313 source->AddString("sideloadWipoutLearnMore", 314 l10n_util::GetStringUTF16(IDS_LEARN_MORE)); 315 source->AddString("extensionSettingsShowButton", 316 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON)); 317 source->AddString("extensionSettingsLoadUnpackedButton", 318 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON)); 319 source->AddString("extensionSettingsPackButton", 320 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PACK_BUTTON)); 321 source->AddString("extensionSettingsCommandsLink", 322 l10n_util::GetStringUTF16(IDS_EXTENSIONS_COMMANDS_CONFIGURE)); 323 source->AddString("extensionSettingsUpdateButton", 324 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UPDATE_BUTTON)); 325 source->AddString("extensionSettingsCrashMessage", 326 l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION)); 327 source->AddString("extensionSettingsInDevelopment", 328 l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT)); 329 source->AddString("extensionSettingsWarningsTitle", 330 l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_TITLE)); 331 source->AddString("extensionSettingsShowDetails", 332 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS)); 333 source->AddString("extensionSettingsHideDetails", 334 l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS)); 335 source->AddString("unlockButton", 336 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNLOCK_BUTTON)); 337 source->AddString("lockButton", 338 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCK_BUTTON)); 339 340 // TODO(estade): comb through the above strings to find ones no longer used in 341 // uber extensions. 342 source->AddString("extensionUninstall", 343 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL)); 344} 345 346void ExtensionSettingsHandler::RenderViewHostCreated( 347 content::RenderViewHost* render_view_host) { 348 Profile* source_profile = Profile::FromBrowserContext( 349 render_view_host->GetSiteInstance()->GetBrowserContext()); 350 if (!Profile::FromWebUI(web_ui())->IsSameProfile(source_profile)) 351 return; 352 MaybeUpdateAfterNotification(); 353} 354 355void ExtensionSettingsHandler::RenderViewDeleted( 356 content::RenderViewHost* render_view_host) { 357 deleting_rvh_ = render_view_host; 358 Profile* source_profile = Profile::FromBrowserContext( 359 render_view_host->GetSiteInstance()->GetBrowserContext()); 360 if (!Profile::FromWebUI(web_ui())->IsSameProfile(source_profile)) 361 return; 362 MaybeUpdateAfterNotification(); 363} 364 365void ExtensionSettingsHandler::NavigateToPendingEntry(const GURL& url, 366 content::NavigationController::ReloadType reload_type) { 367 if (reload_type != content::NavigationController::NO_RELOAD) 368 ReloadUnpackedExtensions(); 369} 370 371void ExtensionSettingsHandler::RegisterMessages() { 372 // Don't override an |extension_service_| or |management_policy_| injected 373 // for testing. 374 if (!extension_service_) { 375 extension_service_ = Profile::FromWebUI(web_ui())->GetOriginalProfile()-> 376 GetExtensionService(); 377 } 378 if (!management_policy_) { 379 management_policy_ = extensions::ExtensionSystem::Get( 380 extension_service_->profile())->management_policy(); 381 } 382 383 web_ui()->RegisterMessageCallback("setElevated", 384 base::Bind(&ExtensionSettingsHandler::ManagedUserSetElevated, 385 base::Unretained(this))); 386 web_ui()->RegisterMessageCallback("extensionSettingsRequestExtensionsData", 387 base::Bind(&ExtensionSettingsHandler::HandleRequestExtensionsData, 388 base::Unretained(this))); 389 web_ui()->RegisterMessageCallback("extensionSettingsToggleDeveloperMode", 390 base::Bind(&ExtensionSettingsHandler::HandleToggleDeveloperMode, 391 base::Unretained(this))); 392 web_ui()->RegisterMessageCallback("extensionSettingsInspect", 393 base::Bind(&ExtensionSettingsHandler::HandleInspectMessage, 394 base::Unretained(this))); 395 web_ui()->RegisterMessageCallback("extensionSettingsLaunch", 396 base::Bind(&ExtensionSettingsHandler::HandleLaunchMessage, 397 base::Unretained(this))); 398 web_ui()->RegisterMessageCallback("extensionSettingsRestart", 399 base::Bind(&ExtensionSettingsHandler::HandleRestartMessage, 400 base::Unretained(this))); 401 web_ui()->RegisterMessageCallback("extensionSettingsReload", 402 base::Bind(&ExtensionSettingsHandler::HandleReloadMessage, 403 base::Unretained(this))); 404 web_ui()->RegisterMessageCallback("extensionSettingsEnable", 405 base::Bind(&ExtensionSettingsHandler::HandleEnableMessage, 406 base::Unretained(this))); 407 web_ui()->RegisterMessageCallback("extensionSettingsEnableIncognito", 408 base::Bind(&ExtensionSettingsHandler::HandleEnableIncognitoMessage, 409 base::Unretained(this))); 410 web_ui()->RegisterMessageCallback("extensionSettingsAllowFileAccess", 411 base::Bind(&ExtensionSettingsHandler::HandleAllowFileAccessMessage, 412 base::Unretained(this))); 413 web_ui()->RegisterMessageCallback("extensionSettingsUninstall", 414 base::Bind(&ExtensionSettingsHandler::HandleUninstallMessage, 415 base::Unretained(this))); 416 web_ui()->RegisterMessageCallback("extensionSettingsOptions", 417 base::Bind(&ExtensionSettingsHandler::HandleOptionsMessage, 418 base::Unretained(this))); 419 web_ui()->RegisterMessageCallback("extensionSettingsPermissions", 420 base::Bind(&ExtensionSettingsHandler::HandlePermissionsMessage, 421 base::Unretained(this))); 422 web_ui()->RegisterMessageCallback("extensionSettingsShowButton", 423 base::Bind(&ExtensionSettingsHandler::HandleShowButtonMessage, 424 base::Unretained(this))); 425 web_ui()->RegisterMessageCallback("extensionSettingsAutoupdate", 426 base::Bind(&ExtensionSettingsHandler::HandleAutoUpdateMessage, 427 base::Unretained(this))); 428 web_ui()->RegisterMessageCallback("extensionSettingsLoadUnpackedExtension", 429 base::Bind(&ExtensionSettingsHandler::HandleLoadUnpackedExtensionMessage, 430 base::Unretained(this))); 431} 432 433void ExtensionSettingsHandler::FileSelected(const base::FilePath& path, 434 int index, 435 void* params) { 436 last_unpacked_directory_ = base::FilePath(path); 437 extensions::UnpackedInstaller::Create(extension_service_)->Load(path); 438} 439 440void ExtensionSettingsHandler::MultiFilesSelected( 441 const std::vector<base::FilePath>& files, void* params) { 442 NOTREACHED(); 443} 444 445void ExtensionSettingsHandler::Observe( 446 int type, 447 const content::NotificationSource& source, 448 const content::NotificationDetails& details) { 449 Profile* profile = Profile::FromWebUI(web_ui()); 450 Profile* source_profile = NULL; 451 switch (type) { 452 // We listen for notifications that will result in the page being 453 // repopulated with data twice for the same event in certain cases. 454 // For instance, EXTENSION_LOADED & EXTENSION_HOST_CREATED because 455 // we don't know about the views for an extension at EXTENSION_LOADED, but 456 // if we only listen to EXTENSION_HOST_CREATED, we'll miss extensions 457 // that don't have a process at startup. 458 // 459 // Doing it this way gets everything but causes the page to be rendered 460 // more than we need. It doesn't seem to result in any noticeable flicker. 461 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED: 462 deleting_rvh_ = content::Details<BackgroundContents>(details)-> 463 web_contents()->GetRenderViewHost(); 464 // Fall through. 465 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: 466 case chrome::NOTIFICATION_EXTENSION_HOST_CREATED: 467 source_profile = content::Source<Profile>(source).ptr(); 468 if (!profile->IsSameProfile(source_profile)) 469 return; 470 MaybeUpdateAfterNotification(); 471 break; 472 case chrome::NOTIFICATION_EXTENSION_LOADED: 473 case chrome::NOTIFICATION_EXTENSION_UNLOADED: 474 case chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED: 475 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED: 476 MaybeUpdateAfterNotification(); 477 break; 478 default: 479 NOTREACHED(); 480 } 481} 482 483void ExtensionSettingsHandler::ExtensionUninstallAccepted() { 484 DCHECK(!extension_id_prompting_.empty()); 485 486 bool was_terminated = false; 487 488 // The extension can be uninstalled in another window while the UI was 489 // showing. Do nothing in that case. 490 const Extension* extension = 491 extension_service_->GetExtensionById(extension_id_prompting_, true); 492 if (!extension) { 493 extension = extension_service_->GetTerminatedExtension( 494 extension_id_prompting_); 495 was_terminated = true; 496 } 497 if (!extension) 498 return; 499 500 extension_service_->UninstallExtension(extension_id_prompting_, 501 false, // External uninstall. 502 NULL); // Error. 503 extension_id_prompting_ = ""; 504 505 // There will be no EXTENSION_UNLOADED notification for terminated 506 // extensions as they were already unloaded. 507 if (was_terminated) 508 HandleRequestExtensionsData(NULL); 509} 510 511void ExtensionSettingsHandler::ExtensionUninstallCanceled() { 512 extension_id_prompting_ = ""; 513} 514 515void ExtensionSettingsHandler::ExtensionWarningsChanged() { 516 MaybeUpdateAfterNotification(); 517} 518 519void ExtensionSettingsHandler::InstallUIProceed() { 520 // This should never happen. The dialog only has a cancel button. 521 NOTREACHED(); 522} 523 524void ExtensionSettingsHandler::InstallUIAbort(bool user_initiated) { 525} 526 527void ExtensionSettingsHandler::ReloadUnpackedExtensions() { 528 const ExtensionSet* extensions = extension_service_->extensions(); 529 std::vector<const Extension*> unpacked_extensions; 530 for (ExtensionSet::const_iterator extension = extensions->begin(); 531 extension != extensions->end(); ++extension) { 532 if (Manifest::IsUnpackedLocation((*extension)->location())) 533 unpacked_extensions.push_back(*extension); 534 } 535 536 for (std::vector<const Extension*>::iterator iter = 537 unpacked_extensions.begin(); iter != unpacked_extensions.end(); ++iter) { 538 extension_service_->ReloadExtension((*iter)->id()); 539 } 540} 541 542void ExtensionSettingsHandler::PassphraseDialogCallback(bool success) { 543 if (!success) 544 return; 545 ManagedModeNavigationObserver* observer = 546 ManagedModeNavigationObserver::FromWebContents( 547 web_ui()->GetWebContents()); 548 observer->set_elevated(true); 549 HandleRequestExtensionsData(NULL); 550} 551 552void ExtensionSettingsHandler::ManagedUserSetElevated(const ListValue* args) { 553 ManagedUserService* service = ManagedUserServiceFactory::GetForProfile( 554 Profile::FromWebUI(web_ui())); 555 bool elevated; 556 CHECK(args->GetBoolean(0, &elevated)); 557 if (elevated) { 558 service->RequestAuthorization( 559 web_ui()->GetWebContents(), 560 base::Bind(&ExtensionSettingsHandler::PassphraseDialogCallback, 561 base::Unretained(this))); 562 } else { 563 ManagedModeNavigationObserver* observer = 564 ManagedModeNavigationObserver::FromWebContents( 565 web_ui()->GetWebContents()); 566 observer->set_elevated(false); 567 HandleRequestExtensionsData(NULL); 568 } 569} 570 571scoped_ptr<ScopedExtensionElevation> 572 ExtensionSettingsHandler::GetScopedElevation( 573 const std::string& extension_id) { 574 // web_ui() can be NULL in a unit_test. 575 if (web_ui() == NULL) 576 return scoped_ptr<ScopedExtensionElevation>(NULL); 577 ManagedUserService* service = ManagedUserServiceFactory::GetForProfile( 578 Profile::FromWebUI(web_ui())); 579 scoped_ptr<ScopedExtensionElevation> elevation( 580 new ScopedExtensionElevation(service)); 581 if (service->ProfileIsManaged() && 582 service->IsElevatedForWebContents(web_ui()->GetWebContents())) { 583 elevation->AddExtension(extension_id); 584 } 585 return elevation.Pass(); 586} 587 588bool ExtensionSettingsHandler::CheckUserMayModifySettings( 589 const Extension* extension) { 590 // Get managed user elevation for a specific extension id. The elevation will 591 // be removed automatically when |elevation| goes out of scope. 592 scoped_ptr<ScopedExtensionElevation> elevation = 593 GetScopedElevation(extension->id()); 594 return management_policy_->UserMayModifySettings(extension, NULL); 595} 596 597void ExtensionSettingsHandler::HandleRequestExtensionsData( 598 const ListValue* args) { 599 DictionaryValue results; 600 601 Profile* profile = Profile::FromWebUI(web_ui()); 602 603 // Add the extensions to the results structure. 604 ListValue *extensions_list = new ListValue(); 605 606 extensions::ExtensionWarningService* warnings = 607 extensions::ExtensionSystem::Get(profile)->warning_service(); 608 609 const ExtensionSet* extensions = extension_service_->extensions(); 610 for (ExtensionSet::const_iterator extension = extensions->begin(); 611 extension != extensions->end(); ++extension) { 612 if ((*extension)->ShouldDisplayInExtensionSettings()) { 613 extensions_list->Append(CreateExtensionDetailValue( 614 *extension, 615 GetInspectablePagesForExtension(*extension, true), 616 warnings)); 617 } 618 } 619 extensions = extension_service_->disabled_extensions(); 620 for (ExtensionSet::const_iterator extension = extensions->begin(); 621 extension != extensions->end(); ++extension) { 622 if ((*extension)->ShouldDisplayInExtensionSettings()) { 623 extensions_list->Append(CreateExtensionDetailValue( 624 *extension, 625 GetInspectablePagesForExtension(*extension, false), 626 warnings)); 627 } 628 } 629 extensions = extension_service_->terminated_extensions(); 630 std::vector<ExtensionPage> empty_pages; 631 for (ExtensionSet::const_iterator extension = extensions->begin(); 632 extension != extensions->end(); ++extension) { 633 if ((*extension)->ShouldDisplayInExtensionSettings()) { 634 extensions_list->Append(CreateExtensionDetailValue( 635 *extension, 636 empty_pages, // Terminated process has no active pages. 637 warnings)); 638 } 639 } 640 results.Set("extensions", extensions_list); 641 642 ManagedUserService* service = 643 ManagedUserServiceFactory::GetForProfile(profile); 644 645 bool is_managed = service->ProfileIsManaged(); 646 bool is_elevated = 647 service->IsElevatedForWebContents(web_ui()->GetWebContents()); 648 bool developer_mode = 649 (!is_managed || is_elevated) && 650 profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode); 651 results.SetBoolean("profileIsManaged", is_managed); 652 results.SetBoolean("profileIsElevated", is_elevated); 653 results.SetBoolean("developerMode", developer_mode); 654 655 bool load_unpacked_disabled = 656 extension_service_->extension_prefs()->ExtensionsBlacklistedByDefault(); 657 results.SetBoolean("loadUnpackedDisabled", load_unpacked_disabled); 658 659 web_ui()->CallJavascriptFunction("ExtensionSettings.returnExtensionsData", 660 results); 661 662 MaybeRegisterForNotifications(); 663} 664 665void ExtensionSettingsHandler::HandleToggleDeveloperMode( 666 const ListValue* args) { 667 Profile* profile = Profile::FromWebUI(web_ui()); 668 if (ManagedUserServiceFactory::GetForProfile(profile)->ProfileIsManaged()) 669 return; 670 671 bool developer_mode = 672 profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode); 673 profile->GetPrefs()->SetBoolean( 674 prefs::kExtensionsUIDeveloperMode, !developer_mode); 675} 676 677void ExtensionSettingsHandler::HandleInspectMessage(const ListValue* args) { 678 std::string extension_id; 679 std::string render_process_id_str; 680 std::string render_view_id_str; 681 int render_process_id; 682 int render_view_id; 683 bool incognito; 684 CHECK_EQ(4U, args->GetSize()); 685 CHECK(args->GetString(0, &extension_id)); 686 CHECK(args->GetString(1, &render_process_id_str)); 687 CHECK(args->GetString(2, &render_view_id_str)); 688 CHECK(args->GetBoolean(3, &incognito)); 689 CHECK(base::StringToInt(render_process_id_str, &render_process_id)); 690 CHECK(base::StringToInt(render_view_id_str, &render_view_id)); 691 692 if (render_process_id == -1) { 693 // This message is for a lazy background page. Start the page if necessary. 694 const Extension* extension = 695 extension_service_->extensions()->GetByID(extension_id); 696 DCHECK(extension); 697 698 ExtensionService* service = extension_service_; 699 if (incognito) 700 service = extensions::ExtensionSystem::Get(extension_service_-> 701 profile()->GetOffTheRecordProfile())->extension_service(); 702 703 service->InspectBackgroundPage(extension); 704 return; 705 } 706 707 RenderViewHost* host = RenderViewHost::FromID(render_process_id, 708 render_view_id); 709 if (!host) { 710 // This can happen if the host has gone away since the page was displayed. 711 return; 712 } 713 714 DevToolsWindow::OpenDevToolsWindow(host); 715} 716 717void ExtensionSettingsHandler::HandleLaunchMessage(const ListValue* args) { 718 CHECK_EQ(1U, args->GetSize()); 719 std::string extension_id; 720 CHECK(args->GetString(0, &extension_id)); 721 const extensions::Extension* extension = 722 extension_service_->GetExtensionById(extension_id, false); 723 chrome::OpenApplication(chrome::AppLaunchParams(extension_service_->profile(), 724 extension, 725 extension_misc::LAUNCH_WINDOW, 726 NEW_WINDOW)); 727} 728 729void ExtensionSettingsHandler::HandleRestartMessage(const ListValue* args) { 730 CHECK_EQ(1U, args->GetSize()); 731 std::string extension_id; 732 CHECK(args->GetString(0, &extension_id)); 733 extension_service_->RestartExtension(extension_id); 734} 735 736void ExtensionSettingsHandler::HandleReloadMessage(const ListValue* args) { 737 std::string extension_id = UTF16ToUTF8(ExtractStringValue(args)); 738 CHECK(!extension_id.empty()); 739 extension_service_->ReloadExtension(extension_id); 740} 741 742void ExtensionSettingsHandler::HandleEnableMessage(const ListValue* args) { 743 CHECK_EQ(2U, args->GetSize()); 744 std::string extension_id, enable_str; 745 CHECK(args->GetString(0, &extension_id)); 746 CHECK(args->GetString(1, &enable_str)); 747 748 const Extension* extension = 749 extension_service_->GetInstalledExtension(extension_id); 750 if (!extension || !CheckUserMayModifySettings(extension)) { 751 LOG(ERROR) << "Attempt to enable an extension that is non-usermanagable was" 752 << "made. Extension id: " << extension->id(); 753 return; 754 } 755 756 if (enable_str == "true") { 757 extensions::ExtensionPrefs* prefs = extension_service_->extension_prefs(); 758 if (prefs->DidExtensionEscalatePermissions(extension_id)) { 759 extensions::ShowExtensionDisabledDialog( 760 extension_service_, web_ui()->GetWebContents(), extension); 761 } else if ((prefs->GetDisableReasons(extension_id) & 762 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) && 763 !requirements_checker_.get()) { 764 // Recheck the requirements. 765 scoped_refptr<const Extension> extension = 766 extension_service_->GetExtensionById(extension_id, 767 true /* include disabled */); 768 requirements_checker_.reset(new extensions::RequirementsChecker()); 769 requirements_checker_->Check( 770 extension, 771 base::Bind(&ExtensionSettingsHandler::OnRequirementsChecked, 772 AsWeakPtr(), extension_id)); 773 } else { 774 extension_service_->EnableExtension(extension_id); 775 776 // Make sure any browser action contained within it is not hidden. 777 extensions::ExtensionActionAPI::SetBrowserActionVisibility( 778 prefs, extension->id(), true); 779 } 780 } else { 781 // Get managed user elevation for a specific extension id. The elevation 782 // will be removed automatically when |elevation| goes out of scope. 783 scoped_ptr<ScopedExtensionElevation> elevation = 784 GetScopedElevation(extension_id); 785 extension_service_->DisableExtension( 786 extension_id, Extension::DISABLE_USER_ACTION); 787 } 788} 789 790void ExtensionSettingsHandler::HandleEnableIncognitoMessage( 791 const ListValue* args) { 792 CHECK_EQ(2U, args->GetSize()); 793 std::string extension_id, enable_str; 794 CHECK(args->GetString(0, &extension_id)); 795 CHECK(args->GetString(1, &enable_str)); 796 const Extension* extension = 797 extension_service_->GetInstalledExtension(extension_id); 798 if (!extension) 799 return; 800 801 // Flipping the incognito bit will generate unload/load notifications for the 802 // extension, but we don't want to reload the page, because a) we've already 803 // updated the UI to reflect the change, and b) we want the yellow warning 804 // text to stay until the user has left the page. 805 // 806 // TODO(aa): This creates crappiness in some cases. For example, in a main 807 // window, when toggling this, the browser action will flicker because it gets 808 // unloaded, then reloaded. It would be better to have a dedicated 809 // notification for this case. 810 // 811 // Bug: http://crbug.com/41384 812 base::AutoReset<bool> auto_reset_ignore_notifications( 813 &ignore_notifications_, true); 814 extension_service_->SetIsIncognitoEnabled(extension->id(), 815 enable_str == "true"); 816} 817 818void ExtensionSettingsHandler::HandleAllowFileAccessMessage( 819 const ListValue* args) { 820 CHECK_EQ(2U, args->GetSize()); 821 std::string extension_id, allow_str; 822 CHECK(args->GetString(0, &extension_id)); 823 CHECK(args->GetString(1, &allow_str)); 824 const Extension* extension = 825 extension_service_->GetInstalledExtension(extension_id); 826 if (!extension) 827 return; 828 829 if (!CheckUserMayModifySettings(extension)) { 830 LOG(ERROR) << "Attempt to change allow file access of an extension that is " 831 << "non-usermanagable was made. Extension id : " 832 << extension->id(); 833 return; 834 } 835 836 extension_service_->SetAllowFileAccess(extension, allow_str == "true"); 837} 838 839void ExtensionSettingsHandler::HandleUninstallMessage(const ListValue* args) { 840 CHECK_EQ(1U, args->GetSize()); 841 std::string extension_id; 842 CHECK(args->GetString(0, &extension_id)); 843 const Extension* extension = 844 extension_service_->GetInstalledExtension(extension_id); 845 if (!extension) 846 return; 847 848 if (!CheckUserMayModifySettings(extension)) { 849 LOG(ERROR) << "Attempt to uninstall an extension that is non-usermanagable " 850 << "was made. Extension id : " << extension->id(); 851 return; 852 } 853 854 if (!extension_id_prompting_.empty()) 855 return; // Only one prompt at a time. 856 857 extension_id_prompting_ = extension_id; 858 859 GetExtensionUninstallDialog()->ConfirmUninstall(extension); 860} 861 862void ExtensionSettingsHandler::HandleOptionsMessage(const ListValue* args) { 863 const Extension* extension = GetActiveExtension(args); 864 if (!extension || 865 extensions::ManifestURL::GetOptionsPage(extension).is_empty()) 866 return; 867 ExtensionTabUtil::OpenOptionsPage(extension, 868 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents())); 869} 870 871void ExtensionSettingsHandler::HandlePermissionsMessage(const ListValue* args) { 872 std::string extension_id(UTF16ToUTF8(ExtractStringValue(args))); 873 CHECK(!extension_id.empty()); 874 const Extension* extension = 875 extension_service_->GetExtensionById(extension_id, true); 876 if (!extension) 877 return; 878 879 prompt_.reset(new ExtensionInstallPrompt(web_contents())); 880 prompt_->ReviewPermissions(this, extension); 881} 882 883void ExtensionSettingsHandler::HandleShowButtonMessage(const ListValue* args) { 884 const Extension* extension = GetActiveExtension(args); 885 if (!extension) 886 return; 887 extensions::ExtensionActionAPI::SetBrowserActionVisibility( 888 extension_service_->extension_prefs(), extension->id(), true); 889} 890 891void ExtensionSettingsHandler::HandleAutoUpdateMessage(const ListValue* args) { 892 ExtensionUpdater* updater = extension_service_->updater(); 893 if (updater) { 894 ExtensionUpdater::CheckParams params; 895 params.install_immediately = true; 896 updater->CheckNow(params); 897 } 898} 899 900void ExtensionSettingsHandler::HandleLoadUnpackedExtensionMessage( 901 const ListValue* args) { 902 DCHECK(args->empty()); 903 904 string16 select_title = 905 l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY); 906 907 const int kFileTypeIndex = 0; // No file type information to index. 908 const ui::SelectFileDialog::Type kSelectType = 909 ui::SelectFileDialog::SELECT_FOLDER; 910 load_extension_dialog_ = ui::SelectFileDialog::Create( 911 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); 912 load_extension_dialog_->SelectFile( 913 kSelectType, 914 select_title, 915 last_unpacked_directory_, 916 NULL, 917 kFileTypeIndex, 918 base::FilePath::StringType(), 919 web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(), 920 NULL); 921} 922 923void ExtensionSettingsHandler::ShowAlert(const std::string& message) { 924 ListValue arguments; 925 arguments.Append(Value::CreateStringValue(message)); 926 web_ui()->CallJavascriptFunction("alert", arguments); 927} 928 929const Extension* ExtensionSettingsHandler::GetActiveExtension( 930 const ListValue* args) { 931 std::string extension_id = UTF16ToUTF8(ExtractStringValue(args)); 932 CHECK(!extension_id.empty()); 933 return extension_service_->GetExtensionById(extension_id, false); 934} 935 936void ExtensionSettingsHandler::MaybeUpdateAfterNotification() { 937 WebContents* contents = web_ui()->GetWebContents(); 938 if (!ignore_notifications_ && contents && contents->GetRenderViewHost()) 939 HandleRequestExtensionsData(NULL); 940 deleting_rvh_ = NULL; 941} 942 943void ExtensionSettingsHandler::MaybeRegisterForNotifications() { 944 if (registered_for_notifications_) 945 return; 946 947 registered_for_notifications_ = true; 948 Profile* profile = Profile::FromWebUI(web_ui()); 949 950 // Register for notifications that we need to reload the page. 951 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 952 content::Source<Profile>(profile)); 953 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 954 content::Source<Profile>(profile)); 955 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, 956 content::Source<Profile>(profile)); 957 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED, 958 content::NotificationService::AllBrowserContextsAndSources()); 959 registrar_.Add(this, 960 chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED, 961 content::NotificationService::AllBrowserContextsAndSources()); 962 registrar_.Add(this, 963 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED, 964 content::NotificationService::AllBrowserContextsAndSources()); 965 registrar_.Add( 966 this, 967 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 968 content::Source<extensions::ExtensionPrefs>( 969 profile->GetExtensionService()->extension_prefs())); 970 971 content::RenderViewHost::AddCreatedCallback(rvh_created_callback_); 972 973 content::WebContentsObserver::Observe(web_ui()->GetWebContents()); 974 975 warning_service_observer_.Add( 976 extensions::ExtensionSystem::Get(profile)->warning_service()); 977 978 base::Closure callback = base::Bind( 979 &ExtensionSettingsHandler::MaybeUpdateAfterNotification, 980 base::Unretained(this)); 981 982 pref_registrar_.Init(profile->GetPrefs()); 983 pref_registrar_.Add(prefs::kExtensionInstallDenyList, callback); 984} 985 986std::vector<ExtensionPage> 987ExtensionSettingsHandler::GetInspectablePagesForExtension( 988 const Extension* extension, bool extension_is_enabled) { 989 std::vector<ExtensionPage> result; 990 991 // Get the extension process's active views. 992 ExtensionProcessManager* process_manager = 993 extensions::ExtensionSystem::Get(extension_service_->profile())-> 994 process_manager(); 995 GetInspectablePagesForExtensionProcess( 996 process_manager->GetRenderViewHostsForExtension(extension->id()), 997 &result); 998 999 // Get shell window views 1000 GetShellWindowPagesForExtensionProfile(extension, 1001 extension_service_->profile(), &result); 1002 1003 // Include a link to start the lazy background page, if applicable. 1004 if (extensions::BackgroundInfo::HasLazyBackgroundPage(extension) && 1005 extension_is_enabled && 1006 !process_manager->GetBackgroundHostForExtension(extension->id())) { 1007 result.push_back( 1008 ExtensionPage(extensions::BackgroundInfo::GetBackgroundURL(extension), 1009 -1, -1, false)); 1010 } 1011 1012 // Repeat for the incognito process, if applicable. Don't try to get 1013 // shell windows for incognito processes. 1014 if (extension_service_->profile()->HasOffTheRecordProfile() && 1015 extensions::IncognitoInfo::IsSplitMode(extension)) { 1016 ExtensionProcessManager* process_manager = 1017 extensions::ExtensionSystem::Get(extension_service_->profile()-> 1018 GetOffTheRecordProfile())->process_manager(); 1019 GetInspectablePagesForExtensionProcess( 1020 process_manager->GetRenderViewHostsForExtension(extension->id()), 1021 &result); 1022 1023 if (extensions::BackgroundInfo::HasLazyBackgroundPage(extension) 1024 && extension_is_enabled && 1025 !process_manager->GetBackgroundHostForExtension(extension->id())) { 1026 result.push_back( 1027 ExtensionPage(extensions::BackgroundInfo::GetBackgroundURL(extension), 1028 -1, -1, true)); 1029 } 1030 } 1031 1032 return result; 1033} 1034 1035void ExtensionSettingsHandler::GetInspectablePagesForExtensionProcess( 1036 const std::set<RenderViewHost*>& views, 1037 std::vector<ExtensionPage>* result) { 1038 for (std::set<RenderViewHost*>::const_iterator iter = views.begin(); 1039 iter != views.end(); ++iter) { 1040 RenderViewHost* host = *iter; 1041 WebContents* web_contents = WebContents::FromRenderViewHost(host); 1042 extensions::ViewType host_type = extensions::GetViewType(web_contents); 1043 if (host == deleting_rvh_ || 1044 extensions::VIEW_TYPE_EXTENSION_POPUP == host_type || 1045 extensions::VIEW_TYPE_EXTENSION_DIALOG == host_type) 1046 continue; 1047 1048 GURL url = web_contents->GetURL(); 1049 content::RenderProcessHost* process = host->GetProcess(); 1050 result->push_back( 1051 ExtensionPage(url, process->GetID(), host->GetRoutingID(), 1052 process->GetBrowserContext()->IsOffTheRecord())); 1053 } 1054} 1055 1056void ExtensionSettingsHandler::GetShellWindowPagesForExtensionProfile( 1057 const Extension* extension, 1058 Profile* profile, 1059 std::vector<ExtensionPage>* result) { 1060 extensions::ShellWindowRegistry* registry = 1061 extensions::ShellWindowRegistry::Get(profile); 1062 if (!registry) return; 1063 1064 const extensions::ShellWindowRegistry::ShellWindowSet windows = 1065 registry->GetShellWindowsForApp(extension->id()); 1066 1067 for (extensions::ShellWindowRegistry::const_iterator it = windows.begin(); 1068 it != windows.end(); ++it) { 1069 WebContents* web_contents = (*it)->web_contents(); 1070 RenderViewHost* host = web_contents->GetRenderViewHost(); 1071 content::RenderProcessHost* process = host->GetProcess(); 1072 1073 result->push_back( 1074 ExtensionPage(web_contents->GetURL(), process->GetID(), 1075 host->GetRoutingID(), 1076 process->GetBrowserContext()->IsOffTheRecord())); 1077 } 1078} 1079 1080ExtensionUninstallDialog* 1081ExtensionSettingsHandler::GetExtensionUninstallDialog() { 1082#if !defined(OS_ANDROID) 1083 if (!extension_uninstall_dialog_.get()) { 1084 Browser* browser = chrome::FindBrowserWithWebContents( 1085 web_ui()->GetWebContents()); 1086 extension_uninstall_dialog_.reset( 1087 ExtensionUninstallDialog::Create(extension_service_->profile(), 1088 browser, this)); 1089 } 1090 return extension_uninstall_dialog_.get(); 1091#else 1092 return NULL; 1093#endif // !defined(OS_ANDROID) 1094} 1095 1096void ExtensionSettingsHandler::OnRequirementsChecked( 1097 std::string extension_id, 1098 std::vector<std::string> requirement_errors) { 1099 if (requirement_errors.empty()) { 1100 extension_service_->EnableExtension(extension_id); 1101 } else { 1102 ExtensionErrorReporter::GetInstance()->ReportError( 1103 UTF8ToUTF16(JoinString(requirement_errors, ' ')), 1104 true /* be noisy */); 1105 } 1106 requirements_checker_.reset(); 1107} 1108