Commit 07d1445e authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Update MultiDeviceSetupClient.

This CL makes two previously-asynchronous API functions synchronous,
which drastically improves the ease of using this class.

The two functions are GetHostStatus() and GetFeatureStates(). With this
CL, the class now caches the most recent value received from the service
and returns in synchronously. If the service's values change, the
changes will be reflected in the client class.

This change unblocks several sub-tasks which use the client, including
setup code for EasyUnlock, Instant Tethering, and AWM.

Bug: 875980, 824568
Change-Id: I29430f614ce17206692b916d66b0cf57ec09f636
Reviewed-on: https://chromium-review.googlesource.com/1196030Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587654}
parent e95c2566
......@@ -422,17 +422,16 @@ void TetherService::OnReady() {
if (base::FeatureList::IsEnabled(
chromeos::features::kEnableUnifiedMultiDeviceSetup)) {
multidevice_setup_client_->GetHostStatus(base::BindOnce(
&TetherService::OnHostStatusChanged, weak_ptr_factory_.GetWeakPtr()));
OnHostStatusChanged(multidevice_setup_client_->GetHostStatus());
} else {
GetBluetoothAdapter();
}
}
void TetherService::OnHostStatusChanged(
chromeos::multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
host_status_ = host_status;
const chromeos::multidevice_setup::MultiDeviceSetupClient::
HostStatusWithDevice& host_status_with_device) {
host_status_ = host_status_with_device.first;
if (adapter_)
UpdateTetherTechnologyState();
......@@ -521,6 +520,11 @@ TetherService::GetTetherTechnologyState() {
}
void TetherService::GetBluetoothAdapter() {
if (adapter_ || is_adapter_being_fetched_)
return;
is_adapter_being_fetched_ = true;
// In the case that this is indirectly called from the constructor,
// GetAdapter() may call OnBluetoothAdapterFetched immediately which can cause
// problems with the Fake implementation since the class is not fully
......@@ -534,6 +538,8 @@ void TetherService::GetBluetoothAdapter() {
void TetherService::OnBluetoothAdapterFetched(
scoped_refptr<device::BluetoothAdapter> adapter) {
is_adapter_being_fetched_ = false;
if (shut_down_)
return;
......
......@@ -125,8 +125,8 @@ class TetherService
// chromeos::multidevice_setup::MultiDeviceSetupClient::Observer:
void OnHostStatusChanged(
chromeos::multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) override;
const chromeos::multidevice_setup::MultiDeviceSetupClient::
HostStatusWithDevice& host_status_with_device) override;
// Callback when the controlling pref changes.
void OnPrefsChanged();
......@@ -271,6 +271,8 @@ class TetherService
// was closed).
bool suspended_ = false;
bool is_adapter_being_fetched_ = false;
chromeos::multidevice_setup::mojom::HostStatus host_status_ =
chromeos::multidevice_setup::mojom::HostStatus::kNoEligibleHosts;
......
......@@ -453,6 +453,9 @@ class TetherServiceTest : public chromeos::NetworkStateTest {
}
void CreateTetherService() {
fake_multidevice_setup_client_->SetHostStatusWithDevice(
std::make_pair(initial_host_status_, initial_host_device_));
tether_service_ = base::WrapUnique(new TestTetherService(
profile_.get(), fake_power_manager_client_.get(),
fake_cryptauth_service_.get(), fake_device_sync_client_.get(),
......@@ -476,15 +479,9 @@ class TetherServiceTest : public chromeos::NetworkStateTest {
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(false /* expected_active */);
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
if (!fake_device_sync_client_->is_ready())
return;
if (base::FeatureList::IsEnabled(
chromeos::features::kEnableUnifiedMultiDeviceSetup)) {
fake_multidevice_setup_client_->InvokePendingGetHostStatusCallback(
initial_host_status_, initial_host_device_);
}
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi) &&
!fake_device_sync_client_->is_ready()) {
return;
}
// Allow the posted task to fetch the BluetoothAdapter to finish.
......@@ -738,9 +735,9 @@ TEST_F(TetherServiceTest,
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(false /* expected_active */);
fake_multidevice_setup_client_->NotifyHostStatusChanged(
fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
chromeos::multidevice_setup::mojom::HostStatus::kHostVerified,
test_devices_[0]);
test_devices_[0]));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED,
......@@ -768,9 +765,9 @@ TEST_F(TetherServiceTest, TestMultiDeviceSetupClientLosesVerifiedHost) {
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(true /* expected_active */);
fake_multidevice_setup_client_->NotifyHostStatusChanged(
fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
chromeos::multidevice_setup::mojom::HostStatus::kNoEligibleHosts,
base::nullopt);
base::nullopt));
EXPECT_EQ(
chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_UNAVAILABLE,
......@@ -963,9 +960,9 @@ TEST_F(
ASSERT_TRUE(tether_service);
fake_multidevice_setup_client_impl_factory_->fake_multidevice_setup_client()
->InvokePendingGetHostStatusCallback(
->SetHostStatusWithDevice(std::make_pair(
chromeos::multidevice_setup::mojom::HostStatus::kHostVerified,
test_devices_[0]);
test_devices_[0]));
base::RunLoop().RunUntilIdle();
tether_service->Shutdown();
......
......@@ -77,36 +77,21 @@ void MultideviceHandler::OnJavascriptDisallowed() {
}
void MultideviceHandler::OnHostStatusChanged(
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
last_host_status_update_ = std::make_pair(host_status, host_device);
AttemptUpdatePageContent();
const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice&
host_status_with_device) {
UpdatePageContent();
}
void MultideviceHandler::OnFeatureStatesChanged(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) {
last_feature_states_update_ = feature_states_map;
AttemptUpdatePageContent();
UpdatePageContent();
}
void MultideviceHandler::AttemptGetPageContentResponse(
const std::string& js_callback_id) {
void MultideviceHandler::UpdatePageContent() {
std::unique_ptr<base::DictionaryValue> page_content_dictionary =
GeneratePageContentDataDictionary();
if (!page_content_dictionary)
return;
ResolveJavascriptCallback(base::Value(js_callback_id),
*page_content_dictionary);
}
void MultideviceHandler::AttemptUpdatePageContent() {
std::unique_ptr<base::DictionaryValue> page_content_dictionary =
GeneratePageContentDataDictionary();
if (!page_content_dictionary)
return;
DCHECK(page_content_dictionary);
FireWebUIListener("settings.updateMultidevicePageContentData",
*page_content_dictionary);
}
......@@ -126,17 +111,11 @@ void MultideviceHandler::HandleGetPageContent(const base::ListValue* args) {
bool result = args->GetString(0, &callback_id);
DCHECK(result);
if (last_host_status_update_ && last_feature_states_update_) {
AttemptGetPageContentResponse(callback_id);
return;
}
std::unique_ptr<base::DictionaryValue> page_content_dictionary =
GeneratePageContentDataDictionary();
DCHECK(page_content_dictionary);
multidevice_setup_client_->GetHostStatus(
base::BindOnce(&MultideviceHandler::OnHostStatusFetched,
callback_weak_ptr_factory_.GetWeakPtr(), callback_id));
multidevice_setup_client_->GetFeatureStates(
base::BindOnce(&MultideviceHandler::OnFeatureStatesFetched,
callback_weak_ptr_factory_.GetWeakPtr(), callback_id));
ResolveJavascriptCallback(base::Value(callback_id), *page_content_dictionary);
}
void MultideviceHandler::HandleSetFeatureEnabledState(
......@@ -179,22 +158,6 @@ void MultideviceHandler::HandleRetryPendingHostSetup(
base::BindOnce(&OnRetrySetHostNowResult));
}
void MultideviceHandler::OnHostStatusFetched(
const std::string& js_callback_id,
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
last_host_status_update_ = std::make_pair(host_status, host_device);
AttemptGetPageContentResponse(js_callback_id);
}
void MultideviceHandler::OnFeatureStatesFetched(
const std::string& js_callback_id,
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) {
last_feature_states_update_ = feature_states_map;
AttemptGetPageContentResponse(js_callback_id);
}
void MultideviceHandler::OnSetFeatureStateEnabledResult(
const std::string& js_callback_id,
bool success) {
......@@ -203,39 +166,38 @@ void MultideviceHandler::OnSetFeatureStateEnabledResult(
std::unique_ptr<base::DictionaryValue>
MultideviceHandler::GeneratePageContentDataDictionary() {
// Cannot generate page contents without all required data.
if (!last_host_status_update_ || !last_feature_states_update_)
return nullptr;
auto page_content_dictionary = std::make_unique<base::DictionaryValue>();
multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice
host_status_with_device = multidevice_setup_client_->GetHostStatus();
multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap feature_states =
multidevice_setup_client_->GetFeatureStates();
page_content_dictionary->SetInteger(
kPageContentDataModeKey,
static_cast<int32_t>(last_host_status_update_->first));
static_cast<int32_t>(host_status_with_device.first));
page_content_dictionary->SetInteger(
kPageContentDataBetterTogetherStateKey,
static_cast<int32_t>(
(*last_feature_states_update_)
feature_states
[multidevice_setup::mojom::Feature::kBetterTogetherSuite]));
page_content_dictionary->SetInteger(
kPageContentDataInstantTetheringStateKey,
static_cast<int32_t>(
(*last_feature_states_update_)
feature_states
[multidevice_setup::mojom::Feature::kInstantTethering]));
page_content_dictionary->SetInteger(
kPageContentDataMessagesStateKey,
static_cast<int32_t>((*last_feature_states_update_)
[multidevice_setup::mojom::Feature::kMessages]));
static_cast<int32_t>(
feature_states[multidevice_setup::mojom::Feature::kMessages]));
page_content_dictionary->SetInteger(
kPageContentDataSmartLockStateKey,
static_cast<int32_t>(
(*last_feature_states_update_)
[multidevice_setup::mojom::Feature::kSmartLock]));
feature_states[multidevice_setup::mojom::Feature::kSmartLock]));
if (last_host_status_update_->second) {
page_content_dictionary->SetString(
kPageContentDataHostDeviceNameKey,
last_host_status_update_->second->name());
if (host_status_with_device.second) {
page_content_dictionary->SetString(kPageContentDataHostDeviceNameKey,
host_status_with_device.second->name());
}
return page_content_dictionary;
......
......@@ -37,19 +37,15 @@ class MultideviceHandler
// multidevice_setup::MultiDeviceSetupClient::Observer:
void OnHostStatusChanged(
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) override;
const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice&
host_status_with_device) override;
void OnFeatureStatesChanged(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) override;
// Attempts to send the most recent PageContentData dictionary to the WebUI
// page as a response to a getPageContent() request.
void AttemptGetPageContentResponse(const std::string& js_callback_id);
// Attempts to send the most recent PageContentData dictionary to the WebUI
// page as an update (e.g., not due to a getPageCOntent() request.
void AttemptUpdatePageContent();
// Sends the most recent PageContentData dictionary to the WebUI page as an
// update (e.g., not due to a getPageContent() request).
void UpdatePageContent();
void HandleShowMultiDeviceSetupDialog(const base::ListValue* args);
void HandleGetPageContent(const base::ListValue* args);
......@@ -57,14 +53,6 @@ class MultideviceHandler
void HandleRemoveHostDevice(const base::ListValue* args);
void HandleRetryPendingHostSetup(const base::ListValue* args);
void OnHostStatusFetched(
const std::string& js_callback_id,
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device);
void OnFeatureStatesFetched(
const std::string& js_callback_id,
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map);
void OnSetFeatureStateEnabledResult(const std::string& js_callback_id,
bool success);
......@@ -79,12 +67,6 @@ class MultideviceHandler
multidevice_setup::MultiDeviceSetupClient::Observer>
multidevice_setup_observer_;
base::Optional<std::pair<multidevice_setup::mojom::HostStatus,
base::Optional<cryptauth::RemoteDeviceRef>>>
last_host_status_update_;
base::Optional<multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap>
last_feature_states_update_;
// Used to cancel callbacks when JavaScript becomes disallowed.
base::WeakPtrFactory<MultideviceHandler> callback_weak_ptr_factory_;
......
......@@ -31,6 +31,19 @@ class TestMultideviceHandler : public MultideviceHandler {
using MultideviceHandler::set_web_ui;
};
multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap
GenerateDefaultFeatureStatesMap() {
return multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap{
{multidevice_setup::mojom::Feature::kBetterTogetherSuite,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kInstantTethering,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kMessages,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kSmartLock,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}};
}
void VerifyPageContentDict(
const base::Value* value,
multidevice_setup::mojom::HostStatus expected_host_status,
......@@ -102,39 +115,13 @@ class MultideviceHandlerTest : public testing::Test {
handler_->AllowJavascript();
}
void SetPageContent(
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device,
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) {
current_host_status_with_device_ = std::make_pair(host_status, host_device);
current_feature_states_map_ = feature_states_map;
}
void CallGetPageContentData(bool expected_to_request_data_from_device_sync) {
EXPECT_TRUE(current_host_status_with_device_);
void CallGetPageContentData() {
size_t call_data_count_before_call = test_web_ui()->call_data().size();
base::ListValue args;
args.AppendString("handlerFunctionName");
test_web_ui()->HandleReceivedMessage("getPageContentData", &args);
if (expected_to_request_data_from_device_sync) {
// The callback did not complete yet, so no call should have been made.
EXPECT_EQ(call_data_count_before_call, test_web_ui()->call_data().size());
// Invoke the host status callback.
fake_multidevice_setup_client()->InvokePendingGetHostStatusCallback(
current_host_status_with_device_->first /* host_status */,
current_host_status_with_device_->second /* host_device */);
// Invoke the feature states callback; this should trigger the event to be
// sent to JS.
fake_multidevice_setup_client()->InvokePendingGetFeatureStatesCallback(
*current_feature_states_map_);
}
EXPECT_EQ(call_data_count_before_call + 1u,
test_web_ui()->call_data().size());
......@@ -158,11 +145,10 @@ class MultideviceHandlerTest : public testing::Test {
void SimulateHostStatusUpdate(
multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
current_host_status_with_device_ = std::make_pair(host_status, host_device);
size_t call_data_count_before_call = test_web_ui()->call_data().size();
fake_multidevice_setup_client_->NotifyHostStatusChanged(host_status,
host_device);
fake_multidevice_setup_client_->SetHostStatusWithDevice(
std::make_pair(host_status, host_device));
EXPECT_EQ(call_data_count_before_call + 1u,
test_web_ui()->call_data().size());
......@@ -177,11 +163,9 @@ class MultideviceHandlerTest : public testing::Test {
void SimulateFeatureStatesUpdate(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) {
current_feature_states_map_ = feature_states_map;
size_t call_data_count_before_call = test_web_ui()->call_data().size();
fake_multidevice_setup_client_->NotifyFeatureStateChanged(
feature_states_map);
fake_multidevice_setup_client_->SetFeatureStates(feature_states_map);
EXPECT_EQ(call_data_count_before_call + 1u,
test_web_ui()->call_data().size());
......@@ -245,9 +229,10 @@ class MultideviceHandlerTest : public testing::Test {
private:
void VerifyPageContent(const base::Value* value) {
VerifyPageContentDict(value, current_host_status_with_device_->first,
current_host_status_with_device_->second,
*current_feature_states_map_);
VerifyPageContentDict(
value, fake_multidevice_setup_client_->GetHostStatus().first,
fake_multidevice_setup_client_->GetHostStatus().second,
fake_multidevice_setup_client_->GetFeatureStates());
}
std::unique_ptr<content::TestWebUI> test_web_ui_;
......@@ -255,33 +240,17 @@ class MultideviceHandlerTest : public testing::Test {
fake_multidevice_setup_client_;
std::unique_ptr<TestMultideviceHandler> handler_;
base::Optional<std::pair<multidevice_setup::mojom::HostStatus,
base::Optional<cryptauth::RemoteDeviceRef>>>
current_host_status_with_device_;
base::Optional<multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap>
current_feature_states_map_;
multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice
host_status_with_device_;
multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap
feature_states_map_;
DISALLOW_COPY_AND_ASSIGN(MultideviceHandlerTest);
};
TEST_F(MultideviceHandlerTest, PageContentData) {
static multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap
feature_states_map{
{multidevice_setup::mojom::Feature::kBetterTogetherSuite,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kInstantTethering,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kMessages,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost},
{multidevice_setup::mojom::Feature::kSmartLock,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}};
// multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap
// feature_states_map = GenerateUnverifiedFeatureStatesMap();
SetPageContent(multidevice_setup::mojom::HostStatus::kNoEligibleHosts,
base::nullopt /* host_device */, feature_states_map);
CallGetPageContentData(true /* expected_to_request_data_from_device_sync */);
CallGetPageContentData(false /* expected_to_request_data_from_device_sync */);
CallGetPageContentData();
CallGetPageContentData();
SimulateHostStatusUpdate(
multidevice_setup::mojom::HostStatus::kEligibleHostExistsButNoHostSet,
......@@ -295,6 +264,8 @@ TEST_F(MultideviceHandlerTest, PageContentData) {
SimulateHostStatusUpdate(multidevice_setup::mojom::HostStatus::kHostVerified,
test_device_);
multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap
feature_states_map = GenerateDefaultFeatureStatesMap();
feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] =
multidevice_setup::mojom::FeatureState::kEnabledByUser;
SimulateFeatureStatesUpdate(feature_states_map);
......
......@@ -8,7 +8,6 @@
#include "base/memory/ptr_util.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
#include "components/cryptauth/remote_device.h"
#include "components/cryptauth/remote_device_provider.h"
......@@ -57,19 +56,23 @@ TetherHostFetcherImpl::TetherHostFetcherImpl(
device_sync_client_(device_sync_client),
multidevice_setup_client_(multidevice_setup_client),
weak_ptr_factory_(this) {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->AddObserver(this);
else
multidevice_setup_client_->AddObserver(this);
} else {
remote_device_provider_->AddObserver(this);
}
CacheCurrentTetherHosts();
}
TetherHostFetcherImpl::~TetherHostFetcherImpl() {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
device_sync_client_->RemoveObserver(this);
else
multidevice_setup_client_->RemoveObserver(this);
} else {
remote_device_provider_->RemoveObserver(this);
}
}
bool TetherHostFetcherImpl::HasSyncedTetherHosts() {
......@@ -96,13 +99,36 @@ void TetherHostFetcherImpl::OnNewDevicesSynced() {
CacheCurrentTetherHosts();
}
void TetherHostFetcherImpl::OnHostStatusChanged(
const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice&
host_status_with_device) {
CacheCurrentTetherHosts();
}
void TetherHostFetcherImpl::OnFeatureStatesChanged(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) {
CacheCurrentTetherHosts();
}
void TetherHostFetcherImpl::CacheCurrentTetherHosts() {
cryptauth::RemoteDeviceRefList updated_list;
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
multidevice_setup_client_->GetHostStatus(
base::BindOnce(&TetherHostFetcherImpl::OnHostStatusFetched,
weak_ptr_factory_.GetWeakPtr()));
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi) &&
base::FeatureList::IsEnabled(
chromeos::features::kEnableUnifiedMultiDeviceSetup)) {
multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice
host_status_with_device = multidevice_setup_client_->GetHostStatus();
if (host_status_with_device.first ==
chromeos::multidevice_setup::mojom::HostStatus::kHostVerified) {
updated_list.push_back(*host_status_with_device.second);
}
if (updated_list == current_remote_device_list_)
return;
current_remote_device_list_.swap(updated_list);
NotifyTetherHostsUpdated();
return;
}
......@@ -128,24 +154,6 @@ void TetherHostFetcherImpl::CacheCurrentTetherHosts() {
NotifyTetherHostsUpdated();
}
void TetherHostFetcherImpl::OnHostStatusFetched(
chromeos::multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
cryptauth::RemoteDeviceRefList updated_list;
if (host_status ==
chromeos::multidevice_setup::mojom::HostStatus::kHostVerified) {
updated_list.push_back(*host_device);
}
if (updated_list == current_remote_device_list_)
return;
current_remote_device_list_.swap(updated_list);
NotifyTetherHostsUpdated();
}
} // namespace tether
} // namespace chromeos
......@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "chromeos/components/tether/tether_host_fetcher.h"
#include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "components/cryptauth/remote_device_provider.h"
#include "components/cryptauth/remote_device_ref.h"
......@@ -21,10 +22,6 @@ class RemoteDeviceProvider;
namespace chromeos {
namespace multidevice_setup {
class MultiDeviceSetupClient;
} // namespace multidevice_setup
namespace tether {
// Concrete TetherHostFetcher implementation. Despite the asynchronous function
......@@ -37,9 +34,11 @@ namespace tether {
// features::kMultiDeviceApi). Once Tether has fully migrated to DeviceSync Mojo
// Service, RemoteDeviceProvider will be ripped out of this class. See
// https://crbug.com/848956.
class TetherHostFetcherImpl : public TetherHostFetcher,
public cryptauth::RemoteDeviceProvider::Observer,
public device_sync::DeviceSyncClient::Observer {
class TetherHostFetcherImpl
: public TetherHostFetcher,
public cryptauth::RemoteDeviceProvider::Observer,
public device_sync::DeviceSyncClient::Observer,
public multidevice_setup::MultiDeviceSetupClient::Observer {
public:
class Factory {
public:
......@@ -76,6 +75,14 @@ class TetherHostFetcherImpl : public TetherHostFetcher,
// device_sync::DeviceSyncClient::Observer:
void OnNewDevicesSynced() override;
// multidevice_setup::MultiDeviceSetupClient::Observer:
void OnHostStatusChanged(
const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice&
host_status_with_device) override;
void OnFeatureStatesChanged(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) override;
protected:
// TODO(crbug.com/848956): Remove RemoteDeviceProvider once all clients have
// migrated to the DeviceSync Mojo API.
......@@ -86,9 +93,6 @@ class TetherHostFetcherImpl : public TetherHostFetcher,
private:
void CacheCurrentTetherHosts();
void OnHostStatusFetched(
chromeos::multidevice_setup::mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device);
cryptauth::RemoteDeviceProvider* remote_device_provider_;
device_sync::DeviceSyncClient* device_sync_client_;
......
......@@ -68,8 +68,12 @@ class TetherHostFetcherImplTest : public testing::Test {
tether_host_fetcher_.reset();
}
void SetMultiDeviceApiEnabled() {
scoped_feature_list_.InitAndEnableFeature(features::kMultiDeviceApi);
void SetMultiDeviceFeaturesEnabled() {
scoped_feature_list_.InitWithFeatures(
{chromeos::features::kMultiDeviceApi,
chromeos::features::
kEnableUnifiedMultiDeviceSetup} /* enabled_features */,
{} /* disabled_features */);
}
void InitializeTest() {
......@@ -85,28 +89,11 @@ class TetherHostFetcherImplTest : public testing::Test {
base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)
? fake_multidevice_setup_client_.get()
: nullptr);
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(test_remote_device_list_[0]);
test_observer_ = std::make_unique<TestObserver>();
tether_host_fetcher_->AddObserver(test_observer_.get());
}
void InvokeGetHostStatusCallback(
const base::Optional<cryptauth::RemoteDevice>& host_device) {
EXPECT_TRUE(
base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
if (!host_device) {
fake_multidevice_setup_client_->InvokePendingGetHostStatusCallback(
chromeos::multidevice_setup::mojom::HostStatus::kNoEligibleHosts,
base::nullopt);
} else {
fake_multidevice_setup_client_->InvokePendingGetHostStatusCallback(
chromeos::multidevice_setup::mojom::HostStatus::kHostVerified,
cryptauth::RemoteDeviceRef(
std::make_shared<cryptauth::RemoteDevice>(*host_device)));
}
}
void OnTetherHostListFetched(
const cryptauth::RemoteDeviceRefList& device_list) {
last_fetched_list_ = device_list;
......@@ -167,9 +154,28 @@ class TetherHostFetcherImplTest : public testing::Test {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
fake_device_sync_client_->set_synced_devices(
CreateTestRemoteDeviceRefList(devices));
} else {
fake_remote_device_provider_->set_synced_remote_devices(devices);
if (devices.empty()) {
fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
multidevice_setup::mojom::HostStatus::kNoEligibleHosts,
base::nullopt /* host_device */));
fake_multidevice_setup_client_->SetFeatureState(
multidevice_setup::mojom::Feature::kInstantTethering,
multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost);
return;
}
fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
multidevice_setup::mojom::HostStatus::kHostVerified,
cryptauth::RemoteDeviceRef(
std::make_shared<cryptauth::RemoteDevice>(devices[0]))));
fake_multidevice_setup_client_->SetFeatureState(
multidevice_setup::mojom::Feature::kInstantTethering,
multidevice_setup::mojom::FeatureState::kEnabledByUser);
return;
}
fake_remote_device_provider_->set_synced_remote_devices(devices);
}
void NotifyNewDevicesSynced() {
......@@ -188,32 +194,24 @@ class TetherHostFetcherImplTest : public testing::Test {
// Update the list of devices to be empty.
SetSyncedDevices(cryptauth::RemoteDeviceList());
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(base::nullopt);
EXPECT_FALSE(tether_host_fetcher_->HasSyncedTetherHosts());
EXPECT_EQ(1u, test_observer_->num_updates());
// Notify that the list has changed, even though it hasn't. There should be
// no update.
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(base::nullopt);
EXPECT_FALSE(tether_host_fetcher_->HasSyncedTetherHosts());
EXPECT_EQ(1u, test_observer_->num_updates());
// Update the list to include device 0 only.
SetSyncedDevices({test_remote_device_list_[0]});
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(test_remote_device_list_[0]);
EXPECT_TRUE(tether_host_fetcher_->HasSyncedTetherHosts());
EXPECT_EQ(2u, test_observer_->num_updates());
// Notify that the list has changed, even though it hasn't. There should be
// no update.
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(test_remote_device_list_[0]);
EXPECT_TRUE(tether_host_fetcher_->HasSyncedTetherHosts());
EXPECT_EQ(2u, test_observer_->num_updates());
}
......@@ -228,8 +226,6 @@ class TetherHostFetcherImplTest : public testing::Test {
// requested.
SetSyncedDevices(cryptauth::RemoteDeviceList{test_remote_device_list_[0]});
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(test_remote_device_list_[0]);
VerifySingleTetherHost(test_remote_device_ref_list_[0].GetDeviceId(),
test_remote_device_ref_list_[0]);
......@@ -242,16 +238,12 @@ class TetherHostFetcherImplTest : public testing::Test {
SetSyncedDevices(cryptauth::RemoteDeviceList{remote_device});
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(remote_device);
VerifySingleTetherHost(test_remote_device_ref_list_[0].GetDeviceId(),
base::nullopt);
// Update the list; now, there are no more devices.
SetSyncedDevices(cryptauth::RemoteDeviceList());
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
InvokeGetHostStatusCallback(base::nullopt);
VerifySingleTetherHost(test_remote_device_ref_list_[0].GetDeviceId(),
base::nullopt);
}
......@@ -276,7 +268,6 @@ class TetherHostFetcherImplTest : public testing::Test {
SetSyncedDevices(test_remote_device_list_);
NotifyNewDevicesSynced();
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
InvokeGetHostStatusCallback(test_remote_device_list_[0]);
VerifyAllTetherHosts(
CreateTestRemoteDeviceRefList({test_remote_device_list_[0]}));
} else {
......@@ -311,7 +302,7 @@ TEST_F(TetherHostFetcherImplTest, TestHasSyncedTetherHosts) {
TEST_F(TetherHostFetcherImplTest,
TestHasSyncedTetherHosts_MultideviceApiEnabled) {
SetMultiDeviceApiEnabled();
SetMultiDeviceFeaturesEnabled();
TestHasSyncedTetherHosts();
}
......@@ -321,7 +312,7 @@ TEST_F(TetherHostFetcherImplTest, TestFetchAllTetherHosts) {
TEST_F(TetherHostFetcherImplTest,
TestFetchAllTetherHosts_MultideviceApiEnabled) {
SetMultiDeviceApiEnabled();
SetMultiDeviceFeaturesEnabled();
TestFetchAllTetherHosts();
}
......@@ -330,7 +321,7 @@ TEST_F(TetherHostFetcherImplTest, TestSingleTetherHost) {
}
TEST_F(TetherHostFetcherImplTest, TestSingleTetherHost_MultideviceApiEnabled) {
SetMultiDeviceApiEnabled();
SetMultiDeviceFeaturesEnabled();
TestSingleTetherHost();
}
......@@ -342,7 +333,7 @@ TEST_F(TetherHostFetcherImplTest,
TEST_F(TetherHostFetcherImplTest,
TestSingleTetherHost_IdDoesNotCorrespondToDevice_MultideviceApiEnabled) {
SetMultiDeviceApiEnabled();
SetMultiDeviceFeaturesEnabled();
InitializeTest();
VerifySingleTetherHost("nonexistentId", base::nullopt);
}
......
......@@ -8,6 +8,7 @@
#include "base/test/scoped_task_environment.h"
#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/services/multidevice_setup/fake_account_status_change_delegate.h"
#include "chromeos/services/multidevice_setup/fake_feature_state_observer.h"
#include "chromeos/services/multidevice_setup/fake_host_status_observer.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_impl.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
......@@ -212,6 +213,13 @@ TEST_F(MultiDeviceSetupServiceTest, CallFunctionsBeforeInitialization) {
fake_host_status_observer->GenerateInterfacePtr());
multidevice_setup_ptr().FlushForTesting();
// AddFeatureStateObserver().
auto fake_feature_state_observer =
std::make_unique<FakeFeatureStateObserver>();
multidevice_setup_ptr()->AddFeatureStateObserver(
fake_feature_state_observer->GenerateInterfacePtr());
multidevice_setup_ptr().FlushForTesting();
// GetEligibleHostDevices().
multidevice_setup_ptr()->GetEligibleHostDevices(base::DoNothing());
multidevice_setup_ptr().FlushForTesting();
......@@ -241,7 +249,8 @@ TEST_F(MultiDeviceSetupServiceTest, CallFunctionsBeforeInitialization) {
// Finish initialization; all of the pending calls should have been forwarded.
FinishInitialization();
EXPECT_TRUE(fake_multidevice_setup()->delegate());
EXPECT_EQ(1u, fake_multidevice_setup()->host_status_observers().size());
EXPECT_TRUE(fake_multidevice_setup()->HasAtLeastOneHostStatusObserver());
EXPECT_TRUE(fake_multidevice_setup()->HasAtLeastOneFeatureStateObserver());
EXPECT_EQ(1u, fake_multidevice_setup()->get_eligible_hosts_args().size());
EXPECT_EQ(1u, fake_multidevice_setup()->get_host_args().size());
EXPECT_EQ(1u, fake_multidevice_setup()->set_feature_enabled_args().size());
......@@ -310,7 +319,15 @@ TEST_F(MultiDeviceSetupServiceTest, FinishInitializationFirst) {
multidevice_setup_ptr()->AddHostStatusObserver(
fake_host_status_observer->GenerateInterfacePtr());
multidevice_setup_ptr().FlushForTesting();
EXPECT_EQ(1u, fake_multidevice_setup()->host_status_observers().size());
EXPECT_TRUE(fake_multidevice_setup()->HasAtLeastOneHostStatusObserver());
// AddFeatureStateObserver().
auto fake_feature_state_observer =
std::make_unique<FakeFeatureStateObserver>();
multidevice_setup_ptr()->AddFeatureStateObserver(
fake_feature_state_observer->GenerateInterfacePtr());
multidevice_setup_ptr().FlushForTesting();
EXPECT_TRUE(fake_multidevice_setup()->HasAtLeastOneFeatureStateObserver());
// GetEligibleHostDevices().
multidevice_setup_ptr()->GetEligibleHostDevices(base::DoNothing());
......
......@@ -62,6 +62,37 @@ void FakeMultiDeviceSetup::BindHandle(mojo::ScopedMessagePipeHandle handle) {
std::move(handle)));
}
void FakeMultiDeviceSetup::FlushForTesting() {
host_status_observers_.FlushForTesting();
feature_state_observers_.FlushForTesting();
}
bool FakeMultiDeviceSetup::HasAtLeastOneHostStatusObserver() {
return !host_status_observers_.empty();
}
bool FakeMultiDeviceSetup::HasAtLeastOneFeatureStateObserver() {
return !feature_state_observers_.empty();
}
void FakeMultiDeviceSetup::NotifyHostStatusChanged(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDevice>& host_device) {
host_status_observers_.ForAllPtrs(
[&host_status, &host_device](mojom::HostStatusObserver* observer) {
observer->OnHostStatusChanged(host_status, host_device);
});
}
void FakeMultiDeviceSetup::NotifyFeatureStateChanged(
const base::flat_map<mojom::Feature, mojom::FeatureState>&
feature_states_map) {
feature_state_observers_.ForAllPtrs(
[&feature_states_map](mojom::FeatureStateObserver* observer) {
observer->OnFeatureStatesChanged(feature_states_map);
});
}
void FakeMultiDeviceSetup::SetAccountStatusChangeDelegate(
mojom::AccountStatusChangeDelegatePtr delegate) {
delegate_ = std::move(delegate);
......@@ -69,12 +100,12 @@ void FakeMultiDeviceSetup::SetAccountStatusChangeDelegate(
void FakeMultiDeviceSetup::AddHostStatusObserver(
mojom::HostStatusObserverPtr observer) {
host_status_observers_.push_back(std::move(observer));
host_status_observers_.AddPtr(std::move(observer));
}
void FakeMultiDeviceSetup::AddFeatureStateObserver(
mojom::FeatureStateObserverPtr observer) {
feature_state_observers_.push_back(std::move(observer));
feature_state_observers_.AddPtr(std::move(observer));
}
void FakeMultiDeviceSetup::GetEligibleHostDevices(
......
......@@ -12,6 +12,7 @@
#include "chromeos/services/multidevice_setup/multidevice_setup_base.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
namespace chromeos {
......@@ -24,16 +25,19 @@ class FakeMultiDeviceSetup : public MultiDeviceSetupBase {
~FakeMultiDeviceSetup() override;
void BindHandle(mojo::ScopedMessagePipeHandle handle);
void FlushForTesting();
mojom::AccountStatusChangeDelegatePtr& delegate() { return delegate_; }
bool HasAtLeastOneHostStatusObserver();
bool HasAtLeastOneFeatureStateObserver();
std::vector<mojom::HostStatusObserverPtr>& host_status_observers() {
return host_status_observers_;
}
void NotifyHostStatusChanged(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDevice>& host_device);
void NotifyFeatureStateChanged(
const base::flat_map<mojom::Feature, mojom::FeatureState>&
feature_states);
std::vector<mojom::FeatureStateObserverPtr>& feature_state_observers() {
return feature_state_observers_;
}
mojom::AccountStatusChangeDelegatePtr& delegate() { return delegate_; }
std::vector<GetEligibleHostDevicesCallback>& get_eligible_hosts_args() {
return get_eligible_hosts_args_;
......@@ -94,8 +98,9 @@ class FakeMultiDeviceSetup : public MultiDeviceSetupBase {
TriggerEventForDebuggingCallback callback) override;
mojom::AccountStatusChangeDelegatePtr delegate_;
std::vector<mojom::HostStatusObserverPtr> host_status_observers_;
std::vector<mojom::FeatureStateObserverPtr> feature_state_observers_;
mojo::InterfacePtrSet<mojom::HostStatusObserver> host_status_observers_;
mojo::InterfacePtrSet<mojom::FeatureStateObserver> feature_state_observers_;
std::vector<GetEligibleHostDevicesCallback> get_eligible_hosts_args_;
std::vector<std::tuple<std::string, std::string, SetHostDeviceCallback>>
set_host_args_;
......
......@@ -8,18 +8,46 @@ namespace chromeos {
namespace multidevice_setup {
FakeMultiDeviceSetupClient::FakeMultiDeviceSetupClient() = default;
FakeMultiDeviceSetupClient::FakeMultiDeviceSetupClient()
: host_status_with_device_(GenerateDefaultHostStatusWithDevice()),
feature_states_map_(GenerateDefaultFeatureStatesMap()) {}
FakeMultiDeviceSetupClient::~FakeMultiDeviceSetupClient() {
DCHECK(get_eligible_host_devices_callback_queue_.empty());
DCHECK(set_host_args_queue_.empty());
DCHECK(get_host_status_callback_queue_.empty());
DCHECK(set_feature_enabled_state_args_queue_.empty());
DCHECK(get_feature_states_args_queue_.empty());
DCHECK(retry_set_host_now_callback_queue_.empty());
DCHECK(trigger_event_for_debugging_type_and_callback_queue_.empty());
}
void FakeMultiDeviceSetupClient::SetHostStatusWithDevice(
const HostStatusWithDevice& host_status_with_device) {
if (host_status_with_device == host_status_with_device_)
return;
host_status_with_device_ = host_status_with_device;
MultiDeviceSetupClient::NotifyHostStatusChanged(host_status_with_device_);
}
void FakeMultiDeviceSetupClient::SetFeatureStates(
const FeatureStatesMap& feature_states_map) {
if (feature_states_map == feature_states_map_)
return;
feature_states_map_ = feature_states_map;
MultiDeviceSetupClient::NotifyFeatureStateChanged(feature_states_map_);
}
void FakeMultiDeviceSetupClient::SetFeatureState(
mojom::Feature feature,
mojom::FeatureState feature_state) {
if (feature_states_map_[feature] == feature_state)
return;
feature_states_map_[feature] = feature_state;
MultiDeviceSetupClient::NotifyFeatureStateChanged(feature_states_map_);
}
void FakeMultiDeviceSetupClient::InvokePendingGetEligibleHostDevicesCallback(
const cryptauth::RemoteDeviceRefList& eligible_devices) {
std::move(get_eligible_host_devices_callback_queue_.front())
......@@ -37,14 +65,6 @@ void FakeMultiDeviceSetupClient::InvokePendingSetHostDeviceCallback(
set_host_args_queue_.pop();
}
void FakeMultiDeviceSetupClient::InvokePendingGetHostStatusCallback(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
std::move(get_host_status_callback_queue_.front())
.Run(host_status, host_device);
get_host_status_callback_queue_.pop();
}
void FakeMultiDeviceSetupClient::InvokePendingSetFeatureEnabledStateCallback(
mojom::Feature expected_feature,
bool expected_enabled,
......@@ -58,12 +78,6 @@ void FakeMultiDeviceSetupClient::InvokePendingSetFeatureEnabledStateCallback(
set_feature_enabled_state_args_queue_.pop();
}
void FakeMultiDeviceSetupClient::InvokePendingGetFeatureStatesCallback(
const FeatureStatesMap& feature_states_map) {
std::move(get_feature_states_args_queue_.front()).Run(feature_states_map);
get_feature_states_args_queue_.pop();
}
void FakeMultiDeviceSetupClient::InvokePendingRetrySetHostNowCallback(
bool success) {
std::move(retry_set_host_now_callback_queue_.front()).Run(success);
......@@ -96,8 +110,9 @@ void FakeMultiDeviceSetupClient::RemoveHostDevice() {
num_remove_host_device_called_++;
}
void FakeMultiDeviceSetupClient::GetHostStatus(GetHostStatusCallback callback) {
get_host_status_callback_queue_.push(std::move(callback));
const MultiDeviceSetupClient::HostStatusWithDevice&
FakeMultiDeviceSetupClient::GetHostStatus() const {
return host_status_with_device_;
}
void FakeMultiDeviceSetupClient::SetFeatureEnabledState(
......@@ -109,9 +124,9 @@ void FakeMultiDeviceSetupClient::SetFeatureEnabledState(
std::move(callback));
}
void FakeMultiDeviceSetupClient::GetFeatureStates(
mojom::MultiDeviceSetup::GetFeatureStatesCallback callback) {
get_feature_states_args_queue_.emplace(std::move(callback));
const MultiDeviceSetupClient::FeatureStatesMap&
FakeMultiDeviceSetupClient::GetFeatureStates() const {
return feature_states_map_;
}
void FakeMultiDeviceSetupClient::RetrySetHostNow(
......
......@@ -27,22 +27,23 @@ class FakeMultiDeviceSetupClient : public MultiDeviceSetupClient {
FakeMultiDeviceSetupClient();
~FakeMultiDeviceSetupClient() override;
void SetHostStatusWithDevice(
const HostStatusWithDevice& host_status_with_device);
void SetFeatureStates(const FeatureStatesMap& feature_states_map);
void SetFeatureState(mojom::Feature feature,
mojom::FeatureState feature_state);
void InvokePendingGetEligibleHostDevicesCallback(
const cryptauth::RemoteDeviceRefList& eligible_devices);
void InvokePendingSetHostDeviceCallback(
const std::string& expected_device_id,
const std::string& expected_auth_token,
bool success);
void InvokePendingGetHostStatusCallback(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device);
void InvokePendingSetFeatureEnabledStateCallback(
mojom::Feature expected_feature,
bool expected_enabled,
const base::Optional<std::string>& expected_auth_token,
bool success);
void InvokePendingGetFeatureStatesCallback(
const FeatureStatesMap& feature_states_map);
void InvokePendingRetrySetHostNowCallback(bool success);
void InvokePendingTriggerEventForDebuggingCallback(
mojom::EventTypeForDebugging expected_type,
......@@ -52,25 +53,24 @@ class FakeMultiDeviceSetupClient : public MultiDeviceSetupClient {
return num_remove_host_device_called_;
}
using MultiDeviceSetupClient::NotifyHostStatusChanged;
using MultiDeviceSetupClient::NotifyFeatureStateChanged;
// MultiDeviceSetupClient:
const HostStatusWithDevice& GetHostStatus() const override;
const FeatureStatesMap& GetFeatureStates() const override;
private:
// MultiDeviceSetupClient:
void GetEligibleHostDevices(GetEligibleHostDevicesCallback callback) override;
void SetHostDevice(
const std::string& host_device_id,
const std::string& auth_token,
mojom::MultiDeviceSetup::SetHostDeviceCallback callback) override;
void RemoveHostDevice() override;
void GetHostStatus(GetHostStatusCallback callback) override;
void SetFeatureEnabledState(
mojom::Feature feature,
bool enabled,
const base::Optional<std::string>& auth_token,
mojom::MultiDeviceSetup::SetFeatureEnabledStateCallback callback)
override;
void GetFeatureStates(
mojom::MultiDeviceSetup::GetFeatureStatesCallback callback) override;
void RetrySetHostNow(
mojom::MultiDeviceSetup::RetrySetHostNowCallback callback) override;
void TriggerEventForDebugging(
......@@ -86,15 +86,12 @@ class FakeMultiDeviceSetupClient : public MultiDeviceSetupClient {
std::string,
mojom::MultiDeviceSetup::SetHostDeviceCallback>>
set_host_args_queue_;
std::queue<GetHostStatusCallback> get_host_status_callback_queue_;
std::queue<
std::tuple<mojom::Feature,
bool,
base::Optional<std::string>,
mojom::MultiDeviceSetup::SetFeatureEnabledStateCallback>>
set_feature_enabled_state_args_queue_;
std::queue<mojom::MultiDeviceSetup::GetFeatureStatesCallback>
get_feature_states_args_queue_;
std::queue<mojom::MultiDeviceSetup::RetrySetHostNowCallback>
retry_set_host_now_callback_queue_;
std::queue<
......@@ -102,6 +99,9 @@ class FakeMultiDeviceSetupClient : public MultiDeviceSetupClient {
mojom::MultiDeviceSetup::TriggerEventForDebuggingCallback>>
trigger_event_for_debugging_type_and_callback_queue_;
HostStatusWithDevice host_status_with_device_;
FeatureStatesMap feature_states_map_;
DISALLOW_COPY_AND_ASSIGN(FakeMultiDeviceSetupClient);
};
......
......@@ -8,6 +8,26 @@ namespace chromeos {
namespace multidevice_setup {
// static
MultiDeviceSetupClient::HostStatusWithDevice
MultiDeviceSetupClient::GenerateDefaultHostStatusWithDevice() {
return HostStatusWithDevice{mojom::HostStatus::kNoEligibleHosts,
base::nullopt /* host_device */};
}
// static
MultiDeviceSetupClient::FeatureStatesMap
MultiDeviceSetupClient::GenerateDefaultFeatureStatesMap() {
return FeatureStatesMap{{mojom::Feature::kBetterTogetherSuite,
mojom::FeatureState::kUnavailableNoVerifiedHost},
{mojom::Feature::kInstantTethering,
mojom::FeatureState::kUnavailableNoVerifiedHost},
{mojom::Feature::kMessages,
mojom::FeatureState::kUnavailableNoVerifiedHost},
{mojom::Feature::kSmartLock,
mojom::FeatureState::kUnavailableNoVerifiedHost}};
}
MultiDeviceSetupClient::MultiDeviceSetupClient() = default;
MultiDeviceSetupClient::~MultiDeviceSetupClient() = default;
......@@ -20,11 +40,15 @@ void MultiDeviceSetupClient::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
mojom::FeatureState MultiDeviceSetupClient::GetFeatureState(
mojom::Feature feature) const {
return GetFeatureStates().find(feature)->second;
}
void MultiDeviceSetupClient::NotifyHostStatusChanged(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {
const HostStatusWithDevice& host_status_with_device) {
for (auto& observer : observer_list_)
observer.OnHostStatusChanged(host_status, host_device);
observer.OnHostStatusChanged(host_status_with_device);
}
void MultiDeviceSetupClient::NotifyFeatureStateChanged(
......
......@@ -23,16 +23,18 @@ namespace multidevice_setup {
// Provides clients access to the MultiDeviceSetup API.
class MultiDeviceSetupClient {
public:
using HostStatusWithDevice =
std::pair<mojom::HostStatus, base::Optional<cryptauth::RemoteDeviceRef>>;
using FeatureStatesMap = base::flat_map<mojom::Feature, mojom::FeatureState>;
class Observer {
public:
// Called whenever the host status changes. If the host status is
// HostStatus::kNoEligibleHosts or
// HostStatus::kEligibleHostExistsButNoHostSet, |host_device| is null.
// HostStatus::kEligibleHostExistsButNoHostSet, the provided RemoteDeviceRef
// will be null.
virtual void OnHostStatusChanged(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device) {}
const HostStatusWithDevice& host_device_with_status) {}
// Called whenever the state of any feature has changed.
virtual void OnFeatureStatesChanged(
......@@ -44,9 +46,6 @@ class MultiDeviceSetupClient {
using GetEligibleHostDevicesCallback =
base::OnceCallback<void(const cryptauth::RemoteDeviceRefList&)>;
using GetHostStatusCallback = base::OnceCallback<void(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>&)>;
MultiDeviceSetupClient();
virtual ~MultiDeviceSetupClient();
......@@ -61,14 +60,14 @@ class MultiDeviceSetupClient {
const std::string& auth_token,
mojom::MultiDeviceSetup::SetHostDeviceCallback callback) = 0;
virtual void RemoveHostDevice() = 0;
virtual void GetHostStatus(GetHostStatusCallback callback) = 0;
virtual const HostStatusWithDevice& GetHostStatus() const = 0;
virtual void SetFeatureEnabledState(
mojom::Feature feature,
bool enabled,
const base::Optional<std::string>& auth_token,
mojom::MultiDeviceSetup::SetFeatureEnabledStateCallback callback) = 0;
virtual void GetFeatureStates(
mojom::MultiDeviceSetup::GetFeatureStatesCallback callback) = 0;
virtual const FeatureStatesMap& GetFeatureStates() const = 0;
mojom::FeatureState GetFeatureState(mojom::Feature feature) const;
virtual void RetrySetHostNow(
mojom::MultiDeviceSetup::RetrySetHostNowCallback callback) = 0;
virtual void TriggerEventForDebugging(
......@@ -76,12 +75,16 @@ class MultiDeviceSetupClient {
mojom::MultiDeviceSetup::TriggerEventForDebuggingCallback callback) = 0;
protected:
static HostStatusWithDevice GenerateDefaultHostStatusWithDevice();
static FeatureStatesMap GenerateDefaultFeatureStatesMap();
void NotifyHostStatusChanged(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device);
const HostStatusWithDevice& host_status_with_device);
void NotifyFeatureStateChanged(const FeatureStatesMap& feature_states_map);
private:
friend class MultiDeviceSetupClientImplTest;
base::ObserverList<Observer>::Unchecked observer_list_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupClient);
......
......@@ -50,12 +50,20 @@ MultiDeviceSetupClientImpl::MultiDeviceSetupClientImpl(
: host_status_observer_binding_(this),
feature_state_observer_binding_(this),
remote_device_cache_(
cryptauth::RemoteDeviceCache::Factory::Get()->BuildInstance()) {
cryptauth::RemoteDeviceCache::Factory::Get()->BuildInstance()),
host_status_with_device_(GenerateDefaultHostStatusWithDevice()),
feature_states_map_(GenerateDefaultFeatureStatesMap()) {
connector->BindInterface(mojom::kServiceName, &multidevice_setup_ptr_);
multidevice_setup_ptr_->AddHostStatusObserver(
GenerateHostStatusObserverInterfacePtr());
multidevice_setup_ptr_->AddFeatureStateObserver(
GenerateFeatureStatesObserverInterfacePtr());
multidevice_setup_ptr_->GetHostStatus(
base::BindOnce(&MultiDeviceSetupClientImpl::OnHostStatusChanged,
base::Unretained(this)));
multidevice_setup_ptr_->GetFeatureStates(
base::BindOnce(&MultiDeviceSetupClientImpl::OnFeatureStatesChanged,
base::Unretained(this)));
}
MultiDeviceSetupClientImpl::~MultiDeviceSetupClientImpl() = default;
......@@ -79,10 +87,9 @@ void MultiDeviceSetupClientImpl::RemoveHostDevice() {
multidevice_setup_ptr_->RemoveHostDevice();
}
void MultiDeviceSetupClientImpl::GetHostStatus(GetHostStatusCallback callback) {
multidevice_setup_ptr_->GetHostStatus(
base::BindOnce(&MultiDeviceSetupClientImpl::OnGetHostStatusCompleted,
base::Unretained(this), std::move(callback)));
const MultiDeviceSetupClient::HostStatusWithDevice&
MultiDeviceSetupClientImpl::GetHostStatus() const {
return host_status_with_device_;
}
void MultiDeviceSetupClientImpl::SetFeatureEnabledState(
......@@ -94,9 +101,9 @@ void MultiDeviceSetupClientImpl::SetFeatureEnabledState(
std::move(callback));
}
void MultiDeviceSetupClientImpl::GetFeatureStates(
mojom::MultiDeviceSetup::GetFeatureStatesCallback callback) {
multidevice_setup_ptr_->GetFeatureStates(std::move(callback));
const MultiDeviceSetupClient::FeatureStatesMap&
MultiDeviceSetupClientImpl::GetFeatureStates() const {
return feature_states_map_;
}
void MultiDeviceSetupClientImpl::RetrySetHostNow(
......@@ -115,16 +122,21 @@ void MultiDeviceSetupClientImpl::OnHostStatusChanged(
const base::Optional<cryptauth::RemoteDevice>& host_device) {
if (host_device) {
remote_device_cache_->SetRemoteDevices({*host_device});
NotifyHostStatusChanged(host_status, remote_device_cache_->GetRemoteDevice(
host_device->GetDeviceId()));
host_status_with_device_ = std::make_pair(
host_status,
remote_device_cache_->GetRemoteDevice(host_device->GetDeviceId()));
} else {
NotifyHostStatusChanged(host_status, base::nullopt);
host_status_with_device_ =
std::make_pair(host_status, base::nullopt /* host_device */);
}
NotifyHostStatusChanged(host_status_with_device_);
}
void MultiDeviceSetupClientImpl::OnFeatureStatesChanged(
const FeatureStatesMap& feature_states_map) {
NotifyFeatureStateChanged(feature_states_map);
feature_states_map_ = feature_states_map;
NotifyFeatureStateChanged(feature_states_map_);
}
void MultiDeviceSetupClientImpl::OnGetEligibleHostDevicesCompleted(
......@@ -143,19 +155,6 @@ void MultiDeviceSetupClientImpl::OnGetEligibleHostDevicesCompleted(
std::move(callback).Run(eligible_host_device_refs);
}
void MultiDeviceSetupClientImpl::OnGetHostStatusCompleted(
GetHostStatusCallback callback,
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDevice>& host_device) {
if (host_device) {
remote_device_cache_->SetRemoteDevices({*host_device});
std::move(callback).Run(host_status, *remote_device_cache_->GetRemoteDevice(
host_device->GetDeviceId()));
} else {
std::move(callback).Run(host_status, base::nullopt);
}
}
mojom::HostStatusObserverPtr
MultiDeviceSetupClientImpl::GenerateHostStatusObserverInterfacePtr() {
mojom::HostStatusObserverPtr interface_ptr;
......
......@@ -52,15 +52,14 @@ class MultiDeviceSetupClientImpl : public MultiDeviceSetupClient,
const std::string& auth_token,
mojom::MultiDeviceSetup::SetHostDeviceCallback callback) override;
void RemoveHostDevice() override;
void GetHostStatus(GetHostStatusCallback callback) override;
const HostStatusWithDevice& GetHostStatus() const override;
void SetFeatureEnabledState(
mojom::Feature feature,
bool enabled,
const base::Optional<std::string>& auth_token,
mojom::MultiDeviceSetup::SetFeatureEnabledStateCallback callback)
override;
void GetFeatureStates(
mojom::MultiDeviceSetup::GetFeatureStatesCallback callback) override;
const FeatureStatesMap& GetFeatureStates() const override;
void RetrySetHostNow(
mojom::MultiDeviceSetup::RetrySetHostNowCallback callback) override;
void TriggerEventForDebugging(
......@@ -85,10 +84,6 @@ class MultiDeviceSetupClientImpl : public MultiDeviceSetupClient,
void OnGetEligibleHostDevicesCompleted(
GetEligibleHostDevicesCallback callback,
const cryptauth::RemoteDeviceList& eligible_host_devices);
void OnGetHostStatusCompleted(
GetHostStatusCallback callback,
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDevice>& host_device);
mojom::HostStatusObserverPtr GenerateHostStatusObserverInterfacePtr();
mojom::FeatureStateObserverPtr GenerateFeatureStatesObserverInterfacePtr();
......@@ -100,6 +95,9 @@ class MultiDeviceSetupClientImpl : public MultiDeviceSetupClient,
mojo::Binding<mojom::FeatureStateObserver> feature_state_observer_binding_;
std::unique_ptr<cryptauth::RemoteDeviceCache> remote_device_cache_;
HostStatusWithDevice host_status_with_device_;
FeatureStatesMap feature_states_map_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupClientImpl);
};
......
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