1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/api/autotest_private/autotest_private_api.h"
6
7#include "base/lazy_instance.h"
8#include "base/strings/string_number_conversions.h"
9#include "chrome/browser/extensions/extension_action_manager.h"
10#include "chrome/browser/extensions/extension_service.h"
11#include "chrome/browser/extensions/extension_util.h"
12#include "chrome/browser/lifetime/application_lifetime.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/common/extensions/api/autotest_private.h"
15#include "extensions/browser/extension_function_registry.h"
16#include "extensions/browser/extension_registry.h"
17#include "extensions/browser/extension_system.h"
18#include "extensions/common/manifest_handlers/background_info.h"
19#include "extensions/common/manifest_handlers/options_page_info.h"
20#include "extensions/common/permissions/api_permission_set.h"
21#include "extensions/common/permissions/permission_set.h"
22#include "extensions/common/permissions/permissions_data.h"
23
24#if defined(OS_CHROMEOS)
25#include "chrome/browser/chromeos/login/lock/screen_locker.h"
26#include "chromeos/dbus/dbus_thread_manager.h"
27#include "chromeos/dbus/session_manager_client.h"
28#include "components/user_manager/user.h"
29#include "components/user_manager/user_manager.h"
30#endif
31
32namespace extensions {
33namespace {
34
35base::ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
36  const PermissionsData* permissions_data = ext->permissions_data();
37  const URLPatternSet& pattern_set =
38      effective_perm ? permissions_data->GetEffectiveHostPermissions()
39                     : permissions_data->active_permissions()->explicit_hosts();
40
41  base::ListValue* permissions = new base::ListValue;
42  for (URLPatternSet::const_iterator perm = pattern_set.begin();
43       perm != pattern_set.end();
44       ++perm) {
45    permissions->Append(new base::StringValue(perm->GetAsString()));
46  }
47
48  return permissions;
49}
50
51base::ListValue* GetAPIPermissions(const Extension* ext) {
52  base::ListValue* permissions = new base::ListValue;
53  std::set<std::string> perm_list =
54      ext->permissions_data()->active_permissions()->GetAPIsAsStrings();
55  for (std::set<std::string>::const_iterator perm = perm_list.begin();
56       perm != perm_list.end(); ++perm) {
57    permissions->Append(new base::StringValue(perm->c_str()));
58  }
59  return permissions;
60}
61
62bool IsTestMode(Profile* profile) {
63  return AutotestPrivateAPI::GetFactoryInstance()->Get(profile)->test_mode();
64}
65
66}  // namespace
67
68bool AutotestPrivateLogoutFunction::RunSync() {
69  DVLOG(1) << "AutotestPrivateLogoutFunction";
70  if (!IsTestMode(GetProfile()))
71    chrome::AttemptUserExit();
72  return true;
73}
74
75bool AutotestPrivateRestartFunction::RunSync() {
76  DVLOG(1) << "AutotestPrivateRestartFunction";
77  if (!IsTestMode(GetProfile()))
78    chrome::AttemptRestart();
79  return true;
80}
81
82bool AutotestPrivateShutdownFunction::RunSync() {
83  scoped_ptr<api::autotest_private::Shutdown::Params> params(
84      api::autotest_private::Shutdown::Params::Create(*args_));
85  EXTENSION_FUNCTION_VALIDATE(params.get());
86
87  DVLOG(1) << "AutotestPrivateShutdownFunction " << params->force;
88
89  if (!IsTestMode(GetProfile()))
90    chrome::AttemptExit();
91  return true;
92}
93
94bool AutotestPrivateLoginStatusFunction::RunSync() {
95  DVLOG(1) << "AutotestPrivateLoginStatusFunction";
96
97  base::DictionaryValue* result(new base::DictionaryValue);
98#if defined(OS_CHROMEOS)
99  const user_manager::UserManager* user_manager =
100      user_manager::UserManager::Get();
101  const bool is_screen_locked =
102      !!chromeos::ScreenLocker::default_screen_locker();
103
104  if (user_manager) {
105    result->SetBoolean("isLoggedIn", user_manager->IsUserLoggedIn());
106    result->SetBoolean("isOwner", user_manager->IsCurrentUserOwner());
107    result->SetBoolean("isScreenLocked", is_screen_locked);
108    if (user_manager->IsUserLoggedIn()) {
109      result->SetBoolean("isRegularUser",
110                         user_manager->IsLoggedInAsRegularUser());
111      result->SetBoolean("isGuest", user_manager->IsLoggedInAsGuest());
112      result->SetBoolean("isKiosk", user_manager->IsLoggedInAsKioskApp());
113
114      const user_manager::User* user = user_manager->GetLoggedInUser();
115      result->SetString("email", user->email());
116      result->SetString("displayEmail", user->display_email());
117
118      std::string user_image;
119      switch (user->image_index()) {
120        case user_manager::User::USER_IMAGE_EXTERNAL:
121          user_image = "file";
122          break;
123
124        case user_manager::User::USER_IMAGE_PROFILE:
125          user_image = "profile";
126          break;
127
128        default:
129          user_image = base::IntToString(user->image_index());
130          break;
131      }
132      result->SetString("userImage", user_image);
133    }
134  }
135#endif
136
137  SetResult(result);
138  return true;
139}
140
141bool AutotestPrivateLockScreenFunction::RunSync() {
142  DVLOG(1) << "AutotestPrivateLockScreenFunction";
143#if defined(OS_CHROMEOS)
144  chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
145      RequestLockScreen();
146#endif
147  return true;
148}
149
150bool AutotestPrivateGetExtensionsInfoFunction::RunSync() {
151  DVLOG(1) << "AutotestPrivateGetExtensionsInfoFunction";
152
153  ExtensionService* service =
154      ExtensionSystem::Get(GetProfile())->extension_service();
155  ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
156  const ExtensionSet& extensions = registry->enabled_extensions();
157  const ExtensionSet& disabled_extensions = registry->disabled_extensions();
158  ExtensionActionManager* extension_action_manager =
159      ExtensionActionManager::Get(GetProfile());
160
161  base::ListValue* extensions_values = new base::ListValue;
162  ExtensionList all;
163  all.insert(all.end(), extensions.begin(), extensions.end());
164  all.insert(all.end(), disabled_extensions.begin(), disabled_extensions.end());
165  for (ExtensionList::const_iterator it = all.begin();
166       it != all.end(); ++it) {
167    const Extension* extension = it->get();
168    std::string id = extension->id();
169    base::DictionaryValue* extension_value = new base::DictionaryValue;
170    extension_value->SetString("id", id);
171    extension_value->SetString("version", extension->VersionString());
172    extension_value->SetString("name", extension->name());
173    extension_value->SetString("publicKey", extension->public_key());
174    extension_value->SetString("description", extension->description());
175    extension_value->SetString(
176        "backgroundUrl", BackgroundInfo::GetBackgroundURL(extension).spec());
177    extension_value->SetString(
178        "optionsUrl", OptionsPageInfo::GetOptionsPage(extension).spec());
179
180    extension_value->Set("hostPermissions",
181                         GetHostPermissions(extension, false));
182    extension_value->Set("effectiveHostPermissions",
183                         GetHostPermissions(extension, true));
184    extension_value->Set("apiPermissions", GetAPIPermissions(extension));
185
186    Manifest::Location location = extension->location();
187    extension_value->SetBoolean("isComponent",
188                                location == Manifest::COMPONENT);
189    extension_value->SetBoolean("isInternal",
190                                location == Manifest::INTERNAL);
191    extension_value->SetBoolean("isUserInstalled",
192        location == Manifest::INTERNAL ||
193        Manifest::IsUnpackedLocation(location));
194    extension_value->SetBoolean("isEnabled", service->IsExtensionEnabled(id));
195    extension_value->SetBoolean("allowedInIncognito",
196        util::IsIncognitoEnabled(id, GetProfile()));
197    extension_value->SetBoolean(
198        "hasPageAction",
199        extension_action_manager->GetPageAction(*extension) != NULL);
200
201    extensions_values->Append(extension_value);
202  }
203
204  base::DictionaryValue* return_value(new base::DictionaryValue);
205  return_value->Set("extensions", extensions_values);
206  SetResult(return_value);
207  return true;
208}
209
210static int AccessArray(const volatile int arr[], const volatile int *index) {
211  return arr[*index];
212}
213
214bool AutotestPrivateSimulateAsanMemoryBugFunction::RunSync() {
215  DVLOG(1) << "AutotestPrivateSimulateAsanMemoryBugFunction";
216  if (!IsTestMode(GetProfile())) {
217    // This array is volatile not to let compiler optimize us out.
218    volatile int testarray[3] = {0, 0, 0};
219
220    // Cause Address Sanitizer to abort this process.
221    volatile int index = 5;
222    AccessArray(testarray, &index);
223  }
224  return true;
225}
226
227static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI> >
228    g_factory = LAZY_INSTANCE_INITIALIZER;
229
230// static
231BrowserContextKeyedAPIFactory<AutotestPrivateAPI>*
232AutotestPrivateAPI::GetFactoryInstance() {
233  return g_factory.Pointer();
234}
235
236template <>
237KeyedService*
238BrowserContextKeyedAPIFactory<AutotestPrivateAPI>::BuildServiceInstanceFor(
239    content::BrowserContext* context) const {
240  return new AutotestPrivateAPI();
241}
242
243AutotestPrivateAPI::AutotestPrivateAPI() : test_mode_(false) {
244}
245
246AutotestPrivateAPI::~AutotestPrivateAPI() {
247}
248
249}  // namespace extensions
250