1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/extensions/extension_management_api.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <map> 8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <string> 9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/basictypes.h" 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/json/json_writer.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/metrics/histogram.h" 13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_number_conversions.h" 14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h" 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/extensions/extension_event_names.h" 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_event_router.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/extensions/extension_updater.h" 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/extension_icon_source.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension.h" 23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/extensions/extension_constants.h" 24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/extensions/extension_error_utils.h" 25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/extensions/extension_icon_set.h" 26201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/common/extensions/url_pattern.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenusing base::IntToString; 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace events = extension_event_names; 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace { 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kAppLaunchUrlKey[] = "appLaunchUrl"; 36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst char kDescriptionKey[] = "description"; 37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kEnabledKey[] = "enabled"; 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char kHomepageURLKey[] = "homepageUrl"; 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kIconsKey[] = "icons"; 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kIdKey[] = "id"; 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kIsAppKey[] = "isApp"; 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kNameKey[] = "name"; 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kOptionsUrlKey[] = "optionsUrl"; 44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst char kPermissionsKey[] = "permissions"; 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kMayDisableKey[] = "mayDisable"; 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kSizeKey[] = "size"; 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kUrlKey[] = "url"; 48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kVersionKey[] = "version"; 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kNoExtensionError[] = "No extension with id *"; 51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kNotAnAppError[] = "Extension * is not an App"; 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kUserCantDisableError[] = "Extension * can not be disabled by user"; 53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenExtensionService* ExtensionManagementFunction::service() { 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return profile()->GetExtensionService(); 57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstatic DictionaryValue* CreateExtensionInfo(const Extension& extension, 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool enabled) { 61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DictionaryValue* info = new DictionaryValue(); 62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetString(kIdKey, extension.id()); 63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetBoolean(kIsAppKey, extension.is_app()); 64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetString(kNameKey, extension.name()); 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetBoolean(kEnabledKey, enabled); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->SetBoolean(kMayDisableKey, 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Extension::UserMayDisable(extension.location())); 68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetString(kVersionKey, extension.VersionString()); 69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch info->SetString(kDescriptionKey, extension.description()); 70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch info->SetString(kOptionsUrlKey, 71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen extension.options_url().possibly_invalid_spec()); 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen info->SetString(kHomepageURLKey, 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen extension.GetHomepageURL().possibly_invalid_spec()); 74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (extension.is_app()) 75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->SetString(kAppLaunchUrlKey, 76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen extension.GetFullLaunchURL().possibly_invalid_spec()); 77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const ExtensionIconSet::IconMap& icons = extension.icons().map(); 79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!icons.empty()) { 80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ListValue* icon_list = new ListValue(); 81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::map<int, std::string>::const_iterator icon_iter; 82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) { 83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DictionaryValue* icon_info = new DictionaryValue(); 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Extension::Icons size = static_cast<Extension::Icons>(icon_iter->first); 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL url = ExtensionIconSource::GetIconURL( 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &extension, size, ExtensionIconSet::MATCH_EXACTLY, false); 87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen icon_info->SetInteger(kSizeKey, icon_iter->first); 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen icon_info->SetString(kUrlKey, url.spec()); 89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen icon_list->Append(icon_info); 90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen info->Set("icons", icon_list); 92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const std::set<std::string> perms = extension.api_permissions(); 95201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ListValue* permission_list = new ListValue(); 96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!perms.empty()) { 97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::set<std::string>::const_iterator perms_iter; 98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter) { 99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch StringValue* permission_name = new StringValue(*perms_iter); 100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch permission_list->Append(permission_name); 101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch info->Set("permissions", permission_list); 104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ListValue* host_permission_list = new ListValue(); 106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!extension.is_hosted_app()) { 107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Skip host permissions for hosted apps. 108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const URLPatternList host_perms = extension.host_permissions(); 109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!host_perms.empty()) { 110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::vector<URLPattern>::const_iterator host_perms_iter; 111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (host_perms_iter = host_perms.begin(); 112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch host_perms_iter != host_perms.end(); 113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ++host_perms_iter) { 114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch StringValue* name = new StringValue(host_perms_iter->GetAsString()); 115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch host_permission_list->Append(name); 116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch info->Set("hostPermissions", host_permission_list); 120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return info; 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstatic void AddExtensionInfo(ListValue* list, 125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const ExtensionList& extensions, 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool enabled) { 127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen for (ExtensionList::const_iterator i = extensions.begin(); 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen i != extensions.end(); ++i) { 129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const Extension& extension = **i; 130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (extension.location() == Extension::COMPONENT) 132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen continue; // Skip built-in extensions. 133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen list->Append(CreateExtensionInfo(extension, enabled)); 135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool GetAllExtensionsFunction::RunImpl() { 139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ListValue* result = new ListValue(); 140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen result_.reset(result); 141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen AddExtensionInfo(result, *service()->extensions(), true); 143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen AddExtensionInfo(result, *service()->disabled_extensions(), false); 144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return true; 146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool GetExtensionByIdFunction::RunImpl() { 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string extension_id; 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = service()->GetExtensionById(extension_id, true); 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!extension) { 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(kNoExtensionError, 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch extension_id); 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool enabled = service()->extension_prefs()-> 158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetExtensionState(extension_id) == Extension::ENABLED; 159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DictionaryValue* result = CreateExtensionInfo(*extension, enabled); 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch result_.reset(result); 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool LaunchAppFunction::RunImpl() { 167bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string extension_id; 168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = service()->GetExtensionById(extension_id, true); 170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!extension) { 171bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage(kNoExtensionError, 172bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen extension_id); 173bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 174bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!extension->is_app()) { 176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage(kNotAnAppError, 177bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen extension_id); 178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Look at prefs to find the right launch container. 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // |default_pref_value| is set to LAUNCH_REGULAR so that if 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the user has not set a preference, we open the app in a tab. 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen extension_misc::LaunchContainer launch_container = 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen service()->extension_prefs()->GetLaunchContainer( 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen extension, ExtensionPrefs::LAUNCH_DEFAULT); 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Browser::OpenApplication(profile(), extension, launch_container, NULL); 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen extension_misc::APP_LAUNCH_EXTENSION_API, 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); 191bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return true; 193bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 194bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool SetEnabledFunction::RunImpl() { 196bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string extension_id; 197bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool enable; 198bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); 199bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &enable)); 200bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 201bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!service()->GetExtensionById(extension_id, true)) { 202bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 203bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen kNoExtensionError, extension_id); 204bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 205bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 206bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 207bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ExtensionPrefs* prefs = service()->extension_prefs(); 208bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Extension::State state = prefs->GetExtensionState(extension_id); 209bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!Extension::UserMayDisable( 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prefs->GetInstalledExtensionInfo(extension_id)->extension_location)) { 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kUserCantDisableError, extension_id); 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 217bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (state == Extension::DISABLED && enable) { 218bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen service()->EnableExtension(extension_id); 219bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } else if (state == Extension::ENABLED && !enable) { 220bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen service()->DisableExtension(extension_id); 221bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 222bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 223bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return true; 224bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 225bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 226bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UninstallFunction::RunImpl() { 227bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string extension_id; 228bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id)); 229bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 230bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!service()->GetExtensionById(extension_id, true)) { 231bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 232bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen kNoExtensionError, extension_id); 233bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 234bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 235bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionPrefs* prefs = service()->extension_prefs(); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!Extension::UserMayDisable( 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prefs->GetInstalledExtensionInfo(extension_id)->extension_location)) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kUserCantDisableError, extension_id); 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen service()->UninstallExtension(extension_id, false /* external_uninstall */, 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL); 247bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return true; 248bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 249bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 250bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 251bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenExtensionManagementEventRouter* ExtensionManagementEventRouter::GetInstance() { 252bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return Singleton<ExtensionManagementEventRouter>::get(); 253bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 254bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 255bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenExtensionManagementEventRouter::ExtensionManagementEventRouter() {} 256bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 257bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenExtensionManagementEventRouter::~ExtensionManagementEventRouter() {} 258bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 259bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ExtensionManagementEventRouter::Init() { 260bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::Type types[] = { 261bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::EXTENSION_INSTALLED, 262bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::EXTENSION_UNINSTALLED, 263bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::EXTENSION_LOADED, 264bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::EXTENSION_UNLOADED 265bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen }; 266bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Don't re-init (eg in the case of multiple profiles). 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (registrar_.IsEmpty()) { 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < arraysize(types); i++) { 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_.Add(this, 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen types[i], 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationService::AllSources()); 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 274bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 275bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 276bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 277bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ExtensionManagementEventRouter::Observe( 278bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType type, 279bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const NotificationSource& source, 280bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const NotificationDetails& details) { 281bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const char* event_name = NULL; 282bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen switch (type.value) { 283bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen case NotificationType::EXTENSION_INSTALLED: 284bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen event_name = events::kOnExtensionInstalled; 285bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen break; 286bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen case NotificationType::EXTENSION_UNINSTALLED: 287bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen event_name = events::kOnExtensionUninstalled; 288bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen break; 289bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen case NotificationType::EXTENSION_LOADED: 290bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen event_name = events::kOnExtensionEnabled; 291bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen break; 292bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen case NotificationType::EXTENSION_UNLOADED: 293bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen event_name = events::kOnExtensionDisabled; 294bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen break; 295bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen default: 296bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NOTREACHED(); 297bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 298bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 299bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 300bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Profile* profile = Source<Profile>(source).ptr(); 301bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CHECK(profile); 302bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 303bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ListValue args; 304bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (event_name == events::kOnExtensionUninstalled) { 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& extension_id = 306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Details<UninstalledExtensionInfo>(details).ptr()->extension_id; 307bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen args.Append(Value::CreateStringValue(extension_id)); 308bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } else { 30921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const Extension* extension = NULL; 31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (event_name == events::kOnExtensionDisabled) { 31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen extension = Details<UnloadedExtensionInfo>(details)->extension; 31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen extension = Details<const Extension>(details).ptr(); 31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 315bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CHECK(extension); 31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile->GetExtensionService(); 317bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool enabled = service->GetExtensionById(extension->id(), false) != NULL; 318bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen args.Append(CreateExtensionInfo(*extension, enabled)); 319bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 320bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 321bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string args_json; 322bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::JSONWriter::Write(&args, false /* pretty_print */, &args_json); 323bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick profile->GetExtensionEventRouter()->DispatchEventToRenderers( 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick event_name, args_json, NULL, GURL()); 326bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 327