| OLD | NEW |
| (Empty) |
| 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/extension_management_api.h" | |
| 6 | |
| 7 #include <map> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/bind.h" | |
| 12 #include "base/json/json_writer.h" | |
| 13 #include "base/metrics/histogram.h" | |
| 14 #include "base/string_number_conversions.h" | |
| 15 #include "base/string_util.h" | |
| 16 #include "chrome/browser/extensions/event_names.h" | |
| 17 #include "chrome/browser/extensions/event_router.h" | |
| 18 #include "chrome/browser/extensions/extension_management_api_constants.h" | |
| 19 #include "chrome/browser/extensions/extension_service.h" | |
| 20 #include "chrome/browser/extensions/extension_system.h" | |
| 21 #include "chrome/browser/extensions/extension_uninstall_dialog.h" | |
| 22 #include "chrome/browser/extensions/management_policy.h" | |
| 23 #include "chrome/browser/profiles/profile.h" | |
| 24 #include "chrome/browser/ui/extensions/application_launch.h" | |
| 25 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" | |
| 26 #include "chrome/common/chrome_notification_types.h" | |
| 27 #include "chrome/common/chrome_utility_messages.h" | |
| 28 #include "chrome/common/extensions/extension.h" | |
| 29 #include "chrome/common/extensions/extension_constants.h" | |
| 30 #include "chrome/common/extensions/extension_error_utils.h" | |
| 31 #include "chrome/common/extensions/extension_icon_set.h" | |
| 32 #include "chrome/common/extensions/url_pattern.h" | |
| 33 #include "content/public/browser/notification_details.h" | |
| 34 #include "content/public/browser/notification_source.h" | |
| 35 #include "content/public/browser/utility_process_host.h" | |
| 36 #include "content/public/browser/utility_process_host_client.h" | |
| 37 | |
| 38 #if !defined(OS_ANDROID) | |
| 39 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" | |
| 40 #endif | |
| 41 | |
| 42 using base::IntToString; | |
| 43 using content::BrowserThread; | |
| 44 using content::UtilityProcessHost; | |
| 45 using content::UtilityProcessHostClient; | |
| 46 using extensions::Extension; | |
| 47 using extensions::PermissionMessages; | |
| 48 | |
| 49 namespace events = extensions::event_names; | |
| 50 namespace keys = extension_management_api_constants; | |
| 51 | |
| 52 namespace { | |
| 53 | |
| 54 enum AutoConfirmForTest { | |
| 55 DO_NOT_SKIP = 0, | |
| 56 PROCEED, | |
| 57 ABORT | |
| 58 }; | |
| 59 | |
| 60 AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP; | |
| 61 | |
| 62 } // namespace | |
| 63 | |
| 64 ExtensionService* ExtensionManagementFunction::service() { | |
| 65 return profile()->GetExtensionService(); | |
| 66 } | |
| 67 | |
| 68 ExtensionService* AsyncExtensionManagementFunction::service() { | |
| 69 return profile()->GetExtensionService(); | |
| 70 } | |
| 71 | |
| 72 static DictionaryValue* CreateExtensionInfo(const Extension& extension, | |
| 73 ExtensionService* service) { | |
| 74 DictionaryValue* info = new DictionaryValue(); | |
| 75 bool enabled = service->IsExtensionEnabled(extension.id()); | |
| 76 extension.GetBasicInfo(enabled, info); | |
| 77 | |
| 78 const extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get( | |
| 79 service->profile())->management_policy(); | |
| 80 info->SetBoolean(keys::kMayDisableKey, | |
| 81 policy->UserMayModifySettings(&extension, NULL)); | |
| 82 | |
| 83 info->SetBoolean(keys::kIsAppKey, extension.is_app()); | |
| 84 | |
| 85 if (!enabled) { | |
| 86 extensions::ExtensionPrefs* prefs = service->extension_prefs(); | |
| 87 bool permissions_escalated = | |
| 88 prefs->DidExtensionEscalatePermissions(extension.id()); | |
| 89 const char* reason = permissions_escalated ? | |
| 90 keys::kDisabledReasonPermissionsIncrease : keys::kDisabledReasonUnknown; | |
| 91 info->SetString(keys::kDisabledReasonKey, reason); | |
| 92 } | |
| 93 | |
| 94 if (!extension.update_url().is_empty()) | |
| 95 info->SetString(keys::kUpdateUrlKey, | |
| 96 extension.update_url().possibly_invalid_spec()); | |
| 97 if (extension.is_app()) | |
| 98 info->SetString(keys::kAppLaunchUrlKey, | |
| 99 extension.GetFullLaunchURL().possibly_invalid_spec()); | |
| 100 | |
| 101 const ExtensionIconSet::IconMap& icons = extension.icons().map(); | |
| 102 if (!icons.empty()) { | |
| 103 ListValue* icon_list = new ListValue(); | |
| 104 std::map<ExtensionIconSet::Icons, std::string>::const_iterator icon_iter; | |
| 105 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) { | |
| 106 DictionaryValue* icon_info = new DictionaryValue(); | |
| 107 ExtensionIconSet::Icons size = icon_iter->first; | |
| 108 GURL url = ExtensionIconSource::GetIconURL( | |
| 109 &extension, size, ExtensionIconSet::MATCH_EXACTLY, false, NULL); | |
| 110 icon_info->SetInteger(keys::kSizeKey, icon_iter->first); | |
| 111 icon_info->SetString(keys::kUrlKey, url.spec()); | |
| 112 icon_list->Append(icon_info); | |
| 113 } | |
| 114 info->Set(keys::kIconsKey, icon_list); | |
| 115 } | |
| 116 | |
| 117 const std::set<std::string> perms = | |
| 118 extension.GetActivePermissions()->GetAPIsAsStrings(); | |
| 119 ListValue* permission_list = new ListValue(); | |
| 120 if (!perms.empty()) { | |
| 121 std::set<std::string>::const_iterator perms_iter; | |
| 122 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter) { | |
| 123 StringValue* permission_name = new StringValue(*perms_iter); | |
| 124 permission_list->Append(permission_name); | |
| 125 } | |
| 126 } | |
| 127 info->Set(keys::kPermissionsKey, permission_list); | |
| 128 | |
| 129 ListValue* host_permission_list = new ListValue(); | |
| 130 if (!extension.is_hosted_app()) { | |
| 131 // Skip host permissions for hosted apps. | |
| 132 const URLPatternSet host_perms = | |
| 133 extension.GetActivePermissions()->explicit_hosts(); | |
| 134 if (!host_perms.is_empty()) { | |
| 135 URLPatternSet::const_iterator host_perms_iter; | |
| 136 for (host_perms_iter = host_perms.begin(); | |
| 137 host_perms_iter != host_perms.end(); | |
| 138 ++host_perms_iter) { | |
| 139 StringValue* name = new StringValue(host_perms_iter->GetAsString()); | |
| 140 host_permission_list->Append(name); | |
| 141 } | |
| 142 } | |
| 143 } | |
| 144 info->Set(keys::kHostPermissionsKey, host_permission_list); | |
| 145 | |
| 146 return info; | |
| 147 } | |
| 148 | |
| 149 static void AddExtensionInfo(ListValue* list, | |
| 150 const ExtensionSet& extensions, | |
| 151 ExtensionService* service) { | |
| 152 for (ExtensionSet::const_iterator i = extensions.begin(); | |
| 153 i != extensions.end(); ++i) { | |
| 154 const Extension& extension = **i; | |
| 155 | |
| 156 if (extension.location() == Extension::COMPONENT) | |
| 157 continue; // Skip built-in extensions. | |
| 158 | |
| 159 list->Append(CreateExtensionInfo(extension, service)); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 bool GetAllExtensionsFunction::RunImpl() { | |
| 164 ListValue* result = new ListValue(); | |
| 165 SetResult(result); | |
| 166 | |
| 167 AddExtensionInfo(result, *service()->extensions(), service()); | |
| 168 AddExtensionInfo(result, *service()->disabled_extensions(), service()); | |
| 169 | |
| 170 return true; | |
| 171 } | |
| 172 | |
| 173 bool GetExtensionByIdFunction::RunImpl() { | |
| 174 std::string extension_id; | |
| 175 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); | |
| 176 const Extension* extension = service()->GetExtensionById(extension_id, true); | |
| 177 if (!extension) { | |
| 178 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoExtensionError, | |
| 179 extension_id); | |
| 180 return false; | |
| 181 } | |
| 182 DictionaryValue* result = CreateExtensionInfo(*extension, service()); | |
| 183 SetResult(result); | |
| 184 | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 bool GetPermissionWarningsByIdFunction::RunImpl() { | |
| 189 std::string ext_id; | |
| 190 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &ext_id)); | |
| 191 | |
| 192 const Extension* extension = service()->GetExtensionById(ext_id, true); | |
| 193 if (!extension) { | |
| 194 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoExtensionError, | |
| 195 ext_id); | |
| 196 return false; | |
| 197 } | |
| 198 | |
| 199 PermissionMessages warnings = extension->GetPermissionMessages(); | |
| 200 ListValue* result = new ListValue(); | |
| 201 for (PermissionMessages::const_iterator i = warnings.begin(); | |
| 202 i < warnings.end(); ++i) | |
| 203 result->Append(Value::CreateStringValue(i->message())); | |
| 204 SetResult(result); | |
| 205 return true; | |
| 206 } | |
| 207 | |
| 208 namespace { | |
| 209 | |
| 210 // This class helps GetPermissionWarningsByManifestFunction manage | |
| 211 // sending manifest JSON strings to the utility process for parsing. | |
| 212 class SafeManifestJSONParser : public UtilityProcessHostClient { | |
| 213 public: | |
| 214 SafeManifestJSONParser(GetPermissionWarningsByManifestFunction* client, | |
| 215 const std::string& manifest) | |
| 216 : client_(client), | |
| 217 manifest_(manifest) {} | |
| 218 | |
| 219 void Start() { | |
| 220 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 221 BrowserThread::PostTask( | |
| 222 BrowserThread::IO, | |
| 223 FROM_HERE, | |
| 224 base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this)); | |
| 225 } | |
| 226 | |
| 227 void StartWorkOnIOThread() { | |
| 228 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 229 UtilityProcessHost* host = | |
| 230 UtilityProcessHost::Create(this, BrowserThread::IO); | |
| 231 host->EnableZygote(); | |
| 232 host->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); | |
| 233 } | |
| 234 | |
| 235 virtual bool OnMessageReceived(const IPC::Message& message) { | |
| 236 bool handled = true; | |
| 237 IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message) | |
| 238 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, | |
| 239 OnJSONParseSucceeded) | |
| 240 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, | |
| 241 OnJSONParseFailed) | |
| 242 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 243 IPC_END_MESSAGE_MAP() | |
| 244 return handled; | |
| 245 } | |
| 246 | |
| 247 void OnJSONParseSucceeded(const ListValue& wrapper) { | |
| 248 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 249 Value* value = NULL; | |
| 250 CHECK(wrapper.Get(0, &value)); | |
| 251 if (value->IsType(Value::TYPE_DICTIONARY)) | |
| 252 parsed_manifest_.reset(static_cast<DictionaryValue*>(value)->DeepCopy()); | |
| 253 else | |
| 254 error_ = keys::kManifestParseError; | |
| 255 | |
| 256 BrowserThread::PostTask( | |
| 257 BrowserThread::UI, | |
| 258 FROM_HERE, | |
| 259 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); | |
| 260 } | |
| 261 | |
| 262 void OnJSONParseFailed(const std::string& error) { | |
| 263 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 264 error_ = error; | |
| 265 BrowserThread::PostTask( | |
| 266 BrowserThread::UI, | |
| 267 FROM_HERE, | |
| 268 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); | |
| 269 } | |
| 270 | |
| 271 void ReportResultFromUIThread() { | |
| 272 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 273 if (error_.empty() && parsed_manifest_.get()) | |
| 274 client_->OnParseSuccess(parsed_manifest_.release()); | |
| 275 else | |
| 276 client_->OnParseFailure(error_); | |
| 277 } | |
| 278 | |
| 279 private: | |
| 280 ~SafeManifestJSONParser() {} | |
| 281 | |
| 282 // The client who we'll report results back to. | |
| 283 GetPermissionWarningsByManifestFunction* client_; | |
| 284 | |
| 285 // Data to parse. | |
| 286 std::string manifest_; | |
| 287 | |
| 288 // Results of parsing. | |
| 289 scoped_ptr<DictionaryValue> parsed_manifest_; | |
| 290 | |
| 291 std::string error_; | |
| 292 }; | |
| 293 | |
| 294 } // namespace | |
| 295 | |
| 296 bool GetPermissionWarningsByManifestFunction::RunImpl() { | |
| 297 std::string manifest_str; | |
| 298 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &manifest_str)); | |
| 299 | |
| 300 scoped_refptr<SafeManifestJSONParser> parser = | |
| 301 new SafeManifestJSONParser(this, manifest_str); | |
| 302 parser->Start(); | |
| 303 | |
| 304 // Matched with a Release() in OnParseSuccess/Failure(). | |
| 305 AddRef(); | |
| 306 | |
| 307 // Response is sent async in OnParseSuccess/Failure(). | |
| 308 return true; | |
| 309 } | |
| 310 | |
| 311 void GetPermissionWarningsByManifestFunction::OnParseSuccess( | |
| 312 DictionaryValue* parsed_manifest) { | |
| 313 CHECK(parsed_manifest); | |
| 314 | |
| 315 scoped_refptr<Extension> extension = Extension::Create( | |
| 316 FilePath(), Extension::INVALID, *parsed_manifest, Extension::NO_FLAGS, | |
| 317 &error_); | |
| 318 if (!extension.get()) { | |
| 319 OnParseFailure(keys::kExtensionCreateError); | |
| 320 return; | |
| 321 } | |
| 322 | |
| 323 PermissionMessages warnings = extension->GetPermissionMessages(); | |
| 324 ListValue* result = new ListValue(); | |
| 325 for (PermissionMessages::const_iterator i = warnings.begin(); | |
| 326 i < warnings.end(); ++i) | |
| 327 result->Append(Value::CreateStringValue(i->message())); | |
| 328 SetResult(result); | |
| 329 SendResponse(true); | |
| 330 | |
| 331 // Matched with AddRef() in RunImpl(). | |
| 332 Release(); | |
| 333 } | |
| 334 | |
| 335 void GetPermissionWarningsByManifestFunction::OnParseFailure( | |
| 336 const std::string& error) { | |
| 337 error_ = error; | |
| 338 SendResponse(false); | |
| 339 | |
| 340 // Matched with AddRef() in RunImpl(). | |
| 341 Release(); | |
| 342 } | |
| 343 | |
| 344 bool LaunchAppFunction::RunImpl() { | |
| 345 std::string extension_id; | |
| 346 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); | |
| 347 const Extension* extension = service()->GetExtensionById(extension_id, true); | |
| 348 if (!extension) { | |
| 349 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoExtensionError, | |
| 350 extension_id); | |
| 351 return false; | |
| 352 } | |
| 353 if (!extension->is_app()) { | |
| 354 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNotAnAppError, | |
| 355 extension_id); | |
| 356 return false; | |
| 357 } | |
| 358 | |
| 359 // Look at prefs to find the right launch container. | |
| 360 // |default_pref_value| is set to LAUNCH_REGULAR so that if | |
| 361 // the user has not set a preference, we open the app in a tab. | |
| 362 extension_misc::LaunchContainer launch_container = | |
| 363 service()->extension_prefs()->GetLaunchContainer( | |
| 364 extension, extensions::ExtensionPrefs::LAUNCH_DEFAULT); | |
| 365 application_launch::OpenApplication(application_launch::LaunchParams( | |
| 366 profile(), extension, launch_container, NEW_FOREGROUND_TAB)); | |
| 367 #if !defined(OS_ANDROID) | |
| 368 AppLauncherHandler::RecordAppLaunchType( | |
| 369 extension_misc::APP_LAUNCH_EXTENSION_API); | |
| 370 #endif | |
| 371 | |
| 372 return true; | |
| 373 } | |
| 374 | |
| 375 SetEnabledFunction::SetEnabledFunction() { | |
| 376 } | |
| 377 | |
| 378 SetEnabledFunction::~SetEnabledFunction() { | |
| 379 } | |
| 380 | |
| 381 bool SetEnabledFunction::RunImpl() { | |
| 382 bool enable; | |
| 383 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id_)); | |
| 384 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &enable)); | |
| 385 | |
| 386 const Extension* extension = service()->GetExtensionById(extension_id_, true); | |
| 387 if (!extension) { | |
| 388 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
| 389 keys::kNoExtensionError, extension_id_); | |
| 390 return false; | |
| 391 } | |
| 392 | |
| 393 const extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get( | |
| 394 profile())->management_policy(); | |
| 395 if (!policy->UserMayModifySettings(extension, NULL)) { | |
| 396 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
| 397 keys::kUserCantModifyError, extension_id_); | |
| 398 return false; | |
| 399 } | |
| 400 | |
| 401 bool currently_enabled = service()->IsExtensionEnabled(extension_id_); | |
| 402 | |
| 403 if (!currently_enabled && enable) { | |
| 404 extensions::ExtensionPrefs* prefs = service()->extension_prefs(); | |
| 405 if (prefs->DidExtensionEscalatePermissions(extension_id_)) { | |
| 406 if (!user_gesture()) { | |
| 407 error_ = keys::kGestureNeededForEscalationError; | |
| 408 return false; | |
| 409 } | |
| 410 AddRef(); // Matched in InstallUIProceed/InstallUIAbort | |
| 411 install_prompt_.reset( | |
| 412 chrome::CreateExtensionInstallPromptWithBrowser(GetCurrentBrowser())); | |
| 413 install_prompt_->ConfirmReEnable(this, extension); | |
| 414 return true; | |
| 415 } | |
| 416 service()->EnableExtension(extension_id_); | |
| 417 } else if (currently_enabled && !enable) { | |
| 418 service()->DisableExtension(extension_id_, Extension::DISABLE_USER_ACTION); | |
| 419 } | |
| 420 | |
| 421 BrowserThread::PostTask( | |
| 422 BrowserThread::UI, | |
| 423 FROM_HERE, | |
| 424 base::Bind(&SetEnabledFunction::SendResponse, this, true)); | |
| 425 | |
| 426 return true; | |
| 427 } | |
| 428 | |
| 429 void SetEnabledFunction::InstallUIProceed() { | |
| 430 service()->EnableExtension(extension_id_); | |
| 431 SendResponse(true); | |
| 432 Release(); | |
| 433 } | |
| 434 | |
| 435 void SetEnabledFunction::InstallUIAbort(bool user_initiated) { | |
| 436 error_ = keys::kUserDidNotReEnableError; | |
| 437 SendResponse(false); | |
| 438 Release(); | |
| 439 } | |
| 440 | |
| 441 UninstallFunction::UninstallFunction() { | |
| 442 } | |
| 443 | |
| 444 UninstallFunction::~UninstallFunction() { | |
| 445 } | |
| 446 | |
| 447 bool UninstallFunction::RunImpl() { | |
| 448 bool show_confirm_dialog = false; | |
| 449 | |
| 450 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id_)); | |
| 451 | |
| 452 if (HasOptionalArgument(1)) { | |
| 453 DictionaryValue* options = NULL; | |
| 454 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); | |
| 455 | |
| 456 if (options->HasKey(keys::kShowConfirmDialogKey)) { | |
| 457 EXTENSION_FUNCTION_VALIDATE(options->GetBoolean( | |
| 458 keys::kShowConfirmDialogKey, &show_confirm_dialog)); | |
| 459 } | |
| 460 } | |
| 461 | |
| 462 const Extension* extension = service()->GetExtensionById(extension_id_, true); | |
| 463 if (!extension) { | |
| 464 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
| 465 keys::kNoExtensionError, extension_id_); | |
| 466 return false; | |
| 467 } | |
| 468 | |
| 469 if (!extensions::ExtensionSystem::Get( | |
| 470 profile())->management_policy()->UserMayModifySettings(extension, NULL)) { | |
| 471 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
| 472 keys::kUserCantModifyError, extension_id_); | |
| 473 return false; | |
| 474 } | |
| 475 | |
| 476 if (auto_confirm_for_test == DO_NOT_SKIP) { | |
| 477 if (show_confirm_dialog) { | |
| 478 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled | |
| 479 extension_uninstall_dialog_.reset(ExtensionUninstallDialog::Create( | |
| 480 GetCurrentBrowser(), this)); | |
| 481 extension_uninstall_dialog_->ConfirmUninstall(extension); | |
| 482 } else { | |
| 483 Finish(true); | |
| 484 } | |
| 485 } else { | |
| 486 Finish(auto_confirm_for_test == PROCEED); | |
| 487 } | |
| 488 | |
| 489 return true; | |
| 490 } | |
| 491 | |
| 492 // static | |
| 493 void UninstallFunction::SetAutoConfirmForTest(bool should_proceed) { | |
| 494 auto_confirm_for_test = should_proceed ? PROCEED : ABORT; | |
| 495 } | |
| 496 | |
| 497 void UninstallFunction::Finish(bool should_uninstall) { | |
| 498 if (should_uninstall) { | |
| 499 bool success = service()->UninstallExtension( | |
| 500 extension_id_, | |
| 501 false, /* external uninstall */ | |
| 502 NULL); | |
| 503 | |
| 504 // TODO set error_ if !success | |
| 505 SendResponse(success); | |
| 506 } else { | |
| 507 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
| 508 keys::kUninstallCanceledError, extension_id_); | |
| 509 SendResponse(false); | |
| 510 } | |
| 511 | |
| 512 } | |
| 513 | |
| 514 void UninstallFunction::ExtensionUninstallAccepted() { | |
| 515 Finish(true); | |
| 516 Release(); | |
| 517 } | |
| 518 | |
| 519 void UninstallFunction::ExtensionUninstallCanceled() { | |
| 520 Finish(false); | |
| 521 Release(); | |
| 522 } | |
| 523 | |
| 524 ExtensionManagementEventRouter::ExtensionManagementEventRouter(Profile* profile) | |
| 525 : profile_(profile) {} | |
| 526 | |
| 527 ExtensionManagementEventRouter::~ExtensionManagementEventRouter() {} | |
| 528 | |
| 529 void ExtensionManagementEventRouter::Init() { | |
| 530 int types[] = { | |
| 531 chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
| 532 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | |
| 533 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 534 chrome::NOTIFICATION_EXTENSION_UNLOADED | |
| 535 }; | |
| 536 | |
| 537 CHECK(registrar_.IsEmpty()); | |
| 538 for (size_t i = 0; i < arraysize(types); i++) { | |
| 539 registrar_.Add(this, | |
| 540 types[i], | |
| 541 content::Source<Profile>(profile_)); | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 void ExtensionManagementEventRouter::Observe( | |
| 546 int type, | |
| 547 const content::NotificationSource& source, | |
| 548 const content::NotificationDetails& details) { | |
| 549 const char* event_name = NULL; | |
| 550 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 551 CHECK(profile); | |
| 552 CHECK(profile_->IsSameProfile(profile)); | |
| 553 | |
| 554 switch (type) { | |
| 555 case chrome::NOTIFICATION_EXTENSION_INSTALLED: | |
| 556 event_name = events::kOnExtensionInstalled; | |
| 557 break; | |
| 558 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: | |
| 559 event_name = events::kOnExtensionUninstalled; | |
| 560 break; | |
| 561 case chrome::NOTIFICATION_EXTENSION_LOADED: | |
| 562 event_name = events::kOnExtensionEnabled; | |
| 563 break; | |
| 564 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | |
| 565 event_name = events::kOnExtensionDisabled; | |
| 566 break; | |
| 567 default: | |
| 568 NOTREACHED(); | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 ListValue args; | |
| 573 if (event_name == events::kOnExtensionUninstalled) { | |
| 574 args.Append(Value::CreateStringValue( | |
| 575 content::Details<const extensions::Extension>(details).ptr()->id())); | |
| 576 } else { | |
| 577 const Extension* extension = NULL; | |
| 578 if (event_name == events::kOnExtensionDisabled) { | |
| 579 extension = content::Details<extensions::UnloadedExtensionInfo>( | |
| 580 details)->extension; | |
| 581 } else { | |
| 582 extension = content::Details<const Extension>(details).ptr(); | |
| 583 } | |
| 584 CHECK(extension); | |
| 585 ExtensionService* service = profile->GetExtensionService(); | |
| 586 args.Append(CreateExtensionInfo(*extension, service)); | |
| 587 } | |
| 588 | |
| 589 std::string args_json; | |
| 590 base::JSONWriter::Write(&args, &args_json); | |
| 591 | |
| 592 profile->GetExtensionEventRouter()->DispatchEventToRenderers( | |
| 593 event_name, args_json, NULL, GURL(), extensions::EventFilteringInfo()); | |
| 594 } | |
| OLD | NEW |