Commit e30241b2 authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

[CrOS Multidevice] Migrate ProximityAuthWebUIHandler to conditionally use DeviceSyncClient.

ProximityAuthWebUiHandler now uses either ProximityAuthClient or DeviceSyncClient
to get remote device info or perform Cryptauth calls, depending on whether the
chromeos::features::kMultiDeviceApi is enabled. Once the migration to DeviceSyncClient
has been completed across all of Smart Lock, code that references ProximityAuthClient will
be removed.

This is one of many future CLs which are migrating Smart Lock to use
DeviceSync Mojo API instead of directly using the CryptAuth API.

I have manually verified the correctness of this change by verifying the
output on chrome://proximity-auth.

Bug: 824568, 752273, 848956
Change-Id: Ia6bf1666f631a79c2873df3745232b8a8152bc8e
Reviewed-on: https://chromium-review.googlesource.com/1099050
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567354}
parent 17d2fcdd
......@@ -133,6 +133,7 @@
#if defined(OS_CHROMEOS)
#include "base/sys_info.h"
#include "chrome/browser/chromeos/device_sync/device_sync_client_factory.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h"
#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
......@@ -154,6 +155,7 @@
#include "chrome/browser/ui/webui/chromeos/slow_ui.h"
#include "chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_ui.h"
#include "chrome/browser/ui/webui/signin/inline_login_ui.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/proximity_auth/webui/proximity_auth_ui.h"
#include "chromeos/components/proximity_auth/webui/url_constants.h"
#endif
......@@ -259,10 +261,19 @@ WebUIController* NewWebUI<proximity_auth::ProximityAuthUI>(WebUI* web_ui,
const GURL& url) {
content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
// TODO(crbug.com/848956): Only pass DeviceSyncClient once Smart Lock has
// fully migrated to the DeviceSync API.
return new proximity_auth::ProximityAuthUI(
web_ui,
chromeos::EasyUnlockServiceFactory::GetForBrowserContext(browser_context)
->proximity_auth_client());
base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)
? nullptr
: chromeos::EasyUnlockServiceFactory::GetForBrowserContext(
browser_context)
->proximity_auth_client(),
base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)
? chromeos::device_sync::DeviceSyncClientFactory::GetForProfile(
Profile::FromBrowserContext(browser_context))
: nullptr);
}
#endif
......
......@@ -19,9 +19,12 @@ static_library("webui") {
deps = [
"//base",
"//base:i18n",
"//chromeos",
"//chromeos/components/proximity_auth",
"//chromeos/components/proximity_auth/logging",
"//chromeos/resources",
"//chromeos/services/device_sync/public/cpp",
"//chromeos/services/device_sync/public/mojom",
"//chromeos/services/multidevice_setup/public/mojom",
"//components/cryptauth",
"//components/prefs",
......
......@@ -9,6 +9,7 @@
#include "chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.h"
#include "chromeos/components/proximity_auth/webui/url_constants.h"
#include "chromeos/grit/chromeos_resources.h"
#include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
#include "components/grit/components_resources.h"
#include "content/public/browser/browser_context.h"
......@@ -19,8 +20,10 @@
namespace proximity_auth {
ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui,
ProximityAuthClient* delegate)
ProximityAuthUI::ProximityAuthUI(
content::WebUI* web_ui,
ProximityAuthClient* proximity_auth_client,
chromeos::device_sync::DeviceSyncClient* device_sync_client)
: ui::MojoWebUIController(web_ui, true /* enable_chrome_send */) {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(kChromeUIProximityAuthHost);
......@@ -49,8 +52,8 @@ ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui,
content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
content::WebUIDataSource::Add(browser_context, source);
web_ui->AddMessageHandler(
std::make_unique<ProximityAuthWebUIHandler>(delegate));
web_ui->AddMessageHandler(std::make_unique<ProximityAuthWebUIHandler>(
proximity_auth_client, device_sync_client));
AddHandlerToRegistry(base::BindRepeating(
&ProximityAuthUI::BindMultiDeviceSetup, base::Unretained(this)));
}
......
......@@ -12,6 +12,12 @@
#include "content/public/browser/web_ui_controller.h"
#include "ui/webui/mojo_web_ui_controller.h"
namespace chromeos {
namespace device_sync {
class DeviceSyncClient;
} // namespace device_sync
} // namespace chromeos
namespace proximity_auth {
class ProximityAuthClient;
......@@ -19,9 +25,11 @@ class ProximityAuthClient;
// The WebUI controller for chrome://proximity-auth.
class ProximityAuthUI : public ui::MojoWebUIController {
public:
// Note: |web_ui| and |delegate| are not owned by this instance and must
// outlive this instance.
ProximityAuthUI(content::WebUI* web_ui, ProximityAuthClient* delegate);
// Note: |web_ui| and |proximity_auth_client| are not owned by this instance
// and must outlive this instance.
ProximityAuthUI(content::WebUI* web_ui,
ProximityAuthClient* proximity_auth_client,
chromeos::device_sync::DeviceSyncClient* device_sync_client);
~ProximityAuthUI() override;
protected:
......
......@@ -15,11 +15,11 @@
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "base/values.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/components/proximity_auth/messenger.h"
#include "chromeos/components/proximity_auth/remote_device_life_cycle_impl.h"
#include "chromeos/components/proximity_auth/remote_status_update.h"
#include "chromeos/components/proximity_auth/webui/reachable_phone_flow.h"
#include "components/cryptauth/cryptauth_enrollment_manager.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/remote_device_loader.h"
......@@ -106,20 +106,29 @@ std::unique_ptr<base::DictionaryValue> CreateSyncStateDictionary(
} // namespace
ProximityAuthWebUIHandler::ProximityAuthWebUIHandler(
ProximityAuthClient* proximity_auth_client)
ProximityAuthClient* proximity_auth_client,
chromeos::device_sync::DeviceSyncClient* device_sync_client)
: proximity_auth_client_(proximity_auth_client),
device_sync_client_(device_sync_client),
web_contents_initialized_(false),
weak_ptr_factory_(this) {
if (!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
cryptauth_client_factory_ =
proximity_auth_client_->CreateCryptAuthClientFactory();
}
}
ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() {
LogBuffer::GetInstance()->RemoveObserver(this);
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->RemoveObserver(this);
} else {
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (device_manager)
device_manager->RemoveObserver(this);
}
}
void ProximityAuthWebUIHandler::RegisterMessages() {
......@@ -148,11 +157,6 @@ void ProximityAuthWebUIHandler::RegisterMessages() {
base::BindRepeating(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"findReachableDevices",
base::BindRepeating(&ProximityAuthWebUIHandler::FindReachableDevices,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getLocalState",
base::BindRepeating(&ProximityAuthWebUIHandler::GetLocalState,
......@@ -188,22 +192,19 @@ void ProximityAuthWebUIHandler::OnLogBufferCleared() {
}
void ProximityAuthWebUIHandler::OnEnrollmentStarted() {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onEnrollmentStateChanged",
*GetEnrollmentStateDictionary());
}
void ProximityAuthWebUIHandler::OnEnrollmentFinished(bool success) {
std::unique_ptr<base::DictionaryValue> enrollment_state =
GetEnrollmentStateDictionary();
PA_LOG(INFO) << "Enrollment attempt completed with success=" << success
<< ":\n"
<< *enrollment_state;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onEnrollmentStateChanged", *enrollment_state);
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
NotifyOnEnrollmentFinished(success, GetEnrollmentStateDictionary());
}
void ProximityAuthWebUIHandler::OnSyncStarted() {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onDeviceSyncStateChanged",
*GetDeviceSyncStateDictionary());
......@@ -213,27 +214,43 @@ void ProximityAuthWebUIHandler::OnSyncFinished(
cryptauth::CryptAuthDeviceManager::SyncResult sync_result,
cryptauth::CryptAuthDeviceManager::DeviceChangeResult
device_change_result) {
std::unique_ptr<base::DictionaryValue> device_sync_state =
GetDeviceSyncStateDictionary();
PA_LOG(INFO) << "Device sync completed with result="
<< static_cast<int>(sync_result) << ":\n"
<< *device_sync_state;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onDeviceSyncStateChanged", *device_sync_state);
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
NotifyOnSyncFinished(
sync_result == cryptauth::CryptAuthDeviceManager::SyncResult::
SUCCESS /* was_sync_successful */,
device_change_result == cryptauth::CryptAuthDeviceManager::
DeviceChangeResult::CHANGED /* changed */,
GetDeviceSyncStateDictionary());
}
void ProximityAuthWebUIHandler::OnEnrollmentFinished() {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
// OnGetDebugInfo() will call NotifyOnEnrollmentFinished() with the enrollment
// state info.
enrollment_update_waiting_for_debug_info_ = true;
device_sync_client_->GetDebugInfo(
base::BindOnce(&ProximityAuthWebUIHandler::OnGetDebugInfo,
weak_ptr_factory_.GetWeakPtr()));
}
if (device_change_result ==
cryptauth::CryptAuthDeviceManager::DeviceChangeResult::CHANGED) {
std::unique_ptr<base::ListValue> synced_devices = GetRemoteDevicesList();
PA_LOG(INFO) << "New unlock keys obtained after device sync:\n"
<< *synced_devices;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onRemoteDevicesChanged", *synced_devices);
}
void ProximityAuthWebUIHandler::OnNewDevicesSynced() {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
// OnGetDebugInfo() will call NotifyOnSyncFinished() with the device sync
// state info.
sync_update_waiting_for_debug_info_ = true;
device_sync_client_->GetDebugInfo(
base::BindOnce(&ProximityAuthWebUIHandler::OnGetDebugInfo,
weak_ptr_factory_.GetWeakPtr()));
}
void ProximityAuthWebUIHandler::OnWebContentsInitialized(
const base::ListValue* args) {
if (!web_contents_initialized_) {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->AddObserver(this);
} else {
cryptauth::CryptAuthEnrollmentManager* enrollment_manager =
proximity_auth_client_->GetCryptAuthEnrollmentManager();
if (enrollment_manager)
......@@ -243,6 +260,7 @@ void ProximityAuthWebUIHandler::OnWebContentsInitialized(
proximity_auth_client_->GetCryptAuthDeviceManager();
if (device_manager)
device_manager->AddObserver(this);
}
LogBuffer::GetInstance()->AddObserver(this);
......@@ -277,6 +295,13 @@ void ProximityAuthWebUIHandler::ToggleUnlockKey(const base::ListValue* args) {
return;
}
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->SetSoftwareFeatureState(
public_key, cryptauth::SoftwareFeature::EASY_UNLOCK_HOST,
true /* enabled */, true /* is_exclusive */,
base::BindOnce(&ProximityAuthWebUIHandler::OnSetSoftwareFeatureState,
weak_ptr_factory_.GetWeakPtr(), public_key));
} else {
cryptauth::ToggleEasyUnlockRequest request;
request.set_enable(make_unlock_key);
request.set_public_key(public_key);
......@@ -293,10 +318,17 @@ void ProximityAuthWebUIHandler::ToggleUnlockKey(const base::ListValue* args) {
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&ProximityAuthWebUIHandler::OnCryptAuthClientError,
weak_ptr_factory_.GetWeakPtr()));
}
}
void ProximityAuthWebUIHandler::FindEligibleUnlockDevices(
const base::ListValue* args) {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->FindEligibleDevices(
cryptauth::SoftwareFeature::EASY_UNLOCK_HOST,
base::BindOnce(&ProximityAuthWebUIHandler::OnFindEligibleDevices,
weak_ptr_factory_.GetWeakPtr()));
} else {
cryptauth_client_ = cryptauth_client_factory_->CreateInstance();
cryptauth::FindEligibleUnlockDevicesRequest request;
......@@ -308,52 +340,45 @@ void ProximityAuthWebUIHandler::FindEligibleUnlockDevices(
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&ProximityAuthWebUIHandler::OnCryptAuthClientError,
weak_ptr_factory_.GetWeakPtr()));
}
void ProximityAuthWebUIHandler::FindReachableDevices(
const base::ListValue* args) {
if (reachable_phone_flow_) {
PA_LOG(INFO) << "Waiting for existing ReachablePhoneFlow to finish.";
return;
}
reachable_phone_flow_.reset(
new ReachablePhoneFlow(cryptauth_client_factory_.get()));
reachable_phone_flow_->Run(
base::Bind(&ProximityAuthWebUIHandler::OnReachablePhonesFound,
weak_ptr_factory_.GetWeakPtr()));
}
void ProximityAuthWebUIHandler::ForceEnrollment(const base::ListValue* args) {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->ForceEnrollmentNow(
base::BindOnce(&ProximityAuthWebUIHandler::OnForceEnrollmentNow,
weak_ptr_factory_.GetWeakPtr()));
} else {
cryptauth::CryptAuthEnrollmentManager* enrollment_manager =
proximity_auth_client_->GetCryptAuthEnrollmentManager();
if (enrollment_manager) {
enrollment_manager->ForceEnrollmentNow(cryptauth::INVOCATION_REASON_MANUAL);
enrollment_manager->ForceEnrollmentNow(
cryptauth::INVOCATION_REASON_MANUAL);
}
}
}
void ProximityAuthWebUIHandler::ForceDeviceSync(const base::ListValue* args) {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->ForceSyncNow(
base::BindOnce(&ProximityAuthWebUIHandler::OnForceSyncNow,
weak_ptr_factory_.GetWeakPtr()));
} else {
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (device_manager)
device_manager->ForceSyncNow(cryptauth::INVOCATION_REASON_MANUAL);
}
}
void ProximityAuthWebUIHandler::ToggleConnection(const base::ListValue* args) {
cryptauth::CryptAuthEnrollmentManager* enrollment_manager =
proximity_auth_client_->GetCryptAuthEnrollmentManager();
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (!enrollment_manager || !device_manager)
return;
std::string b64_public_key;
std::string public_key;
if (!enrollment_manager || !device_manager || !args->GetSize() ||
!args->GetString(0, &b64_public_key) ||
if (!args->GetSize() || !args->GetString(0, &b64_public_key) ||
!base::Base64UrlDecode(b64_public_key,
base::Base64UrlDecodePolicy::REQUIRE_PADDING,
&public_key)) {
PA_LOG(ERROR) << "Unlock key (" << b64_public_key << ") not found";
return;
}
......@@ -361,15 +386,35 @@ void ProximityAuthWebUIHandler::ToggleConnection(const base::ListValue* args) {
if (selected_remote_device_)
selected_device_public_key = selected_remote_device_->public_key();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
for (const auto& remote_device : device_sync_client_->GetSyncedDevices()) {
if (remote_device.public_key() != public_key)
continue;
if (life_cycle_ && selected_device_public_key == public_key) {
CleanUpRemoteDeviceLifeCycle();
return;
}
StartRemoteDeviceLifeCycle(remote_device);
}
} else {
cryptauth::CryptAuthEnrollmentManager* enrollment_manager =
proximity_auth_client_->GetCryptAuthEnrollmentManager();
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (!enrollment_manager || !device_manager)
return;
for (const auto& unlock_key : device_manager->GetUnlockKeys()) {
if (unlock_key.public_key() == public_key) {
if (unlock_key.public_key() != public_key)
continue;
if (life_cycle_ && selected_device_public_key == public_key) {
CleanUpRemoteDeviceLifeCycle();
return;
}
// TODO(sacomoto): Pass an instance of ProximityAuthPrefManager. This is
// used to get the address of BLE devices.
remote_device_loader_.reset(new cryptauth::RemoteDeviceLoader(
std::vector<cryptauth::ExternalDeviceInfo>(1, unlock_key),
proximity_auth_client_->GetAccountId(),
......@@ -381,8 +426,6 @@ void ProximityAuthWebUIHandler::ToggleConnection(const base::ListValue* args) {
return;
}
}
PA_LOG(ERROR) << "Unlock key (" << b64_public_key << ") not found";
}
void ProximityAuthWebUIHandler::OnCryptAuthClientError(
......@@ -420,39 +463,30 @@ void ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices(
ineligible_devices);
}
void ProximityAuthWebUIHandler::OnReachablePhonesFound(
const std::vector<cryptauth::ExternalDeviceInfo>& reachable_phones) {
reachable_phone_flow_.reset();
base::ListValue device_list;
for (const auto& external_device : reachable_phones) {
device_list.Append(ExternalDeviceInfoToDictionary(external_device));
}
web_ui()->CallJavascriptFunctionUnsafe(
"CryptAuthInterface.onGotReachableDevices", device_list);
}
void ProximityAuthWebUIHandler::GetLocalState(const base::ListValue* args) {
std::unique_ptr<base::Value> truncated_local_device_id =
GetTruncatedLocalDeviceId();
std::unique_ptr<base::DictionaryValue> enrollment_state =
GetEnrollmentStateDictionary();
std::unique_ptr<base::DictionaryValue> device_sync_state =
GetDeviceSyncStateDictionary();
std::unique_ptr<base::ListValue> synced_devices = GetRemoteDevicesList();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
// OnGetDebugInfo() will call NotifyGotLocalState() with the enrollment and
// device sync state info.
get_local_state_update_waiting_for_debug_info_ = true;
device_sync_client_->GetDebugInfo(
base::BindOnce(&ProximityAuthWebUIHandler::OnGetDebugInfo,
weak_ptr_factory_.GetWeakPtr()));
return;
}
PA_LOG(INFO) << "==== Got Local State ====\n"
<< "Device ID (truncated): " << *truncated_local_device_id
<< "\nEnrollment State: \n"
<< *enrollment_state << "Device Sync State: \n"
<< *device_sync_state << "Unlock Keys: \n"
<< *synced_devices;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onGotLocalState", *truncated_local_device_id,
*enrollment_state, *device_sync_state, *synced_devices);
NotifyGotLocalState(GetTruncatedLocalDeviceId(),
GetEnrollmentStateDictionary(),
GetDeviceSyncStateDictionary(), GetRemoteDevicesList());
}
std::unique_ptr<base::Value>
ProximityAuthWebUIHandler::GetTruncatedLocalDeviceId() {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
return std::make_unique<base::Value>(
device_sync_client_->GetLocalDeviceMetadata()
->GetTruncatedDeviceIdForLogs());
}
std::string local_public_key =
proximity_auth_client_->GetLocalDevicePublicKey();
......@@ -467,6 +501,8 @@ ProximityAuthWebUIHandler::GetTruncatedLocalDeviceId() {
std::unique_ptr<base::DictionaryValue>
ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
cryptauth::CryptAuthEnrollmentManager* enrollment_manager =
proximity_auth_client_->GetCryptAuthEnrollmentManager();
if (!enrollment_manager)
......@@ -481,6 +517,8 @@ ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() {
std::unique_ptr<base::DictionaryValue>
ProximityAuthWebUIHandler::GetDeviceSyncStateDictionary() {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (!device_manager)
......@@ -495,17 +533,22 @@ ProximityAuthWebUIHandler::GetDeviceSyncStateDictionary() {
std::unique_ptr<base::ListValue>
ProximityAuthWebUIHandler::GetRemoteDevicesList() {
std::unique_ptr<base::ListValue> unlock_keys(new base::ListValue());
std::unique_ptr<base::ListValue> devices_list_value(new base::ListValue());
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
for (const auto& remote_device : device_sync_client_->GetSyncedDevices())
devices_list_value->Append(RemoteDeviceToDictionary(remote_device));
} else {
cryptauth::CryptAuthDeviceManager* device_manager =
proximity_auth_client_->GetCryptAuthDeviceManager();
if (!device_manager)
return unlock_keys;
return devices_list_value;
for (const auto& unlock_key : device_manager->GetSyncedDevices()) {
unlock_keys->Append(ExternalDeviceInfoToDictionary(unlock_key));
for (const auto& unlock_key : device_manager->GetSyncedDevices())
devices_list_value->Append(ExternalDeviceInfoToDictionary(unlock_key));
}
return unlock_keys;
return devices_list_value;
}
void ProximityAuthWebUIHandler::OnRemoteDevicesLoaded(
......@@ -520,16 +563,35 @@ void ProximityAuthWebUIHandler::OnRemoteDevicesLoaded(
return;
}
selected_remote_device_ = cryptauth::RemoteDeviceRef(
std::make_shared<cryptauth::RemoteDevice>(remote_devices[0]));
StartRemoteDeviceLifeCycle(cryptauth::RemoteDeviceRef(
std::make_shared<cryptauth::RemoteDevice>(remote_devices[0])));
}
void ProximityAuthWebUIHandler::StartRemoteDeviceLifeCycle(
cryptauth::RemoteDeviceRef remote_device) {
selected_remote_device_ = remote_device;
life_cycle_.reset(new RemoteDeviceLifeCycleImpl(*selected_remote_device_));
life_cycle_->AddObserver(this);
life_cycle_->Start();
}
void ProximityAuthWebUIHandler::CleanUpRemoteDeviceLifeCycle() {
if (selected_remote_device_) {
PA_LOG(INFO) << "Cleaning up connection to "
<< selected_remote_device_->name();
}
life_cycle_.reset();
selected_remote_device_ = base::nullopt;
last_remote_status_update_.reset();
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onRemoteDevicesChanged", *GetRemoteDevicesList());
}
std::unique_ptr<base::DictionaryValue>
ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary(
const cryptauth::ExternalDeviceInfo& device_info) {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
std::string base64_public_key;
base::Base64UrlEncode(device_info.public_key(),
base::Base64UrlEncodePolicy::INCLUDE_PADDING,
......@@ -609,6 +671,66 @@ ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary(
return dictionary;
}
std::unique_ptr<base::DictionaryValue>
ProximityAuthWebUIHandler::RemoteDeviceToDictionary(
const cryptauth::RemoteDeviceRef& remote_device) {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
// Set the fields in the ExternalDeviceInfo proto.
std::unique_ptr<base::DictionaryValue> dictionary(
new base::DictionaryValue());
dictionary->SetString(kExternalDevicePublicKey, remote_device.GetDeviceId());
dictionary->SetString(kExternalDevicePublicKeyTruncated,
remote_device.GetTruncatedDeviceIdForLogs());
dictionary->SetString(kExternalDeviceFriendlyName, remote_device.name());
dictionary->SetBoolean(kExternalDeviceUnlockKey, remote_device.unlock_key());
dictionary->SetBoolean(kExternalDeviceMobileHotspot,
remote_device.supports_mobile_hotspot());
dictionary->SetString(kExternalDeviceConnectionStatus,
kExternalDeviceDisconnected);
// TODO(crbug.com/852836): Add kExternalDeviceIsArcPlusPlusEnrollment and
// kExternalDeviceIsPixelPhone values to the dictionary once RemoteDevice
// carries those relevant fields.
std::string selected_device_public_key;
if (selected_remote_device_)
selected_device_public_key = selected_remote_device_->public_key();
// If it's the selected remote device, combine the already-populated
// dictionary with corresponding local device data (e.g. connection status and
// remote status updates).
if (selected_device_public_key != remote_device.public_key())
return dictionary;
// Fill in the current Bluetooth connection status.
std::string connection_status = kExternalDeviceDisconnected;
if (life_cycle_ &&
life_cycle_->GetState() ==
RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) {
connection_status = kExternalDeviceConnected;
} else if (life_cycle_) {
connection_status = kExternalDeviceConnecting;
}
dictionary->SetString(kExternalDeviceConnectionStatus, connection_status);
// Fill the remote status dictionary.
if (last_remote_status_update_) {
std::unique_ptr<base::DictionaryValue> status_dictionary(
new base::DictionaryValue());
status_dictionary->SetInteger("userPresent",
last_remote_status_update_->user_presence);
status_dictionary->SetInteger(
"secureScreenLock",
last_remote_status_update_->secure_screen_lock_state);
status_dictionary->SetInteger(
"trustAgent", last_remote_status_update_->trust_agent_state);
dictionary->Set(kExternalDeviceRemoteState, std::move(status_dictionary));
}
return dictionary;
}
std::unique_ptr<base::DictionaryValue>
ProximityAuthWebUIHandler::IneligibleDeviceToDictionary(
const cryptauth::IneligibleDevice& ineligible_device) {
......@@ -624,18 +746,6 @@ ProximityAuthWebUIHandler::IneligibleDeviceToDictionary(
return device_dictionary;
}
void ProximityAuthWebUIHandler::CleanUpRemoteDeviceLifeCycle() {
if (selected_remote_device_) {
PA_LOG(INFO) << "Cleaning up connection to "
<< selected_remote_device_->name();
}
life_cycle_.reset();
selected_remote_device_ = base::nullopt;
last_remote_status_update_.reset();
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onRemoteDevicesChanged", *GetRemoteDevicesList());
}
void ProximityAuthWebUIHandler::OnLifeCycleStateChanged(
RemoteDeviceLifeCycle::State old_state,
RemoteDeviceLifeCycle::State new_state) {
......@@ -675,4 +785,142 @@ void ProximityAuthWebUIHandler::OnRemoteStatusUpdate(
"LocalStateInterface.onRemoteDevicesChanged", *synced_devices);
}
void ProximityAuthWebUIHandler::OnForceEnrollmentNow(bool success) {
PA_LOG(INFO) << "Force enrollment result: " << success;
}
void ProximityAuthWebUIHandler::OnForceSyncNow(bool success) {
PA_LOG(INFO) << "Force sync result: " << success;
}
void ProximityAuthWebUIHandler::OnSetSoftwareFeatureState(
const std::string public_key,
const base::Optional<std::string>& error_code) {
std::string device_id =
cryptauth::RemoteDeviceRef::GenerateDeviceId(public_key);
if (error_code) {
PA_LOG(ERROR) << "Failed to set SoftwareFeature state for device: "
<< device_id << ", error code: " << *error_code;
} else {
PA_LOG(INFO) << "Successfully set SoftwareFeature state for device: "
<< device_id;
}
}
void ProximityAuthWebUIHandler::OnFindEligibleDevices(
const base::Optional<std::string>& error_code,
cryptauth::RemoteDeviceRefList eligible_devices,
cryptauth::RemoteDeviceRefList ineligible_devices) {
if (error_code) {
PA_LOG(ERROR) << "Failed to find eligible devices: " << *error_code;
return;
}
base::ListValue eligible_devices_list_value;
for (const auto& device : eligible_devices) {
eligible_devices_list_value.Append(RemoteDeviceToDictionary(device));
}
base::ListValue ineligible_devices_list_value;
for (const auto& device : ineligible_devices) {
ineligible_devices_list_value.Append(RemoteDeviceToDictionary(device));
}
PA_LOG(INFO) << "Found " << eligible_devices_list_value.GetSize()
<< " eligible devices and "
<< ineligible_devices_list_value.GetSize()
<< " ineligible devices.";
web_ui()->CallJavascriptFunctionUnsafe(
"CryptAuthInterface.onGotEligibleDevices", eligible_devices_list_value,
ineligible_devices_list_value);
}
void ProximityAuthWebUIHandler::OnGetDebugInfo(
chromeos::device_sync::mojom::DebugInfoPtr debug_info_ptr) {
if (enrollment_update_waiting_for_debug_info_) {
enrollment_update_waiting_for_debug_info_ = false;
NotifyOnEnrollmentFinished(
true /* success */,
CreateSyncStateDictionary(
debug_info_ptr->last_enrollment_time.ToJsTime(),
debug_info_ptr->time_to_next_enrollment_attempt.InMillisecondsF(),
debug_info_ptr->is_recovering_from_enrollment_failure,
debug_info_ptr->is_enrollment_in_progress));
}
if (sync_update_waiting_for_debug_info_) {
sync_update_waiting_for_debug_info_ = false;
NotifyOnSyncFinished(
true /* was_sync_successful */, true /* changed */,
CreateSyncStateDictionary(
debug_info_ptr->last_sync_time.ToJsTime(),
debug_info_ptr->time_to_next_sync_attempt.InMillisecondsF(),
debug_info_ptr->is_recovering_from_sync_failure,
debug_info_ptr->is_sync_in_progress));
}
if (get_local_state_update_waiting_for_debug_info_) {
get_local_state_update_waiting_for_debug_info_ = false;
NotifyGotLocalState(
GetTruncatedLocalDeviceId(),
CreateSyncStateDictionary(
debug_info_ptr->last_enrollment_time.ToJsTime(),
debug_info_ptr->time_to_next_enrollment_attempt.InMillisecondsF(),
debug_info_ptr->is_recovering_from_enrollment_failure,
debug_info_ptr->is_enrollment_in_progress),
CreateSyncStateDictionary(
debug_info_ptr->last_sync_time.ToJsTime(),
debug_info_ptr->time_to_next_sync_attempt.InMillisecondsF(),
debug_info_ptr->is_recovering_from_sync_failure,
debug_info_ptr->is_sync_in_progress),
GetRemoteDevicesList());
}
}
void ProximityAuthWebUIHandler::NotifyOnEnrollmentFinished(
bool success,
std::unique_ptr<base::DictionaryValue> enrollment_state) {
PA_LOG(INFO) << "Enrollment attempt completed with success=" << success
<< ":\n"
<< *enrollment_state;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onEnrollmentStateChanged", *enrollment_state);
}
void ProximityAuthWebUIHandler::NotifyOnSyncFinished(
bool was_sync_successful,
bool changed,
std::unique_ptr<base::DictionaryValue> device_sync_state) {
PA_LOG(INFO) << "Device sync completed with result=" << was_sync_successful
<< ":\n"
<< *device_sync_state;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onDeviceSyncStateChanged", *device_sync_state);
if (changed) {
std::unique_ptr<base::ListValue> synced_devices = GetRemoteDevicesList();
PA_LOG(INFO) << "New unlock keys obtained after device sync:\n"
<< *synced_devices;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onRemoteDevicesChanged", *synced_devices);
}
}
void ProximityAuthWebUIHandler::NotifyGotLocalState(
std::unique_ptr<base::Value> truncated_local_device_id,
std::unique_ptr<base::DictionaryValue> enrollment_state,
std::unique_ptr<base::DictionaryValue> device_sync_state,
std::unique_ptr<base::ListValue> synced_devices) {
PA_LOG(INFO) << "==== Got Local State ====\n"
<< "Device ID (truncated): " << *truncated_local_device_id
<< "\nEnrollment State: \n"
<< *enrollment_state << "Device Sync State: \n"
<< *device_sync_state << "Synced devices: \n"
<< *synced_devices;
web_ui()->CallJavascriptFunctionUnsafe(
"LocalStateInterface.onGotLocalState", *truncated_local_device_id,
*enrollment_state, *device_sync_state, *synced_devices);
}
} // namespace proximity_auth
......@@ -13,11 +13,13 @@
#include "chromeos/components/proximity_auth/messenger_observer.h"
#include "chromeos/components/proximity_auth/proximity_auth_client.h"
#include "chromeos/components/proximity_auth/remote_device_life_cycle.h"
#include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
#include "components/cryptauth/connection_observer.h"
#include "components/cryptauth/cryptauth_client.h"
#include "components/cryptauth/cryptauth_device_manager.h"
#include "components/cryptauth/cryptauth_enrollment_manager.h"
#include "components/cryptauth/cryptauth_gcm_manager.h"
#include "components/cryptauth/remote_device_ref.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace base {
......@@ -31,7 +33,6 @@ class RemoteDeviceLoader;
namespace proximity_auth {
class ReachablePhoneFlow;
class RemoteDeviceLifeCycle;
struct RemoteStatusUpdate;
......@@ -41,12 +42,13 @@ class ProximityAuthWebUIHandler
public LogBuffer::Observer,
public cryptauth::CryptAuthEnrollmentManager::Observer,
public cryptauth::CryptAuthDeviceManager::Observer,
public chromeos::device_sync::DeviceSyncClient::Observer,
public RemoteDeviceLifeCycle::Observer,
public MessengerObserver {
public:
// |client_| is not owned and must outlive this instance.
explicit ProximityAuthWebUIHandler(
ProximityAuthClient* proximity_auth_client);
ProximityAuthWebUIHandler(
ProximityAuthClient* proximity_auth_client,
chromeos::device_sync::DeviceSyncClient* device_sync_client);
~ProximityAuthWebUIHandler() override;
// content::WebUIMessageHandler:
......@@ -67,13 +69,16 @@ class ProximityAuthWebUIHandler
cryptauth::CryptAuthDeviceManager::DeviceChangeResult
device_change_result) override;
// chromeos::device_sync::DeviceSyncClient::Observer:
void OnEnrollmentFinished() override;
void OnNewDevicesSynced() override;
// Message handler callbacks.
void OnWebContentsInitialized(const base::ListValue* args);
void GetLogMessages(const base::ListValue* args);
void ClearLogBuffer(const base::ListValue* args);
void ToggleUnlockKey(const base::ListValue* args);
void FindEligibleUnlockDevices(const base::ListValue* args);
void FindReachableDevices(const base::ListValue* args);
void GetLocalState(const base::ListValue* args);
void ForceEnrollment(const base::ListValue* args);
void ForceDeviceSync(const base::ListValue* args);
......@@ -84,35 +89,25 @@ class ProximityAuthWebUIHandler
void InitEnrollmentManager();
void InitDeviceManager();
// Called when a CryptAuth request fails.
void OnCryptAuthClientError(const std::string& error_message);
// Called when the toggleUnlock request succeeds.
void OnEasyUnlockToggled(const cryptauth::ToggleEasyUnlockResponse& response);
// Called when the findEligibleUnlockDevices request succeeds.
void OnFoundEligibleUnlockDevices(
const cryptauth::FindEligibleUnlockDevicesResponse& response);
// Callback when |reachable_phone_flow_| completes.
void OnReachablePhonesFound(
const std::vector<cryptauth::ExternalDeviceInfo>& reachable_phones);
// Called when the RemoteDevice is loaded so we can create a connection.
void OnRemoteDevicesLoaded(const cryptauth::RemoteDeviceList& remote_devices);
// Converts an ExternalDeviceInfo proto to a JSON dictionary used in
// JavaScript.
void StartRemoteDeviceLifeCycle(cryptauth::RemoteDeviceRef remote_device);
void CleanUpRemoteDeviceLifeCycle();
std::unique_ptr<base::DictionaryValue> ExternalDeviceInfoToDictionary(
const cryptauth::ExternalDeviceInfo& device_info);
// Converts an IneligibleDevice proto to a JSON dictionary used in JavaScript.
std::unique_ptr<base::DictionaryValue> RemoteDeviceToDictionary(
const cryptauth::RemoteDeviceRef& remote_device);
std::unique_ptr<base::DictionaryValue> IneligibleDeviceToDictionary(
const cryptauth::IneligibleDevice& ineligible_device);
// Cleans up the connection to the selected remote device.
void CleanUpRemoteDeviceLifeCycle();
// RemoteDeviceLifeCycle::Observer:
void OnLifeCycleStateChanged(RemoteDeviceLifeCycle::State old_state,
RemoteDeviceLifeCycle::State new_state) override;
......@@ -120,30 +115,46 @@ class ProximityAuthWebUIHandler
// MessengerObserver:
void OnRemoteStatusUpdate(const RemoteStatusUpdate& status_update) override;
// Returns the truncated device ID of the local device.
void OnForceEnrollmentNow(bool success);
void OnForceSyncNow(bool success);
void OnSetSoftwareFeatureState(const std::string public_key,
const base::Optional<std::string>& error_code);
void OnFindEligibleDevices(const base::Optional<std::string>&,
cryptauth::RemoteDeviceRefList eligible_devices,
cryptauth::RemoteDeviceRefList ineligible_devices);
void OnGetDebugInfo(
chromeos::device_sync::mojom::DebugInfoPtr debug_info_ptr);
void NotifyOnEnrollmentFinished(
bool success,
std::unique_ptr<base::DictionaryValue> enrollment_state);
void NotifyOnSyncFinished(
bool was_sync_successful,
bool changed,
std::unique_ptr<base::DictionaryValue> device_sync_state);
void NotifyGotLocalState(
std::unique_ptr<base::Value> truncated_local_device_id,
std::unique_ptr<base::DictionaryValue> enrollment_state,
std::unique_ptr<base::DictionaryValue> device_sync_state,
std::unique_ptr<base::ListValue> synced_devices);
std::unique_ptr<base::Value> GetTruncatedLocalDeviceId();
// Returns the current enrollment state that can be used as a JSON object.
// These two methods cannot be used if the chromeos::features::kMultiDeviceApi
// flag is enabled.
std::unique_ptr<base::DictionaryValue> GetEnrollmentStateDictionary();
// Returns the current device sync state that can be used as a JSON object.
std::unique_ptr<base::DictionaryValue> GetDeviceSyncStateDictionary();
// Returns the current remote devices that can be used as a JSON object.
std::unique_ptr<base::ListValue> GetRemoteDevicesList();
// The delegate used to fetch dependencies. Must outlive this instance.
ProximityAuthClient* proximity_auth_client_;
// Creates CryptAuth client instances to make API calls.
chromeos::device_sync::DeviceSyncClient* device_sync_client_;
std::unique_ptr<cryptauth::CryptAuthClientFactory> cryptauth_client_factory_;
// We only support one concurrent API call.
std::unique_ptr<cryptauth::CryptAuthClient> cryptauth_client_;
// The flow for getting a list of reachable phones.
std::unique_ptr<ReachablePhoneFlow> reachable_phone_flow_;
// True if we get a message from the loaded WebContents to know that it is
// initialized, and we can inject JavaScript.
bool web_contents_initialized_;
......@@ -155,6 +166,10 @@ class ProximityAuthWebUIHandler
std::unique_ptr<RemoteDeviceLifeCycle> life_cycle_;
std::unique_ptr<RemoteStatusUpdate> last_remote_status_update_;
bool enrollment_update_waiting_for_debug_info_ = false;
bool sync_update_waiting_for_debug_info_ = false;
bool get_local_state_update_waiting_for_debug_info_ = false;
base::WeakPtrFactory<ProximityAuthWebUIHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ProximityAuthWebUIHandler);
......
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