management_api.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/extensions/api/management/management_api.h" 6 7#include <map> 8#include <string> 9#include <vector> 10 11#include "base/basictypes.h" 12#include "base/bind.h" 13#include "base/json/json_writer.h" 14#include "base/lazy_instance.h" 15#include "base/logging.h" 16#include "base/memory/linked_ptr.h" 17#include "base/memory/scoped_ptr.h" 18#include "base/metrics/histogram.h" 19#include "base/strings/string_number_conversions.h" 20#include "base/strings/string_util.h" 21#include "base/strings/utf_string_conversions.h" 22#include "chrome/browser/chrome_notification_types.h" 23#include "chrome/browser/extensions/api/management/management_api_constants.h" 24#include "chrome/browser/extensions/extension_service.h" 25#include "chrome/browser/extensions/extension_uninstall_dialog.h" 26#include "chrome/browser/extensions/launch_util.h" 27#include "chrome/browser/profiles/profile.h" 28#include "chrome/browser/ui/extensions/application_launch.h" 29#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 30#include "chrome/common/chrome_utility_messages.h" 31#include "chrome/common/extensions/api/management.h" 32#include "chrome/common/extensions/extension_constants.h" 33#include "chrome/common/extensions/extension_icon_set.h" 34#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 35#include "chrome/common/extensions/manifest_handlers/icons_handler.h" 36#include "chrome/common/extensions/manifest_url_handler.h" 37#include "content/public/browser/notification_details.h" 38#include "content/public/browser/notification_source.h" 39#include "content/public/browser/utility_process_host.h" 40#include "content/public/browser/utility_process_host_client.h" 41#include "extensions/browser/event_router.h" 42#include "extensions/browser/extension_registry.h" 43#include "extensions/browser/extension_system.h" 44#include "extensions/browser/management_policy.h" 45#include "extensions/common/constants.h" 46#include "extensions/common/error_utils.h" 47#include "extensions/common/extension.h" 48#include "extensions/common/manifest_handlers/offline_enabled_info.h" 49#include "extensions/common/permissions/permission_set.h" 50#include "extensions/common/permissions/permissions_data.h" 51#include "extensions/common/url_pattern.h" 52 53#if !defined(OS_ANDROID) 54#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" 55#endif 56 57using base::IntToString; 58using content::BrowserThread; 59using content::UtilityProcessHost; 60using content::UtilityProcessHostClient; 61 62namespace keys = extension_management_api_constants; 63 64namespace extensions { 65 66namespace management = api::management; 67 68namespace { 69 70typedef std::vector<linked_ptr<management::ExtensionInfo> > ExtensionInfoList; 71typedef std::vector<linked_ptr<management::IconInfo> > IconInfoList; 72 73enum AutoConfirmForTest { 74 DO_NOT_SKIP = 0, 75 PROCEED, 76 ABORT 77}; 78 79AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP; 80 81std::vector<std::string> CreateWarningsList(const Extension* extension) { 82 std::vector<std::string> warnings_list; 83 PermissionMessages warnings = 84 PermissionsData::GetPermissionMessages(extension); 85 for (PermissionMessages::const_iterator iter = warnings.begin(); 86 iter != warnings.end(); ++iter) { 87 warnings_list.push_back(base::UTF16ToUTF8(iter->message())); 88 } 89 90 return warnings_list; 91} 92 93scoped_ptr<management::ExtensionInfo> CreateExtensionInfo( 94 const Extension& extension, 95 ExtensionSystem* system) { 96 scoped_ptr<management::ExtensionInfo> info(new management::ExtensionInfo()); 97 ExtensionService* service = system->extension_service(); 98 99 info->id = extension.id(); 100 info->name = extension.name(); 101 info->short_name = extension.short_name(); 102 info->enabled = service->IsExtensionEnabled(info->id); 103 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension); 104 info->version = extension.VersionString(); 105 info->description = extension.description(); 106 info->options_url = ManifestURL::GetOptionsPage(&extension).spec(); 107 info->homepage_url.reset(new std::string( 108 ManifestURL::GetHomepageURL(&extension).spec())); 109 info->may_disable = system->management_policy()-> 110 UserMayModifySettings(&extension, NULL); 111 info->is_app = extension.is_app(); 112 if (info->is_app) { 113 if (extension.is_legacy_packaged_app()) 114 info->type = management::ExtensionInfo::TYPE_LEGACY_PACKAGED_APP; 115 else if (extension.is_hosted_app()) 116 info->type = management::ExtensionInfo::TYPE_HOSTED_APP; 117 else 118 info->type = management::ExtensionInfo::TYPE_PACKAGED_APP; 119 } else if (extension.is_theme()) { 120 info->type = management::ExtensionInfo::TYPE_THEME; 121 } else { 122 info->type = management::ExtensionInfo::TYPE_EXTENSION; 123 } 124 125 if (info->enabled) { 126 info->disabled_reason = management::ExtensionInfo::DISABLED_REASON_NONE; 127 } else { 128 ExtensionPrefs* prefs = service->extension_prefs(); 129 if (prefs->DidExtensionEscalatePermissions(extension.id())) { 130 info->disabled_reason = 131 management::ExtensionInfo::DISABLED_REASON_PERMISSIONS_INCREASE; 132 } else { 133 info->disabled_reason = 134 management::ExtensionInfo::DISABLED_REASON_UNKNOWN; 135 } 136 } 137 138 if (!ManifestURL::GetUpdateURL(&extension).is_empty()) { 139 info->update_url.reset(new std::string( 140 ManifestURL::GetUpdateURL(&extension).spec())); 141 } 142 143 if (extension.is_app()) { 144 info->app_launch_url.reset(new std::string( 145 AppLaunchInfo::GetFullLaunchURL(&extension).spec())); 146 } 147 148 const ExtensionIconSet::IconMap& icons = 149 IconsInfo::GetIcons(&extension).map(); 150 if (!icons.empty()) { 151 info->icons.reset(new IconInfoList()); 152 ExtensionIconSet::IconMap::const_iterator icon_iter; 153 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) { 154 management::IconInfo* icon_info = new management::IconInfo(); 155 icon_info->size = icon_iter->first; 156 GURL url = ExtensionIconSource::GetIconURL( 157 &extension, icon_info->size, ExtensionIconSet::MATCH_EXACTLY, false, 158 NULL); 159 icon_info->url = url.spec(); 160 info->icons->push_back(make_linked_ptr<management::IconInfo>(icon_info)); 161 } 162 } 163 164 const std::set<std::string> perms = 165 extension.GetActivePermissions()->GetAPIsAsStrings(); 166 if (!perms.empty()) { 167 std::set<std::string>::const_iterator perms_iter; 168 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter) 169 info->permissions.push_back(*perms_iter); 170 } 171 172 if (!extension.is_hosted_app()) { 173 // Skip host permissions for hosted apps. 174 const URLPatternSet host_perms = 175 extension.GetActivePermissions()->explicit_hosts(); 176 if (!host_perms.is_empty()) { 177 for (URLPatternSet::const_iterator iter = host_perms.begin(); 178 iter != host_perms.end(); ++iter) { 179 info->host_permissions.push_back(iter->GetAsString()); 180 } 181 } 182 } 183 184 switch (extension.location()) { 185 case Manifest::INTERNAL: 186 info->install_type = management::ExtensionInfo::INSTALL_TYPE_NORMAL; 187 break; 188 case Manifest::UNPACKED: 189 case Manifest::COMMAND_LINE: 190 info->install_type = management::ExtensionInfo::INSTALL_TYPE_DEVELOPMENT; 191 break; 192 case Manifest::EXTERNAL_PREF: 193 case Manifest::EXTERNAL_REGISTRY: 194 case Manifest::EXTERNAL_PREF_DOWNLOAD: 195 info->install_type = management::ExtensionInfo::INSTALL_TYPE_SIDELOAD; 196 break; 197 case Manifest::EXTERNAL_POLICY: 198 case Manifest::EXTERNAL_POLICY_DOWNLOAD: 199 info->install_type = management::ExtensionInfo::INSTALL_TYPE_ADMIN; 200 break; 201 case Manifest::NUM_LOCATIONS: 202 NOTREACHED(); 203 case Manifest::INVALID_LOCATION: 204 case Manifest::COMPONENT: 205 case Manifest::EXTERNAL_COMPONENT: 206 info->install_type = management::ExtensionInfo::INSTALL_TYPE_OTHER; 207 break; 208 } 209 210 return info.Pass(); 211} 212 213void AddExtensionInfo(const ExtensionSet& extensions, 214 ExtensionSystem* system, 215 ExtensionInfoList* extension_list) { 216 for (ExtensionSet::const_iterator iter = extensions.begin(); 217 iter != extensions.end(); ++iter) { 218 const Extension& extension = *iter->get(); 219 220 if (extension.ShouldNotBeVisible()) 221 continue; // Skip built-in extensions/apps. 222 223 extension_list->push_back(make_linked_ptr<management::ExtensionInfo>( 224 CreateExtensionInfo(extension, system).release())); 225 } 226} 227 228} // namespace 229 230ExtensionService* ManagementFunction::service() { 231 return GetProfile()->GetExtensionService(); 232} 233 234ExtensionService* AsyncManagementFunction::service() { 235 return GetProfile()->GetExtensionService(); 236} 237 238bool ManagementGetAllFunction::RunImpl() { 239 ExtensionInfoList extensions; 240 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile()); 241 ExtensionSystem* system = ExtensionSystem::Get(GetProfile()); 242 243 AddExtensionInfo(registry->enabled_extensions(), system, &extensions); 244 AddExtensionInfo(registry->disabled_extensions(), system, &extensions); 245 AddExtensionInfo(registry->terminated_extensions(), system, &extensions); 246 247 results_ = management::GetAll::Results::Create(extensions); 248 return true; 249} 250 251bool ManagementGetFunction::RunImpl() { 252 scoped_ptr<management::Get::Params> params( 253 management::Get::Params::Create(*args_)); 254 EXTENSION_FUNCTION_VALIDATE(params.get()); 255 256 const Extension* extension = service()->GetExtensionById(params->id, true); 257 if (!extension) { 258 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, 259 params->id); 260 return false; 261 } 262 263 scoped_ptr<management::ExtensionInfo> info = 264 CreateExtensionInfo(*extension, ExtensionSystem::Get(GetProfile())); 265 results_ = management::Get::Results::Create(*info); 266 267 return true; 268} 269 270bool ManagementGetPermissionWarningsByIdFunction::RunImpl() { 271 scoped_ptr<management::GetPermissionWarningsById::Params> params( 272 management::GetPermissionWarningsById::Params::Create(*args_)); 273 EXTENSION_FUNCTION_VALIDATE(params.get()); 274 275 const Extension* extension = service()->GetExtensionById(params->id, true); 276 if (!extension) { 277 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, 278 params->id); 279 return false; 280 } 281 282 std::vector<std::string> warnings = CreateWarningsList(extension); 283 results_ = management::GetPermissionWarningsById::Results::Create(warnings); 284 return true; 285} 286 287namespace { 288 289// This class helps ManagementGetPermissionWarningsByManifestFunction manage 290// sending manifest JSON strings to the utility process for parsing. 291class SafeManifestJSONParser : public UtilityProcessHostClient { 292 public: 293 SafeManifestJSONParser( 294 ManagementGetPermissionWarningsByManifestFunction* client, 295 const std::string& manifest) 296 : client_(client), 297 manifest_(manifest) {} 298 299 void Start() { 300 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 301 BrowserThread::PostTask( 302 BrowserThread::IO, 303 FROM_HERE, 304 base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this)); 305 } 306 307 void StartWorkOnIOThread() { 308 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 309 UtilityProcessHost* host = UtilityProcessHost::Create( 310 this, base::MessageLoopProxy::current().get()); 311 host->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); 312 } 313 314 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 315 bool handled = true; 316 IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message) 317 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, 318 OnJSONParseSucceeded) 319 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, 320 OnJSONParseFailed) 321 IPC_MESSAGE_UNHANDLED(handled = false) 322 IPC_END_MESSAGE_MAP() 323 return handled; 324 } 325 326 void OnJSONParseSucceeded(const base::ListValue& wrapper) { 327 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 328 const base::Value* value = NULL; 329 CHECK(wrapper.Get(0, &value)); 330 if (value->IsType(base::Value::TYPE_DICTIONARY)) 331 parsed_manifest_.reset( 332 static_cast<const base::DictionaryValue*>(value)->DeepCopy()); 333 else 334 error_ = keys::kManifestParseError; 335 336 BrowserThread::PostTask( 337 BrowserThread::UI, 338 FROM_HERE, 339 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); 340 } 341 342 void OnJSONParseFailed(const std::string& error) { 343 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 344 error_ = error; 345 BrowserThread::PostTask( 346 BrowserThread::UI, 347 FROM_HERE, 348 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); 349 } 350 351 void ReportResultFromUIThread() { 352 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 353 if (error_.empty() && parsed_manifest_.get()) 354 client_->OnParseSuccess(parsed_manifest_.Pass()); 355 else 356 client_->OnParseFailure(error_); 357 } 358 359 private: 360 virtual ~SafeManifestJSONParser() {} 361 362 // The client who we'll report results back to. 363 ManagementGetPermissionWarningsByManifestFunction* client_; 364 365 // Data to parse. 366 std::string manifest_; 367 368 // Results of parsing. 369 scoped_ptr<base::DictionaryValue> parsed_manifest_; 370 371 std::string error_; 372}; 373 374} // namespace 375 376bool ManagementGetPermissionWarningsByManifestFunction::RunImpl() { 377 scoped_ptr<management::GetPermissionWarningsByManifest::Params> params( 378 management::GetPermissionWarningsByManifest::Params::Create(*args_)); 379 EXTENSION_FUNCTION_VALIDATE(params.get()); 380 381 scoped_refptr<SafeManifestJSONParser> parser = 382 new SafeManifestJSONParser(this, params->manifest_str); 383 parser->Start(); 384 385 // Matched with a Release() in OnParseSuccess/Failure(). 386 AddRef(); 387 388 // Response is sent async in OnParseSuccess/Failure(). 389 return true; 390} 391 392void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess( 393 scoped_ptr<base::DictionaryValue> parsed_manifest) { 394 CHECK(parsed_manifest.get()); 395 396 scoped_refptr<Extension> extension = Extension::Create( 397 base::FilePath(), Manifest::INVALID_LOCATION, *parsed_manifest, 398 Extension::NO_FLAGS, &error_); 399 if (!extension.get()) { 400 OnParseFailure(keys::kExtensionCreateError); 401 return; 402 } 403 404 std::vector<std::string> warnings = CreateWarningsList(extension.get()); 405 results_ = 406 management::GetPermissionWarningsByManifest::Results::Create(warnings); 407 SendResponse(true); 408 409 // Matched with AddRef() in RunImpl(). 410 Release(); 411} 412 413void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure( 414 const std::string& error) { 415 error_ = error; 416 SendResponse(false); 417 418 // Matched with AddRef() in RunImpl(). 419 Release(); 420} 421 422bool ManagementLaunchAppFunction::RunImpl() { 423 scoped_ptr<management::LaunchApp::Params> params( 424 management::LaunchApp::Params::Create(*args_)); 425 EXTENSION_FUNCTION_VALIDATE(params.get()); 426 const Extension* extension = service()->GetExtensionById(params->id, true); 427 if (!extension) { 428 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, 429 params->id); 430 return false; 431 } 432 if (!extension->is_app()) { 433 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, 434 params->id); 435 return false; 436 } 437 438 // Look at prefs to find the right launch container. 439 // If the user has not set a preference, the default launch value will be 440 // returned. 441 LaunchContainer launch_container = 442 GetLaunchContainer(service()->extension_prefs(), extension); 443 OpenApplication(AppLaunchParams( 444 GetProfile(), extension, launch_container, NEW_FOREGROUND_TAB)); 445#if !defined(OS_ANDROID) 446 CoreAppLauncherHandler::RecordAppLaunchType( 447 extension_misc::APP_LAUNCH_EXTENSION_API, 448 extension->GetType()); 449#endif 450 451 return true; 452} 453 454ManagementSetEnabledFunction::ManagementSetEnabledFunction() { 455} 456 457ManagementSetEnabledFunction::~ManagementSetEnabledFunction() { 458} 459 460bool ManagementSetEnabledFunction::RunImpl() { 461 scoped_ptr<management::SetEnabled::Params> params( 462 management::SetEnabled::Params::Create(*args_)); 463 EXTENSION_FUNCTION_VALIDATE(params.get()); 464 465 extension_id_ = params->id; 466 467 const Extension* extension = service()->GetInstalledExtension(extension_id_); 468 if (!extension || extension->ShouldNotBeVisible()) { 469 error_ = ErrorUtils::FormatErrorMessage( 470 keys::kNoExtensionError, extension_id_); 471 return false; 472 } 473 474 const ManagementPolicy* policy = 475 ExtensionSystem::Get(GetProfile())->management_policy(); 476 if (!policy->UserMayModifySettings(extension, NULL) || 477 (!params->enabled && policy->MustRemainEnabled(extension, NULL)) || 478 (params->enabled && policy->MustRemainDisabled(extension, NULL, NULL))) { 479 error_ = ErrorUtils::FormatErrorMessage( 480 keys::kUserCantModifyError, extension_id_); 481 return false; 482 } 483 484 bool currently_enabled = service()->IsExtensionEnabled(extension_id_); 485 486 if (!currently_enabled && params->enabled) { 487 ExtensionPrefs* prefs = service()->extension_prefs(); 488 if (prefs->DidExtensionEscalatePermissions(extension_id_)) { 489 if (!user_gesture()) { 490 error_ = keys::kGestureNeededForEscalationError; 491 return false; 492 } 493 AddRef(); // Matched in InstallUIProceed/InstallUIAbort 494 install_prompt_.reset( 495 new ExtensionInstallPrompt(GetAssociatedWebContents())); 496 install_prompt_->ConfirmReEnable(this, extension); 497 return true; 498 } 499 service()->EnableExtension(extension_id_); 500 } else if (currently_enabled && !params->enabled) { 501 service()->DisableExtension(extension_id_, Extension::DISABLE_USER_ACTION); 502 } 503 504 BrowserThread::PostTask( 505 BrowserThread::UI, 506 FROM_HERE, 507 base::Bind(&ManagementSetEnabledFunction::SendResponse, this, true)); 508 509 return true; 510} 511 512void ManagementSetEnabledFunction::InstallUIProceed() { 513 service()->EnableExtension(extension_id_); 514 SendResponse(true); 515 Release(); 516} 517 518void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) { 519 error_ = keys::kUserDidNotReEnableError; 520 SendResponse(false); 521 Release(); 522} 523 524ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() { 525} 526 527ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() { 528} 529 530bool ManagementUninstallFunctionBase::Uninstall( 531 const std::string& extension_id, 532 bool show_confirm_dialog) { 533 extension_id_ = extension_id; 534 const Extension* extension = service()->GetExtensionById(extension_id_, true); 535 if (!extension || extension->ShouldNotBeVisible()) { 536 error_ = ErrorUtils::FormatErrorMessage( 537 keys::kNoExtensionError, extension_id_); 538 return false; 539 } 540 541 if (!ExtensionSystem::Get(GetProfile()) 542 ->management_policy() 543 ->UserMayModifySettings(extension, NULL)) { 544 error_ = ErrorUtils::FormatErrorMessage( 545 keys::kUserCantModifyError, extension_id_); 546 return false; 547 } 548 549 if (auto_confirm_for_test == DO_NOT_SKIP) { 550 if (show_confirm_dialog) { 551 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled 552 extension_uninstall_dialog_.reset(ExtensionUninstallDialog::Create( 553 GetProfile(), GetCurrentBrowser(), this)); 554 extension_uninstall_dialog_->ConfirmUninstall(extension); 555 } else { 556 Finish(true); 557 } 558 } else { 559 Finish(auto_confirm_for_test == PROCEED); 560 } 561 562 return true; 563} 564 565// static 566void ManagementUninstallFunctionBase::SetAutoConfirmForTest( 567 bool should_proceed) { 568 auto_confirm_for_test = should_proceed ? PROCEED : ABORT; 569} 570 571void ManagementUninstallFunctionBase::Finish(bool should_uninstall) { 572 if (should_uninstall) { 573 bool success = service()->UninstallExtension( 574 extension_id_, 575 false, /* external uninstall */ 576 NULL); 577 578 // TODO set error_ if !success 579 SendResponse(success); 580 } else { 581 error_ = ErrorUtils::FormatErrorMessage( 582 keys::kUninstallCanceledError, extension_id_); 583 SendResponse(false); 584 } 585 586} 587 588void ManagementUninstallFunctionBase::ExtensionUninstallAccepted() { 589 Finish(true); 590 Release(); 591} 592 593void ManagementUninstallFunctionBase::ExtensionUninstallCanceled() { 594 Finish(false); 595 Release(); 596} 597 598ManagementUninstallFunction::ManagementUninstallFunction() { 599} 600 601ManagementUninstallFunction::~ManagementUninstallFunction() { 602} 603 604bool ManagementUninstallFunction::RunImpl() { 605 scoped_ptr<management::Uninstall::Params> params( 606 management::Uninstall::Params::Create(*args_)); 607 EXTENSION_FUNCTION_VALIDATE(extension_); 608 EXTENSION_FUNCTION_VALIDATE(params.get()); 609 610 bool show_confirm_dialog = true; 611 // By default confirmation dialog isn't shown when uninstalling self, but this 612 // can be overridden with showConfirmDialog. 613 if (params->id == extension_->id()) { 614 show_confirm_dialog = params->options.get() && 615 params->options->show_confirm_dialog.get() && 616 *params->options->show_confirm_dialog; 617 } 618 if (show_confirm_dialog && !user_gesture()) { 619 error_ = keys::kGestureNeededForUninstallError; 620 return false; 621 } 622 return Uninstall(params->id, show_confirm_dialog); 623} 624 625ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() { 626} 627 628ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() { 629} 630 631bool ManagementUninstallSelfFunction::RunImpl() { 632 scoped_ptr<management::UninstallSelf::Params> params( 633 management::UninstallSelf::Params::Create(*args_)); 634 EXTENSION_FUNCTION_VALIDATE(params.get()); 635 636 bool show_confirm_dialog = false; 637 if (params->options.get() && params->options->show_confirm_dialog.get()) 638 show_confirm_dialog = *params->options->show_confirm_dialog; 639 return Uninstall(extension_->id(), show_confirm_dialog); 640} 641 642ManagementEventRouter::ManagementEventRouter(Profile* profile) 643 : profile_(profile) { 644 int types[] = { 645 chrome::NOTIFICATION_EXTENSION_INSTALLED, 646 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 647 chrome::NOTIFICATION_EXTENSION_LOADED, 648 chrome::NOTIFICATION_EXTENSION_UNLOADED 649 }; 650 651 CHECK(registrar_.IsEmpty()); 652 for (size_t i = 0; i < arraysize(types); i++) { 653 registrar_.Add(this, 654 types[i], 655 content::Source<Profile>(profile_)); 656 } 657} 658 659ManagementEventRouter::~ManagementEventRouter() {} 660 661void ManagementEventRouter::Observe( 662 int type, 663 const content::NotificationSource& source, 664 const content::NotificationDetails& details) { 665 const char* event_name = NULL; 666 const Extension* extension = NULL; 667 Profile* profile = content::Source<Profile>(source).ptr(); 668 CHECK(profile); 669 CHECK(profile_->IsSameProfile(profile)); 670 671 switch (type) { 672 case chrome::NOTIFICATION_EXTENSION_INSTALLED: 673 event_name = management::OnInstalled::kEventName; 674 extension = 675 content::Details<const InstalledExtensionInfo>(details)->extension; 676 break; 677 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: 678 event_name = management::OnUninstalled::kEventName; 679 extension = content::Details<const Extension>(details).ptr(); 680 break; 681 case chrome::NOTIFICATION_EXTENSION_LOADED: 682 event_name = management::OnEnabled::kEventName; 683 extension = content::Details<const Extension>(details).ptr(); 684 break; 685 case chrome::NOTIFICATION_EXTENSION_UNLOADED: 686 event_name = management::OnDisabled::kEventName; 687 extension = 688 content::Details<const UnloadedExtensionInfo>(details)->extension; 689 break; 690 default: 691 NOTREACHED(); 692 return; 693 } 694 DCHECK(event_name); 695 DCHECK(extension); 696 697 if (extension->ShouldNotBeVisible()) 698 return; // Don't dispatch events for built-in extensions. 699 700 scoped_ptr<base::ListValue> args(new base::ListValue()); 701 if (event_name == management::OnUninstalled::kEventName) { 702 args->Append(new base::StringValue(extension->id())); 703 } else { 704 scoped_ptr<management::ExtensionInfo> info = CreateExtensionInfo( 705 *extension, ExtensionSystem::Get(profile)); 706 args->Append(info->ToValue().release()); 707 } 708 709 scoped_ptr<Event> event(new Event(event_name, args.Pass())); 710 ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass()); 711} 712 713ManagementAPI::ManagementAPI(Profile* profile) 714 : profile_(profile) { 715 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 716 this, management::OnInstalled::kEventName); 717 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 718 this, management::OnUninstalled::kEventName); 719 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 720 this, management::OnEnabled::kEventName); 721 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 722 this, management::OnDisabled::kEventName); 723} 724 725ManagementAPI::~ManagementAPI() { 726} 727 728void ManagementAPI::Shutdown() { 729 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 730} 731 732static base::LazyInstance<ProfileKeyedAPIFactory<ManagementAPI> > 733g_factory = LAZY_INSTANCE_INITIALIZER; 734 735// static 736ProfileKeyedAPIFactory<ManagementAPI>* ManagementAPI::GetFactoryInstance() { 737 return g_factory.Pointer(); 738} 739 740void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) { 741 management_event_router_.reset(new ManagementEventRouter(profile_)); 742 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 743} 744 745} // namespace extensions 746