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