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