Commit 390ac978 authored by tbarzic's avatar tbarzic Committed by Commit bot

Introduce EasyUnlockService class for signin profile

This makes EasyUnlockService pure virtual base class and introduces
separate implementations for regular and signin profiles. Common code
for both service types is kept in EasyUnlockService class.

EasyunlockService for signin profile is left empty.

BUG=401634

Review URL: https://codereview.chromium.org/577683002

Cr-Commit-Position: refs/heads/master@{#295188}
parent 278b065b
......@@ -5,11 +5,12 @@
#ifndef CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_H_
#define CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_H_
#include <string>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/prefs/pref_change_registrar.h"
#include "components/keyed_service/core/keyed_service.h"
namespace base {
......@@ -23,7 +24,6 @@ class PrefRegistrySyncable;
class EasyUnlockScreenlockStateHandler;
class EasyUnlockServiceObserver;
class EasyUnlockToggleFlow;
class Profile;
class EasyUnlockService : public KeyedService {
......@@ -34,8 +34,10 @@ class EasyUnlockService : public KeyedService {
FAIL,
};
explicit EasyUnlockService(Profile* profile);
virtual ~EasyUnlockService();
enum Type {
TYPE_REGULAR,
TYPE_SIGNIN
};
// Gets EasyUnlockService instance.
static EasyUnlockService* Get(Profile* profile);
......@@ -43,13 +45,33 @@ class EasyUnlockService : public KeyedService {
// Registers Easy Unlock profile preferences.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Returns the EasyUnlockService type.
virtual Type GetType() const = 0;
// Returns the user currently associated with the service.
virtual std::string GetUserEmail() const = 0;
// Launches Easy Unlock Setup app.
void LaunchSetup();
virtual void LaunchSetup() = 0;
// Whether easy unlock is allowed to be used. If the controlling preference
// is set (from policy), this returns the preference value. Otherwise, it is
// permitted either the flag is enabled or its field trial is enabled.
bool IsAllowed();
// Gets/Sets/Clears the permit access for the local device.
virtual const base::DictionaryValue* GetPermitAccess() const = 0;
virtual void SetPermitAccess(const base::DictionaryValue& permit) = 0;
virtual void ClearPermitAccess() = 0;
// Gets/Sets/Clears the remote devices list.
virtual const base::ListValue* GetRemoteDevices() const = 0;
virtual void SetRemoteDevices(const base::ListValue& devices) = 0;
virtual void ClearRemoteDevices() = 0;
// Runs the flow for turning Easy unlock off.
virtual void RunTurnOffFlow() = 0;
// Resets the turn off flow if one is in progress.
virtual void ResetTurnOffFlow() = 0;
// Returns the cirernt turn off flow status.
virtual TurnOffFlowStatus GetTurnOffFlowStatus() const = 0;
// Gets |screenlock_state_handler_|. Returns NULL if Easy Unlock is not
// allowed. Otherwise, if |screenlock_state_handler_| is not set, an instance
......@@ -57,32 +79,28 @@ class EasyUnlockService : public KeyedService {
// Unlock gets disabled.
EasyUnlockScreenlockStateHandler* GetScreenlockStateHandler();
// Gets/Sets/Clears the permit access for the local device.
const base::DictionaryValue* GetPermitAccess() const;
void SetPermitAccess(const base::DictionaryValue& permit);
void ClearPermitAccess();
// Gets/Sets/Clears the remote devices list.
const base::ListValue* GetRemoteDevices() const;
void SetRemoteDevices(const base::ListValue& devices);
void ClearRemoteDevices();
void RunTurnOffFlow();
void ResetTurnOffFlow();
// Whether easy unlock is allowed to be used. If the controlling preference
// is set (from policy), this returns the preference value. Otherwise, it is
// permitted either the flag is enabled or its field trial is enabled.
bool IsAllowed();
void AddObserver(EasyUnlockServiceObserver* observer);
void RemoveObserver(EasyUnlockServiceObserver* observer);
TurnOffFlowStatus turn_off_flow_status() const {
return turn_off_flow_status_;
}
protected:
explicit EasyUnlockService(Profile* profile);
virtual ~EasyUnlockService();
private:
// A class to detect whether a bluetooth adapter is present.
class BluetoothDetector;
// Does service type specific initialization.
virtual void InitializeInternal() = 0;
// Initializes the service after ExtensionService is ready.
void Initialize();
// Service type specific tests for whether the service is allowed. Returns
// false if service is not allowed. If true is returned, the service may still
// not be allowed if common tests fail (e.g. if Bluetooth is not available).
virtual bool IsAllowedInternal() = 0;
// Exposes the profile to which the service is attached to subclasses.
Profile* profile() const { return profile_; }
// Installs the Easy unlock component app if it isn't installed or enables
// the app if it is installed but disabled.
......@@ -91,30 +109,31 @@ class EasyUnlockService : public KeyedService {
// Disables the Easy unlock component app if it's loaded.
void DisableAppIfLoaded();
// Reloads the Easy unlock component app if it's loaded.
void ReloadApp();
// Checks whether Easy unlock should be running and updates app state.
void UpdateAppState();
// Callback when the controlling pref changes.
void OnPrefsChanged();
// Notifies observers that the turn off flow status changed.
void NotifyTurnOffOperationStatusChanged();
// Callback when Bluetooth adapter present state changes.
void OnBluetoothAdapterPresentChanged();
private:
// A class to detect whether a bluetooth adapter is present.
class BluetoothDetector;
// Sets the new turn-off flow status.
void SetTurnOffFlowStatus(TurnOffFlowStatus status);
// Initializes the service after ExtensionService is ready.
void Initialize();
// Callback invoked when turn off flow has finished.
void OnTurnOffFlowFinished(bool success);
// Callback when Bluetooth adapter present state changes.
void OnBluetoothAdapterPresentChanged();
Profile* profile_;
PrefChangeRegistrar registrar_;
scoped_ptr<BluetoothDetector> bluetooth_detector_;
// Created lazily in |GetScreenlockStateHandler|.
scoped_ptr<EasyUnlockScreenlockStateHandler> screenlock_state_handler_;
TurnOffFlowStatus turn_off_flow_status_;
scoped_ptr<EasyUnlockToggleFlow> turn_off_flow_;
ObserverList<EasyUnlockServiceObserver> observers_;
scoped_ptr<BluetoothDetector> bluetooth_detector_;
#if defined(OS_CHROMEOS)
// Monitors suspend and wake state of ChromeOS.
......@@ -122,6 +141,8 @@ class EasyUnlockService : public KeyedService {
scoped_ptr<PowerMonitor> power_monitor_;
#endif
ObserverList<EasyUnlockServiceObserver> observers_;
base::WeakPtrFactory<EasyUnlockService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockService);
......
......@@ -8,12 +8,14 @@
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/easy_unlock_service.h"
#include "chrome/browser/signin/easy_unlock_service_regular.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "extensions/browser/extension_system_provider.h"
#include "extensions/browser/extensions_browser_client.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h"
#endif
// static
......@@ -41,17 +43,17 @@ EasyUnlockServiceFactory::~EasyUnlockServiceFactory() {
KeyedService* EasyUnlockServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return new EasyUnlockService(Profile::FromBrowserContext(context));
}
content::BrowserContext* EasyUnlockServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
#if defined(OS_CHROMEOS)
if (chromeos::ProfileHelper::IsSigninProfile(
Profile::FromBrowserContext(context))) {
return NULL;
return new EasyUnlockServiceSignin(Profile::FromBrowserContext(context));
}
#endif
return new EasyUnlockServiceRegular(Profile::FromBrowserContext(context));
}
content::BrowserContext* EasyUnlockServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/signin/easy_unlock_service_regular.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/easy_unlock_toggle_flow.h"
#include "chrome/browser/signin/screenlock_bridge.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "extensions/browser/extension_system.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "components/user_manager/user_manager.h"
#endif
namespace {
// Key name of the local device permit record dictonary in kEasyUnlockPairing.
const char kKeyPermitAccess[] = "permitAccess";
// Key name of the remote device list in kEasyUnlockPairing.
const char kKeyDevices[] = "devices";
// Key name of the phone public key in a device dictionary.
const char kKeyPhoneId[] = "permitRecord.id";
} // namespace
EasyUnlockServiceRegular::EasyUnlockServiceRegular(Profile* profile)
: EasyUnlockService(profile),
turn_off_flow_status_(EasyUnlockService::IDLE) {
}
EasyUnlockServiceRegular::~EasyUnlockServiceRegular() {
}
EasyUnlockService::Type EasyUnlockServiceRegular::GetType() const {
return EasyUnlockService::TYPE_REGULAR;
}
std::string EasyUnlockServiceRegular::GetUserEmail() const {
return ScreenlockBridge::GetAuthenticatedUserEmail(profile());
}
void EasyUnlockServiceRegular::LaunchSetup() {
ExtensionService* service =
extensions::ExtensionSystem::Get(profile())->extension_service();
const extensions::Extension* extension =
service->GetExtensionById(extension_misc::kEasyUnlockAppId, false);
OpenApplication(AppLaunchParams(
profile(), extension, extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW));
}
const base::DictionaryValue* EasyUnlockServiceRegular::GetPermitAccess() const {
const base::DictionaryValue* pairing_dict =
profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
const base::DictionaryValue* permit_dict = NULL;
if (pairing_dict &&
pairing_dict->GetDictionary(kKeyPermitAccess, &permit_dict))
return permit_dict;
return NULL;
}
void EasyUnlockServiceRegular::SetPermitAccess(
const base::DictionaryValue& permit) {
DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
prefs::kEasyUnlockPairing);
pairing_update->SetWithoutPathExpansion(kKeyPermitAccess, permit.DeepCopy());
}
void EasyUnlockServiceRegular::ClearPermitAccess() {
DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
prefs::kEasyUnlockPairing);
pairing_update->RemoveWithoutPathExpansion(kKeyPermitAccess, NULL);
}
const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
const base::DictionaryValue* pairing_dict =
profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
const base::ListValue* devices = NULL;
if (pairing_dict && pairing_dict->GetList(kKeyDevices, &devices))
return devices;
return NULL;
}
void EasyUnlockServiceRegular::SetRemoteDevices(
const base::ListValue& devices) {
DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
prefs::kEasyUnlockPairing);
pairing_update->SetWithoutPathExpansion(kKeyDevices, devices.DeepCopy());
}
void EasyUnlockServiceRegular::ClearRemoteDevices() {
DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
prefs::kEasyUnlockPairing);
pairing_update->RemoveWithoutPathExpansion(kKeyDevices, NULL);
}
void EasyUnlockServiceRegular::RunTurnOffFlow() {
if (turn_off_flow_status_ == PENDING)
return;
SetTurnOffFlowStatus(PENDING);
// Currently there should only be one registered phone.
// TODO(xiyuan): Revisit this when server supports toggle for all or
// there are multiple phones.
const base::DictionaryValue* pairing_dict =
profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
const base::ListValue* devices_list = NULL;
const base::DictionaryValue* first_device = NULL;
std::string phone_public_key;
if (!pairing_dict || !pairing_dict->GetList(kKeyDevices, &devices_list) ||
!devices_list || !devices_list->GetDictionary(0, &first_device) ||
!first_device ||
!first_device->GetString(kKeyPhoneId, &phone_public_key)) {
LOG(WARNING) << "Bad easy unlock pairing data, wiping out local data";
OnTurnOffFlowFinished(true);
return;
}
turn_off_flow_.reset(new EasyUnlockToggleFlow(
profile(),
phone_public_key,
false,
base::Bind(&EasyUnlockServiceRegular::OnTurnOffFlowFinished,
base::Unretained(this))));
turn_off_flow_->Start();
}
void EasyUnlockServiceRegular::ResetTurnOffFlow() {
turn_off_flow_.reset();
SetTurnOffFlowStatus(IDLE);
}
EasyUnlockService::TurnOffFlowStatus
EasyUnlockServiceRegular::GetTurnOffFlowStatus() const {
return turn_off_flow_status_;
}
void EasyUnlockServiceRegular::InitializeInternal() {
registrar_.Init(profile()->GetPrefs());
registrar_.Add(
prefs::kEasyUnlockAllowed,
base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged,
base::Unretained(this)));
OnPrefsChanged();
}
bool EasyUnlockServiceRegular::IsAllowedInternal() {
#if defined(OS_CHROMEOS)
if (!user_manager::UserManager::Get()->IsLoggedInAsRegularUser())
return false;
if (!chromeos::ProfileHelper::IsPrimaryProfile(profile()))
return false;
return true;
#else
// TODO(xiyuan): Revisit when non-chromeos platforms are supported.
return false;
#endif
}
void EasyUnlockServiceRegular::OnPrefsChanged() {
UpdateAppState();
}
void EasyUnlockServiceRegular::SetTurnOffFlowStatus(TurnOffFlowStatus status) {
turn_off_flow_status_ = status;
NotifyTurnOffOperationStatusChanged();
}
void EasyUnlockServiceRegular::OnTurnOffFlowFinished(bool success) {
turn_off_flow_.reset();
if (!success) {
SetTurnOffFlowStatus(FAIL);
return;
}
ClearRemoteDevices();
SetTurnOffFlowStatus(IDLE);
ReloadApp();
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_REGULAR_H_
#define CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_REGULAR_H_
#include <string>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_change_registrar.h"
#include "chrome/browser/signin/easy_unlock_service.h"
namespace base {
class DictionaryValue;
class ListValue;
}
class EasyUnlockToggleFlow;
class Profile;
// EasyUnlockService instance that should be used for regular, non-signin
// profiles.
class EasyUnlockServiceRegular : public EasyUnlockService {
public:
explicit EasyUnlockServiceRegular(Profile* profile);
virtual ~EasyUnlockServiceRegular();
private:
// EasyUnlockService implementation.
virtual EasyUnlockService::Type GetType() const OVERRIDE;
virtual std::string GetUserEmail() const OVERRIDE;
virtual void LaunchSetup() OVERRIDE;
virtual const base::DictionaryValue* GetPermitAccess() const OVERRIDE;
virtual void SetPermitAccess(const base::DictionaryValue& permit) OVERRIDE;
virtual void ClearPermitAccess() OVERRIDE;
virtual const base::ListValue* GetRemoteDevices() const OVERRIDE;
virtual void SetRemoteDevices(const base::ListValue& devices) OVERRIDE;
virtual void ClearRemoteDevices() OVERRIDE;
virtual void RunTurnOffFlow() OVERRIDE;
virtual void ResetTurnOffFlow() OVERRIDE;
virtual TurnOffFlowStatus GetTurnOffFlowStatus() const OVERRIDE;
virtual void InitializeInternal() OVERRIDE;
virtual bool IsAllowedInternal() OVERRIDE;
// Callback when the controlling pref changes.
void OnPrefsChanged();
// Sets the new turn-off flow status.
void SetTurnOffFlowStatus(TurnOffFlowStatus status);
// Callback invoked when turn off flow has finished.
void OnTurnOffFlowFinished(bool success);
PrefChangeRegistrar registrar_;
TurnOffFlowStatus turn_off_flow_status_;
scoped_ptr<EasyUnlockToggleFlow> turn_off_flow_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceRegular);
};
#endif // CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_REGULAR_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h"
EasyUnlockServiceSignin::EasyUnlockServiceSignin(Profile* profile)
: EasyUnlockService(profile) {
}
EasyUnlockServiceSignin::~EasyUnlockServiceSignin() {
}
EasyUnlockService::Type EasyUnlockServiceSignin::GetType() const {
return EasyUnlockService::TYPE_SIGNIN;
}
std::string EasyUnlockServiceSignin::GetUserEmail() const {
// TODO(tbarzic): Implement this (http://crbug.com/401634).
return "";
}
void EasyUnlockServiceSignin::LaunchSetup() {
NOTREACHED();
}
const base::DictionaryValue* EasyUnlockServiceSignin::GetPermitAccess() const {
// TODO(tbarzic): Implement this (http://crbug.com/401634).
return NULL;
}
void EasyUnlockServiceSignin::SetPermitAccess(
const base::DictionaryValue& permit) {
NOTREACHED();
}
void EasyUnlockServiceSignin::ClearPermitAccess() {
NOTREACHED();
}
const base::ListValue* EasyUnlockServiceSignin::GetRemoteDevices() const {
// TODO(tbarzic): Implement this (http://crbug.com/401634).
return NULL;
}
void EasyUnlockServiceSignin::SetRemoteDevices(
const base::ListValue& devices) {
NOTREACHED();
}
void EasyUnlockServiceSignin::ClearRemoteDevices() {
NOTREACHED();
}
void EasyUnlockServiceSignin::RunTurnOffFlow() {
NOTREACHED();
}
void EasyUnlockServiceSignin::ResetTurnOffFlow() {
NOTREACHED();
}
EasyUnlockService::TurnOffFlowStatus
EasyUnlockServiceSignin::GetTurnOffFlowStatus() const {
return EasyUnlockService::IDLE;
}
void EasyUnlockServiceSignin::InitializeInternal() {
}
bool EasyUnlockServiceSignin::IsAllowedInternal() {
// TODO(tbarzic): Implement this (http://crbug.com/401634).
return false;
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_SIGNIN_CHROMEOS_H_
#define CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_SIGNIN_CHROMEOS_H_
#include <string>
#include "base/macros.h"
#include "chrome/browser/signin/easy_unlock_service.h"
// EasyUnlockService instance that should be used for signin profile.
class EasyUnlockServiceSignin : public EasyUnlockService {
public:
explicit EasyUnlockServiceSignin(Profile* profile);
virtual ~EasyUnlockServiceSignin();
private:
// EasyUnlockService implementation:
virtual EasyUnlockService::Type GetType() const OVERRIDE;
virtual std::string GetUserEmail() const OVERRIDE;
virtual void LaunchSetup() OVERRIDE;
virtual const base::DictionaryValue* GetPermitAccess() const OVERRIDE;
virtual void SetPermitAccess(const base::DictionaryValue& permit) OVERRIDE;
virtual void ClearPermitAccess() OVERRIDE;
virtual const base::ListValue* GetRemoteDevices() const OVERRIDE;
virtual void SetRemoteDevices(const base::ListValue& devices) OVERRIDE;
virtual void ClearRemoteDevices() OVERRIDE;
virtual void RunTurnOffFlow() OVERRIDE;
virtual void ResetTurnOffFlow() OVERRIDE;
virtual TurnOffFlowStatus GetTurnOffFlowStatus() const OVERRIDE;
virtual bool IsAllowedInternal() OVERRIDE;
virtual void InitializeInternal() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceSignin);
};
#endif // CHROME_BROWSER_SIGNIN_EASY_UNLOCK_SERVICE_SIGNIN_CHROMEOS_H_
......@@ -4,6 +4,8 @@
#include "chrome/browser/ui/webui/options/easy_unlock_handler.h"
#include <string>
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
......@@ -67,7 +69,7 @@ void EasyUnlockHandler::OnTurnOffOperationStatusChanged() {
void EasyUnlockHandler::SendTurnOffOperationStatus() {
EasyUnlockService::TurnOffFlowStatus status =
EasyUnlockService::Get(Profile::FromWebUI(web_ui()))
->turn_off_flow_status();
->GetTurnOffFlowStatus();
// Translate status into JS UI state string. Note the translated string
// should match UIState defined in easy_unlock_turn_off_overlay.js.
......
......@@ -1458,6 +1458,10 @@
'browser/signin/easy_unlock_service.h',
'browser/signin/easy_unlock_service_factory.cc',
'browser/signin/easy_unlock_service_factory.h',
'browser/signin/easy_unlock_service_regular.cc',
'browser/signin/easy_unlock_service_regular.h',
'browser/signin/easy_unlock_service_signin_chromeos.cc',
'browser/signin/easy_unlock_service_signin_chromeos.h',
'browser/signin/easy_unlock_toggle_flow.cc',
'browser/signin/easy_unlock_toggle_flow.h',
'browser/speech/extension_api/tts_engine_extension_api.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment