Move Webstore URL concepts to //extensions and out
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service.cc
blob68ffa44cb8aafd74bbf6292ebc5828aa37da6478
1 // Copyright 2014 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.
5 #include "chrome/browser/signin/easy_unlock_service.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/component_loader.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h"
17 #include "chrome/browser/signin/easy_unlock_service_factory.h"
18 #include "chrome/browser/signin/easy_unlock_service_observer.h"
19 #include "chrome/browser/signin/screenlock_bridge.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "device/bluetooth/bluetooth_adapter.h"
25 #include "device/bluetooth/bluetooth_adapter_factory.h"
26 #include "extensions/browser/extension_registry.h"
27 #include "extensions/browser/extension_system.h"
28 #include "extensions/common/one_shot_event.h"
29 #include "grit/browser_resources.h"
31 #if defined(OS_CHROMEOS)
32 #include "chromeos/dbus/dbus_thread_manager.h"
33 #include "chromeos/dbus/power_manager_client.h"
34 #endif
36 namespace {
38 extensions::ComponentLoader* GetComponentLoader(
39 content::BrowserContext* context) {
40 extensions::ExtensionSystem* extension_system =
41 extensions::ExtensionSystem::Get(context);
42 ExtensionService* extension_service = extension_system->extension_service();
43 return extension_service->component_loader();
46 } // namespace
48 // static
49 EasyUnlockService* EasyUnlockService::Get(Profile* profile) {
50 return EasyUnlockServiceFactory::GetForProfile(profile);
53 class EasyUnlockService::BluetoothDetector
54 : public device::BluetoothAdapter::Observer {
55 public:
56 explicit BluetoothDetector(EasyUnlockService* service)
57 : service_(service),
58 weak_ptr_factory_(this) {
61 virtual ~BluetoothDetector() {
62 if (adapter_.get())
63 adapter_->RemoveObserver(this);
66 void Initialize() {
67 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
68 return;
70 device::BluetoothAdapterFactory::GetAdapter(
71 base::Bind(&BluetoothDetector::OnAdapterInitialized,
72 weak_ptr_factory_.GetWeakPtr()));
75 bool IsPresent() const { return adapter_.get() && adapter_->IsPresent(); }
77 // device::BluetoothAdapter::Observer:
78 virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter,
79 bool present) OVERRIDE {
80 service_->OnBluetoothAdapterPresentChanged();
83 private:
84 void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter) {
85 adapter_ = adapter;
86 adapter_->AddObserver(this);
87 service_->OnBluetoothAdapterPresentChanged();
90 // Owner of this class and should out-live this class.
91 EasyUnlockService* service_;
92 scoped_refptr<device::BluetoothAdapter> adapter_;
93 base::WeakPtrFactory<BluetoothDetector> weak_ptr_factory_;
95 DISALLOW_COPY_AND_ASSIGN(BluetoothDetector);
98 #if defined(OS_CHROMEOS)
99 class EasyUnlockService::PowerMonitor :
100 public chromeos::PowerManagerClient::Observer {
101 public:
102 explicit PowerMonitor(EasyUnlockService* service) : service_(service) {
103 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
104 AddObserver(this);
107 virtual ~PowerMonitor() {
108 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
109 RemoveObserver(this);
112 private:
113 // chromeos::PowerManagerClient::Observer:
114 virtual void SuspendImminent() OVERRIDE {
115 service_->DisableAppIfLoaded();
118 virtual void SuspendDone(const base::TimeDelta& sleep_duration) OVERRIDE {
119 service_->LoadApp();
122 EasyUnlockService* service_;
124 DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
126 #endif
128 EasyUnlockService::EasyUnlockService(Profile* profile)
129 : profile_(profile),
130 bluetooth_detector_(new BluetoothDetector(this)),
131 weak_ptr_factory_(this) {
132 extensions::ExtensionSystem::Get(profile_)->ready().Post(
133 FROM_HERE,
134 base::Bind(&EasyUnlockService::Initialize,
135 weak_ptr_factory_.GetWeakPtr()));
138 EasyUnlockService::~EasyUnlockService() {
141 // static
142 void EasyUnlockService::RegisterProfilePrefs(
143 user_prefs::PrefRegistrySyncable* registry) {
144 registry->RegisterBooleanPref(
145 prefs::kEasyUnlockEnabled,
146 false,
147 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
148 registry->RegisterBooleanPref(
149 prefs::kEasyUnlockShowTutorial,
150 true,
151 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
152 registry->RegisterDictionaryPref(
153 prefs::kEasyUnlockPairing,
154 new base::DictionaryValue(),
155 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
156 registry->RegisterBooleanPref(
157 prefs::kEasyUnlockAllowed,
158 true,
159 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
162 bool EasyUnlockService::IsAllowed() {
163 if (!IsAllowedInternal())
164 return false;
166 #if defined(OS_CHROMEOS)
167 if (!profile_->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed))
168 return false;
170 // Respect existing policy and skip finch test.
171 if (!profile_->GetPrefs()->IsManagedPreference(prefs::kEasyUnlockAllowed)) {
172 // It is disabled when the trial exists and is in "Disable" group.
173 if (base::FieldTrialList::FindFullName("EasyUnlock") == "Disable")
174 return false;
177 if (!bluetooth_detector_->IsPresent())
178 return false;
180 return true;
181 #else
182 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
183 return false;
184 #endif
187 EasyUnlockScreenlockStateHandler*
188 EasyUnlockService::GetScreenlockStateHandler() {
189 if (!IsAllowed())
190 return NULL;
191 if (!screenlock_state_handler_) {
192 screenlock_state_handler_.reset(new EasyUnlockScreenlockStateHandler(
193 GetUserEmail(),
194 GetType() == TYPE_REGULAR ? profile_->GetPrefs() : NULL,
195 ScreenlockBridge::Get()));
197 return screenlock_state_handler_.get();
200 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
201 observers_.AddObserver(observer);
204 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver* observer) {
205 observers_.RemoveObserver(observer);
208 void EasyUnlockService::LoadApp() {
209 DCHECK(IsAllowed());
211 #if defined(GOOGLE_CHROME_BUILD)
212 base::FilePath easy_unlock_path;
213 #if defined(OS_CHROMEOS)
214 easy_unlock_path = base::FilePath("/usr/share/chromeos-assets/easy_unlock");
215 #endif // defined(OS_CHROMEOS)
217 #ifndef NDEBUG
218 // Only allow app path override switch for debug build.
219 const CommandLine* command_line = CommandLine::ForCurrentProcess();
220 if (command_line->HasSwitch(switches::kEasyUnlockAppPath)) {
221 easy_unlock_path =
222 command_line->GetSwitchValuePath(switches::kEasyUnlockAppPath);
224 #endif // !defined(NDEBUG)
226 if (!easy_unlock_path.empty()) {
227 extensions::ComponentLoader* loader = GetComponentLoader(profile_);
228 if (!loader->Exists(extension_misc::kEasyUnlockAppId))
229 loader->Add(IDR_EASY_UNLOCK_MANIFEST, easy_unlock_path);
231 ExtensionService* extension_service =
232 extensions::ExtensionSystem::Get(profile_)->extension_service();
233 extension_service->EnableExtension(extension_misc::kEasyUnlockAppId);
235 #endif // defined(GOOGLE_CHROME_BUILD)
238 void EasyUnlockService::DisableAppIfLoaded() {
239 // Make sure lock screen state set by the extension gets reset.
240 screenlock_state_handler_.reset();
242 extensions::ComponentLoader* loader = GetComponentLoader(profile_);
243 if (!loader->Exists(extension_misc::kEasyUnlockAppId))
244 return;
246 ExtensionService* extension_service =
247 extensions::ExtensionSystem::Get(profile_)->extension_service();
248 extension_service->DisableExtension(extension_misc::kEasyUnlockAppId,
249 extensions::Extension::DISABLE_RELOAD);
252 void EasyUnlockService::ReloadApp() {
253 // Make sure lock screen state set by the extension gets reset.
254 screenlock_state_handler_.reset();
256 if (GetComponentLoader(profile_)->Exists(extension_misc::kEasyUnlockAppId)) {
257 extensions::ExtensionSystem* extension_system =
258 extensions::ExtensionSystem::Get(profile_);
259 extension_system->extension_service()->ReloadExtension(
260 extension_misc::kEasyUnlockAppId);
264 void EasyUnlockService::UpdateAppState() {
265 if (IsAllowed()) {
266 LoadApp();
268 #if defined(OS_CHROMEOS)
269 if (!power_monitor_)
270 power_monitor_.reset(new PowerMonitor(this));
271 #endif
272 } else {
273 DisableAppIfLoaded();
274 #if defined(OS_CHROMEOS)
275 power_monitor_.reset();
276 #endif
280 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
281 FOR_EACH_OBSERVER(
282 EasyUnlockServiceObserver, observers_, OnTurnOffOperationStatusChanged());
285 void EasyUnlockService::Initialize() {
286 InitializeInternal();
288 #if defined(OS_CHROMEOS)
289 // Only start Bluetooth detection for ChromeOS since the feature is
290 // only offered on ChromeOS. Enabling this on non-ChromeOS platforms
291 // previously introduced a performance regression: http://crbug.com/404482
292 // Make sure not to reintroduce a performance regression if re-enabling on
293 // additional platforms.
294 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
295 bluetooth_detector_->Initialize();
296 #endif // defined(OS_CHROMEOS)
299 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
300 UpdateAppState();