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