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