Commit f2c92e29 authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Wrap ARC_PACKAGE in pseudo-USS codepath

The sync datatype is the last leftover that hasn't been wrapped in the
USS architecture, and could end up in the critical path to future
dismantling efforts.

The new controller has been simplified by instead introducing the
notion of model-readiness in SyncableService, which the USS codepath
honors. This makes the new controller a lot simpler, and is aligned
with our plans to avoid the notion of model readiness in controllers,
and narrow down the scope of DataTypeController::ReadyForStart() to
non-transient business logic (i.e. is a datatype allowed to start).

Sync integration tests are now parameterized to exercise both codepaths
in case the feature toggle must be used in the future as kill switch.

Bug: 870624,939329
Change-Id: I9d415eba7bd53f0fd9cf7bbfa00db98b7e916e1c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1507657Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638630}
parent 60b52be5
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
#include "chrome/browser/chromeos/printing/synced_printers_manager.h" #include "chrome/browser/chromeos/printing/synced_printers_manager.h"
#include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h" #include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h"
#include "chrome/browser/ui/app_list/arc/arc_package_sync_data_type_controller.h" #include "chrome/browser/ui/app_list/arc/arc_package_sync_data_type_controller.h"
#include "chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h"
#include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h" #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
#include "components/arc/arc_util.h" #include "components/arc/arc_util.h"
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
...@@ -448,8 +449,16 @@ ChromeSyncClient::CreateDataTypeControllers(syncer::SyncService* sync_service) { ...@@ -448,8 +449,16 @@ ChromeSyncClient::CreateDataTypeControllers(syncer::SyncService* sync_service) {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (arc::IsArcAllowedForProfile(profile_) && if (arc::IsArcAllowedForProfile(profile_) &&
!arc::IsArcAppSyncFlowDisabled()) { !arc::IsArcAppSyncFlowDisabled()) {
controllers.push_back(std::make_unique<ArcPackageSyncDataTypeController>( if (base::FeatureList::IsEnabled(switches::kSyncPseudoUSSArcPackage)) {
syncer::ARC_PACKAGE, dump_stack, sync_service, this, profile_)); controllers.push_back(std::make_unique<ArcPackageSyncModelTypeController>(
GetModelTypeStoreService()->GetStoreFactory(),
base::BindOnce(&ChromeSyncClient::GetSyncableServiceForType,
base::Unretained(this), syncer::ARC_PACKAGE),
dump_stack, sync_service, profile_));
} else {
controllers.push_back(std::make_unique<ArcPackageSyncDataTypeController>(
syncer::ARC_PACKAGE, dump_stack, sync_service, this, profile_));
}
} }
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
......
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/test/integration/feature_toggler.h"
#include "chrome/browser/sync/test/integration/sync_arc_package_helper.h" #include "chrome/browser/sync/test/integration/sync_arc_package_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h" #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
#include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h" #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
#include "components/sync/driver/sync_driver_switches.h"
namespace arc { namespace arc {
...@@ -19,9 +21,11 @@ bool AllProfilesHaveSameArcPackageDetails() { ...@@ -19,9 +21,11 @@ bool AllProfilesHaveSameArcPackageDetails() {
} // namespace } // namespace
class SingleClientArcPackageSyncTest : public SyncTest { class SingleClientArcPackageSyncTest : public FeatureToggler, public SyncTest {
public: public:
SingleClientArcPackageSyncTest() : SyncTest(SINGLE_CLIENT) {} SingleClientArcPackageSyncTest()
: FeatureToggler(switches::kSyncPseudoUSSArcPackage),
SyncTest(SINGLE_CLIENT) {}
~SingleClientArcPackageSyncTest() override {} ~SingleClientArcPackageSyncTest() override {}
...@@ -29,13 +33,13 @@ class SingleClientArcPackageSyncTest : public SyncTest { ...@@ -29,13 +33,13 @@ class SingleClientArcPackageSyncTest : public SyncTest {
DISALLOW_COPY_AND_ASSIGN(SingleClientArcPackageSyncTest); DISALLOW_COPY_AND_ASSIGN(SingleClientArcPackageSyncTest);
}; };
IN_PROC_BROWSER_TEST_F(SingleClientArcPackageSyncTest, ArcPackageEmpty) { IN_PROC_BROWSER_TEST_P(SingleClientArcPackageSyncTest, ArcPackageEmpty) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
} }
IN_PROC_BROWSER_TEST_F(SingleClientArcPackageSyncTest, IN_PROC_BROWSER_TEST_P(SingleClientArcPackageSyncTest,
ArcPackageInstallSomePackages) { ArcPackageInstallSomePackages) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
...@@ -49,4 +53,8 @@ IN_PROC_BROWSER_TEST_F(SingleClientArcPackageSyncTest, ...@@ -49,4 +53,8 @@ IN_PROC_BROWSER_TEST_F(SingleClientArcPackageSyncTest,
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
} }
INSTANTIATE_TEST_SUITE_P(USS,
SingleClientArcPackageSyncTest,
::testing::Values(false, true));
} // namespace arc } // namespace arc
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/test/integration/feature_toggler.h"
#include "chrome/browser/sync/test/integration/sync_arc_package_helper.h" #include "chrome/browser/sync/test/integration/sync_arc_package_helper.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/sync/test/integration/sync_test.h"
#include "components/sync/driver/sync_driver_switches.h"
namespace arc { namespace arc {
...@@ -18,9 +20,13 @@ bool AllProfilesHaveSameArcPackageDetails() { ...@@ -18,9 +20,13 @@ bool AllProfilesHaveSameArcPackageDetails() {
} // namespace } // namespace
class TwoClientArcPackageSyncTest : public SyncTest { class TwoClientArcPackageSyncTest : public FeatureToggler, public SyncTest {
public: public:
TwoClientArcPackageSyncTest() : SyncTest(TWO_CLIENT) { DisableVerifier(); } TwoClientArcPackageSyncTest()
: FeatureToggler(switches::kSyncPseudoUSSArcPackage),
SyncTest(TWO_CLIENT) {
DisableVerifier();
}
~TwoClientArcPackageSyncTest() override {} ~TwoClientArcPackageSyncTest() override {}
...@@ -28,13 +34,13 @@ class TwoClientArcPackageSyncTest : public SyncTest { ...@@ -28,13 +34,13 @@ class TwoClientArcPackageSyncTest : public SyncTest {
DISALLOW_COPY_AND_ASSIGN(TwoClientArcPackageSyncTest); DISALLOW_COPY_AND_ASSIGN(TwoClientArcPackageSyncTest);
}; };
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, StartWithNoPackages) { IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest, StartWithNoPackages) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
} }
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, StartWithSamePackages) { IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest, StartWithSamePackages) {
ASSERT_TRUE(SetupClients()); ASSERT_TRUE(SetupClients());
constexpr size_t kNumPackages = 5; constexpr size_t kNumPackages = 5;
...@@ -50,7 +56,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, StartWithSamePackages) { ...@@ -50,7 +56,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, StartWithSamePackages) {
// In this test, packages are installed before sync started. Client1 will have // In this test, packages are installed before sync started. Client1 will have
// package 0 to 4 installed while client2 has no package installed. // package 0 to 4 installed while client2 has no package installed.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest,
OneClientHasPackagesAnotherHasNone) { OneClientHasPackagesAnotherHasNone) {
ASSERT_TRUE(SetupClients()); ASSERT_TRUE(SetupClients());
...@@ -68,7 +74,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, ...@@ -68,7 +74,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest,
// In this test, packages are installed before sync started. Client1 will have // In this test, packages are installed before sync started. Client1 will have
// package 0 to 9 installed and client2 will have package 0 to 4 installed. // package 0 to 9 installed and client2 will have package 0 to 4 installed.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest,
OneClientHasPackagesAnotherHasSubSet) { OneClientHasPackagesAnotherHasSubSet) {
ASSERT_TRUE(SetupClients()); ASSERT_TRUE(SetupClients());
...@@ -91,7 +97,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, ...@@ -91,7 +97,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest,
// In this test, packages are installed before sync started. Client1 will have // In this test, packages are installed before sync started. Client1 will have
// package 0 to 4 installed and client2 will have package 1 to 5 installed. // package 0 to 4 installed and client2 will have package 1 to 5 installed.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest,
StartWithDifferentPackages) { StartWithDifferentPackages) {
ASSERT_TRUE(SetupClients()); ASSERT_TRUE(SetupClients());
...@@ -111,7 +117,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, ...@@ -111,7 +117,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest,
} }
// Tests package installaton after sync started. // Tests package installaton after sync started.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Install) { IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest, Install) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
...@@ -122,7 +128,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Install) { ...@@ -122,7 +128,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Install) {
// In this test, packages are installed after sync started. Client1 installs // In this test, packages are installed after sync started. Client1 installs
// package 0 to 4 and client2 installs package 3 to 7. // package 0 to 4 and client2 installs package 3 to 7.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, InstallDifferent) { IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest, InstallDifferent) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
...@@ -140,7 +146,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, InstallDifferent) { ...@@ -140,7 +146,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, InstallDifferent) {
// Installs package from one client and uninstalls from another after sync // Installs package from one client and uninstalls from another after sync
// started. // started.
IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Uninstall) { IN_PROC_BROWSER_TEST_P(TwoClientArcPackageSyncTest, Uninstall) {
ASSERT_TRUE(SetupSync()); ASSERT_TRUE(SetupSync());
ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails()); ASSERT_TRUE(AllProfilesHaveSameArcPackageDetails());
...@@ -154,4 +160,8 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Uninstall) { ...@@ -154,4 +160,8 @@ IN_PROC_BROWSER_TEST_F(TwoClientArcPackageSyncTest, Uninstall) {
EXPECT_TRUE(AllProfilesHaveSameArcPackageDetails()); EXPECT_TRUE(AllProfilesHaveSameArcPackageDetails());
} }
INSTANTIATE_TEST_SUITE_P(USS,
TwoClientArcPackageSyncTest,
::testing::Values(false, true));
} // namespace arc } // namespace arc
...@@ -3265,6 +3265,8 @@ jumbo_split_static_library("ui") { ...@@ -3265,6 +3265,8 @@ jumbo_split_static_library("ui") {
"app_list/arc/arc_fast_app_reinstall_starter.h", "app_list/arc/arc_fast_app_reinstall_starter.h",
"app_list/arc/arc_package_sync_data_type_controller.cc", "app_list/arc/arc_package_sync_data_type_controller.cc",
"app_list/arc/arc_package_sync_data_type_controller.h", "app_list/arc/arc_package_sync_data_type_controller.h",
"app_list/arc/arc_package_sync_model_type_controller.cc",
"app_list/arc/arc_package_sync_model_type_controller.h",
"app_list/arc/arc_package_syncable_service.cc", "app_list/arc/arc_package_syncable_service.cc",
"app_list/arc/arc_package_syncable_service.h", "app_list/arc/arc_package_syncable_service.h",
"app_list/arc/arc_package_syncable_service_factory.cc", "app_list/arc/arc_package_syncable_service_factory.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h"
#include <utility>
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/profiles/profile.h"
#include "components/sync/driver/sync_service.h"
ArcPackageSyncModelTypeController::ArcPackageSyncModelTypeController(
syncer::OnceModelTypeStoreFactory store_factory,
SyncableServiceProvider syncable_service_provider,
const base::RepeatingClosure& dump_stack,
syncer::SyncService* sync_service,
Profile* profile)
: syncer::SyncableServiceBasedModelTypeController(
syncer::ARC_PACKAGE,
std::move(store_factory),
std::move(syncable_service_provider),
dump_stack),
sync_service_(sync_service),
profile_(profile) {
arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
if (arc_session_manager) {
arc_session_manager->AddObserver(this);
}
}
ArcPackageSyncModelTypeController::~ArcPackageSyncModelTypeController() {
arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
if (arc_session_manager) {
arc_session_manager->RemoveObserver(this);
}
}
bool ArcPackageSyncModelTypeController::ReadyForStart() const {
DCHECK(CalledOnValidThread());
return arc::IsArcPlayStoreEnabledForProfile(profile_);
}
void ArcPackageSyncModelTypeController::OnArcPlayStoreEnabledChanged(
bool enabled) {
DCHECK(CalledOnValidThread());
sync_service_->ReadyForStartChanged(type());
}
void ArcPackageSyncModelTypeController::OnArcInitialStart() {
DCHECK(CalledOnValidThread());
sync_service_->ReadyForStartChanged(type());
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNC_MODEL_TYPE_CONTROLLER_H_
#define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNC_MODEL_TYPE_CONTROLLER_H_
#include "base/macros.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "components/sync/driver/syncable_service_based_model_type_controller.h"
class Profile;
namespace syncer {
class SyncService;
} // namespace syncer
// A DataTypeController for arc package sync datatypes, which enables or
// disables these types based on whether ArcAppInstance is ready.
class ArcPackageSyncModelTypeController
: public syncer::SyncableServiceBasedModelTypeController,
public arc::ArcSessionManager::Observer {
public:
// |dump_stack| is called when an unrecoverable error occurs.
ArcPackageSyncModelTypeController(
syncer::OnceModelTypeStoreFactory store_factory,
SyncableServiceProvider syncable_service_provider,
const base::RepeatingClosure& dump_stack,
syncer::SyncService* sync_service,
Profile* profile);
~ArcPackageSyncModelTypeController() override;
// DataTypeController overrides.
bool ReadyForStart() const override;
// ArcSessionManager::Observer:
void OnArcPlayStoreEnabledChanged(bool enabled) override;
void OnArcInitialStart() override;
private:
syncer::SyncService* const sync_service_;
Profile* const profile_;
DISALLOW_COPY_AND_ASSIGN(ArcPackageSyncModelTypeController);
};
#endif // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNC_MODEL_TYPE_CONTROLLER_H_
...@@ -120,6 +120,17 @@ bool ArcPackageSyncableService::IsPackageSyncing( ...@@ -120,6 +120,17 @@ bool ArcPackageSyncableService::IsPackageSyncing(
pending_install_items_.end(); pending_install_items_.end();
} }
void ArcPackageSyncableService::WaitUntilReadyToSync(base::OnceClosure done) {
if (prefs_->package_list_initial_refreshed()) {
std::move(done).Run();
return;
}
// Wait until the initial list is loaded, handled in
// OnPackageListInitialRefreshed().
wait_until_ready_to_sync_cb_ = std::move(done);
}
syncer::SyncMergeResult ArcPackageSyncableService::MergeDataAndStartSyncing( syncer::SyncMergeResult ArcPackageSyncableService::MergeDataAndStartSyncing(
syncer::ModelType type, syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data, const syncer::SyncDataList& initial_sync_data,
...@@ -322,6 +333,11 @@ void ArcPackageSyncableService::OnPackageModified( ...@@ -322,6 +333,11 @@ void ArcPackageSyncableService::OnPackageModified(
SendSyncChange(package_info, SyncChange::ACTION_UPDATE); SendSyncChange(package_info, SyncChange::ACTION_UPDATE);
} }
void ArcPackageSyncableService::OnPackageListInitialRefreshed() {
if (wait_until_ready_to_sync_cb_)
std::move(wait_until_ready_to_sync_cb_).Run();
}
void ArcPackageSyncableService::SendSyncChange( void ArcPackageSyncableService::SendSyncChange(
const mojom::ArcPackageInfo& package_info, const mojom::ArcPackageInfo& package_info,
const syncer::SyncChange::SyncChangeType& sync_change_type) { const syncer::SyncChange::SyncChangeType& sync_change_type) {
......
...@@ -55,6 +55,7 @@ class ArcPackageSyncableService : public syncer::SyncableService, ...@@ -55,6 +55,7 @@ class ArcPackageSyncableService : public syncer::SyncableService,
bool IsPackageSyncing(const std::string& package_name) const; bool IsPackageSyncing(const std::string& package_name) const;
// syncer::SyncableService: // syncer::SyncableService:
void WaitUntilReadyToSync(base::OnceClosure done) override;
syncer::SyncMergeResult MergeDataAndStartSyncing( syncer::SyncMergeResult MergeDataAndStartSyncing(
syncer::ModelType type, syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data, const syncer::SyncDataList& initial_sync_data,
...@@ -79,6 +80,7 @@ class ArcPackageSyncableService : public syncer::SyncableService, ...@@ -79,6 +80,7 @@ class ArcPackageSyncableService : public syncer::SyncableService,
void OnPackageModified(const mojom::ArcPackageInfo& package_info) override; void OnPackageModified(const mojom::ArcPackageInfo& package_info) override;
void OnPackageRemoved(const std::string& package_name, void OnPackageRemoved(const std::string& package_name,
bool uninstalled) override; bool uninstalled) override;
void OnPackageListInitialRefreshed() override;
// Sends adds/updates sync change to sync server. // Sends adds/updates sync change to sync server.
void SendSyncChange( void SendSyncChange(
...@@ -105,6 +107,7 @@ class ArcPackageSyncableService : public syncer::SyncableService, ...@@ -105,6 +107,7 @@ class ArcPackageSyncableService : public syncer::SyncableService,
bool ShouldSyncPackage(const std::string& package_name) const; bool ShouldSyncPackage(const std::string& package_name) const;
Profile* const profile_; Profile* const profile_;
base::OnceClosure wait_until_ready_to_sync_cb_;
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_; std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler_; std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler_;
......
...@@ -100,17 +100,19 @@ void DataTypeManagerImpl::ReenableType(ModelType type) { ...@@ -100,17 +100,19 @@ void DataTypeManagerImpl::ReenableType(ModelType type) {
} }
void DataTypeManagerImpl::ReadyForStartChanged(ModelType type) { void DataTypeManagerImpl::ReadyForStartChanged(ModelType type) {
const auto& dtc_iter = controllers_->find(type); if (!UpdateUnreadyTypeError(type)) {
if (dtc_iter == controllers_->end()) // Nothing changed.
return; return;
}
if (dtc_iter->second->ReadyForStart()) { if (data_type_status_table_.GetUnreadyErrorTypes().Has(type)) {
ForceReconfiguration();
} else {
model_association_manager_.StopDatatype( model_association_manager_.StopDatatype(
type, DISABLE_SYNC, type, DISABLE_SYNC,
SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR, SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
"Data type is unready.", type)); "Data type is unready.", type));
} else if (last_requested_types_.Has(type)) {
// Only reconfigure if the type is both ready and desired.
ForceReconfiguration();
} }
} }
...@@ -347,28 +349,36 @@ TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes( ...@@ -347,28 +349,36 @@ TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
void DataTypeManagerImpl::UpdateUnreadyTypeErrors( void DataTypeManagerImpl::UpdateUnreadyTypeErrors(
const ModelTypeSet& desired_types) { const ModelTypeSet& desired_types) {
for (ModelType type : desired_types) { for (ModelType type : desired_types) {
const auto& iter = controllers_->find(type); UpdateUnreadyTypeError(type);
if (iter == controllers_->end())
continue;
const DataTypeController* dtc = iter->second.get();
bool unready_status =
data_type_status_table_.GetUnreadyErrorTypes().Has(type);
if (dtc->ReadyForStart() != (unready_status == false)) {
// Adjust data_type_status_table_ if unready state in it doesn't match
// DataTypeController::ReadyForStart().
if (dtc->ReadyForStart()) {
data_type_status_table_.ResetUnreadyErrorFor(type);
} else {
SyncError error(FROM_HERE, SyncError::UNREADY_ERROR,
"Datatype not ready at config time.", type);
std::map<ModelType, SyncError> errors;
errors[type] = error;
data_type_status_table_.UpdateFailedDataTypes(errors);
}
}
} }
} }
bool DataTypeManagerImpl::UpdateUnreadyTypeError(ModelType type) {
const auto& iter = controllers_->find(type);
if (iter == controllers_->end())
return false;
const DataTypeController* dtc = iter->second.get();
bool unready_status =
data_type_status_table_.GetUnreadyErrorTypes().Has(type);
if (dtc->ReadyForStart() == (unready_status == false))
return false;
// Adjust data_type_status_table_ if unready state in it doesn't match
// DataTypeController::ReadyForStart().
if (dtc->ReadyForStart()) {
data_type_status_table_.ResetUnreadyErrorFor(type);
} else {
SyncError error(FROM_HERE, SyncError::UNREADY_ERROR,
"Datatype not ready at config time.", type);
std::map<ModelType, SyncError> errors;
errors[type] = error;
data_type_status_table_.UpdateFailedDataTypes(errors);
}
return true;
}
void DataTypeManagerImpl::ProcessReconfigure() { void DataTypeManagerImpl::ProcessReconfigure() {
// This may have been called asynchronously; no-op if it is no longer needed. // This may have been called asynchronously; no-op if it is no longer needed.
if (!needs_reconfigure_) { if (!needs_reconfigure_) {
......
...@@ -141,6 +141,11 @@ class DataTypeManagerImpl : public DataTypeManager, ...@@ -141,6 +141,11 @@ class DataTypeManagerImpl : public DataTypeManager,
// DataTypeController::ReadyForStart(). // DataTypeController::ReadyForStart().
void UpdateUnreadyTypeErrors(const ModelTypeSet& desired_types); void UpdateUnreadyTypeErrors(const ModelTypeSet& desired_types);
// Update unready state for |type|, such that data_type_status_table_ matches
// DataTypeController::ReadyForStart(). Returns true if there was an actual
// change.
bool UpdateUnreadyTypeError(ModelType type);
// Post a task to reconfigure when no downloading or association are running. // Post a task to reconfigure when no downloading or association are running.
void ProcessReconfigure(); void ProcessReconfigure();
......
...@@ -48,6 +48,8 @@ const base::Feature kSyncPseudoUSSAppList{"SyncPseudoUSSAppList", ...@@ -48,6 +48,8 @@ const base::Feature kSyncPseudoUSSAppList{"SyncPseudoUSSAppList",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncPseudoUSSApps{"SyncPseudoUSSApps", const base::Feature kSyncPseudoUSSApps{"SyncPseudoUSSApps",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncPseudoUSSArcPackage{"SyncPseudoUSSArcPackage",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncPseudoUSSDictionary{"SyncPseudoUSSDictionary", const base::Feature kSyncPseudoUSSDictionary{"SyncPseudoUSSDictionary",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncPseudoUSSExtensionSettings{ const base::Feature kSyncPseudoUSSExtensionSettings{
......
...@@ -24,6 +24,7 @@ extern const base::Feature ...@@ -24,6 +24,7 @@ extern const base::Feature
kSyncAllowWalletDataInTransportModeWithCustomPassphrase; kSyncAllowWalletDataInTransportModeWithCustomPassphrase;
extern const base::Feature kSyncPseudoUSSAppList; extern const base::Feature kSyncPseudoUSSAppList;
extern const base::Feature kSyncPseudoUSSApps; extern const base::Feature kSyncPseudoUSSApps;
extern const base::Feature kSyncPseudoUSSArcPackage;
extern const base::Feature kSyncPseudoUSSDictionary; extern const base::Feature kSyncPseudoUSSDictionary;
extern const base::Feature kSyncPseudoUSSExtensionSettings; extern const base::Feature kSyncPseudoUSSExtensionSettings;
extern const base::Feature kSyncPseudoUSSExtensions; extern const base::Feature kSyncPseudoUSSExtensions;
......
...@@ -4,10 +4,16 @@ ...@@ -4,10 +4,16 @@
#include "components/sync/model/syncable_service.h" #include "components/sync/model/syncable_service.h"
#include <utility>
namespace syncer { namespace syncer {
SyncableService::SyncableService() {} SyncableService::SyncableService() {}
SyncableService::~SyncableService() {} SyncableService::~SyncableService() {}
void SyncableService::WaitUntilReadyToSync(base::OnceClosure done) {
std::move(done).Run();
}
} // namespace syncer } // namespace syncer
...@@ -43,6 +43,12 @@ class SyncableService : public base::SupportsWeakPtr<SyncableService> { ...@@ -43,6 +43,12 @@ class SyncableService : public base::SupportsWeakPtr<SyncableService> {
// make pptimizations or tradeoffs by type, etc. // make pptimizations or tradeoffs by type, etc.
using StartSyncFlare = base::Callback<void(ModelType)>; using StartSyncFlare = base::Callback<void(ModelType)>;
// Allows the SyncableService to delay sync events (all below) until the model
// becomes ready to sync.
// TODO(crbug.com/939329): Make this pure to enforce discussion on all
// subclasses.
virtual void WaitUntilReadyToSync(base::OnceClosure done);
// Informs the service to begin syncing the specified synced datatype |type|. // Informs the service to begin syncing the specified synced datatype |type|.
// The service should then merge |initial_sync_data| into it's local data, // The service should then merge |initial_sync_data| into it's local data,
// calling |sync_processor|'s ProcessSyncChanges as necessary to reconcile the // calling |sync_processor|'s ProcessSyncChanges as necessary to reconcile the
......
...@@ -319,10 +319,9 @@ void SyncableServiceBasedBridge::OnSyncStarting( ...@@ -319,10 +319,9 @@ void SyncableServiceBasedBridge::OnSyncStarting(
return; return;
} }
std::move(store_factory_) syncable_service_->WaitUntilReadyToSync(
.Run(type_, base::BindOnce(&SyncableServiceBasedBridge::OnStoreCreated, base::BindOnce(&SyncableServiceBasedBridge::OnSyncableServiceReady,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
DCHECK(!store_factory_);
} }
base::Optional<ModelError> SyncableServiceBasedBridge::MergeSyncData( base::Optional<ModelError> SyncableServiceBasedBridge::MergeSyncData(
...@@ -456,6 +455,15 @@ SyncableServiceBasedBridge::CreateLocalChangeProcessorForTesting( ...@@ -456,6 +455,15 @@ SyncableServiceBasedBridge::CreateLocalChangeProcessorForTesting(
other); other);
} }
void SyncableServiceBasedBridge::OnSyncableServiceReady() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(store_factory_)
.Run(type_, base::BindOnce(&SyncableServiceBasedBridge::OnStoreCreated,
weak_ptr_factory_.GetWeakPtr()));
DCHECK(!store_factory_);
}
void SyncableServiceBasedBridge::OnStoreCreated( void SyncableServiceBasedBridge::OnStoreCreated(
const base::Optional<ModelError>& error, const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store) { std::unique_ptr<ModelTypeStore> store) {
......
...@@ -76,6 +76,7 @@ class SyncableServiceBasedBridge : public ModelTypeSyncBridge { ...@@ -76,6 +76,7 @@ class SyncableServiceBasedBridge : public ModelTypeSyncBridge {
ModelTypeChangeProcessor* other); ModelTypeChangeProcessor* other);
private: private:
void OnSyncableServiceReady();
void OnStoreCreated(const base::Optional<ModelError>& error, void OnStoreCreated(const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store); std::unique_ptr<ModelTypeStore> store);
void OnReadAllDataForInit(std::unique_ptr<InMemoryStore> in_memory_store, void OnReadAllDataForInit(std::unique_ptr<InMemoryStore> in_memory_store,
......
...@@ -30,14 +30,16 @@ ...@@ -30,14 +30,16 @@
namespace syncer { namespace syncer {
namespace { namespace {
using testing::_;
using testing::DoAll; using testing::DoAll;
using testing::ElementsAre; using testing::ElementsAre;
using testing::Invoke;
using testing::IsEmpty; using testing::IsEmpty;
using testing::IsNull;
using testing::NotNull; using testing::NotNull;
using testing::Pair; using testing::Pair;
using testing::Return; using testing::Return;
using testing::SaveArg; using testing::SaveArg;
using testing::_;
const ModelType kModelType = PREFERENCES; const ModelType kModelType = PREFERENCES;
...@@ -65,6 +67,7 @@ MATCHER_P(HasName, name, "") { ...@@ -65,6 +67,7 @@ MATCHER_P(HasName, name, "") {
class MockSyncableService : public SyncableService { class MockSyncableService : public SyncableService {
public: public:
MOCK_METHOD1(WaitUntilReadyToSync, void(base::OnceClosure done));
MOCK_METHOD4( MOCK_METHOD4(
MergeDataAndStartSyncing, MergeDataAndStartSyncing,
SyncMergeResult(ModelType type, SyncMergeResult(ModelType type,
...@@ -82,6 +85,9 @@ class SyncableServiceBasedBridgeTest : public ::testing::Test { ...@@ -82,6 +85,9 @@ class SyncableServiceBasedBridgeTest : public ::testing::Test {
protected: protected:
SyncableServiceBasedBridgeTest() SyncableServiceBasedBridgeTest()
: store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) { : store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) {
ON_CALL(syncable_service_, WaitUntilReadyToSync(_))
.WillByDefault(
Invoke([](base::OnceClosure done) { std::move(done).Run(); }));
ON_CALL(syncable_service_, MergeDataAndStartSyncing(_, _, _, _)) ON_CALL(syncable_service_, MergeDataAndStartSyncing(_, _, _, _))
.WillByDefault( .WillByDefault(
[&](ModelType type, const SyncDataList& initial_sync_data, [&](ModelType type, const SyncDataList& initial_sync_data,
...@@ -113,15 +119,18 @@ class SyncableServiceBasedBridgeTest : public ::testing::Test { ...@@ -113,15 +119,18 @@ class SyncableServiceBasedBridgeTest : public ::testing::Test {
real_processor_.reset(); real_processor_.reset();
} }
void StartSyncing() { syncer::DataTypeActivationRequest GetTestActivationRequest() {
syncer::DataTypeActivationRequest request; syncer::DataTypeActivationRequest request;
request.error_handler = mock_error_handler_.Get(); request.error_handler = mock_error_handler_.Get();
request.cache_guid = "TestCacheGuid"; request.cache_guid = "TestCacheGuid";
request.authenticated_account_id = "SomeAccountId"; request.authenticated_account_id = "SomeAccountId";
return request;
}
void StartSyncing() {
base::RunLoop loop; base::RunLoop loop;
real_processor_->OnSyncStarting( real_processor_->OnSyncStarting(
request, GetTestActivationRequest(),
base::BindLambdaForTesting( base::BindLambdaForTesting(
[&](std::unique_ptr<syncer::DataTypeActivationResponse> response) { [&](std::unique_ptr<syncer::DataTypeActivationResponse> response) {
worker_ = std::make_unique<MockModelTypeWorker>( worker_ = std::make_unique<MockModelTypeWorker>(
...@@ -204,6 +213,38 @@ TEST_F(SyncableServiceBasedBridgeTest, ...@@ -204,6 +213,38 @@ TEST_F(SyncableServiceBasedBridgeTest,
EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash, _))); EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash, _)));
} }
TEST_F(SyncableServiceBasedBridgeTest, ShouldWaitUntilModelReadyToSync) {
base::OnceClosure syncable_service_ready_cb;
ON_CALL(syncable_service_, WaitUntilReadyToSync(_))
.WillByDefault(Invoke([&](base::OnceClosure done) {
syncable_service_ready_cb = std::move(done);
}));
EXPECT_CALL(mock_processor_, ModelReadyToSync(_)).Times(0);
EXPECT_CALL(syncable_service_, WaitUntilReadyToSync(_)).Times(0);
EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing(_, _, _, _)).Times(0);
// Bridge initialization alone, without sync itself starting, should not
// issue calls to the syncable service.
InitializeBridge();
EXPECT_FALSE(syncable_service_ready_cb);
// Sync itself starting should wait until the syncable service becomes ready,
// before issuing any other call (e.g. MergeDataAndStartSyncing()).
EXPECT_CALL(syncable_service_, WaitUntilReadyToSync(_));
real_processor_->OnSyncStarting(GetTestActivationRequest(),
base::DoNothing());
ASSERT_TRUE(syncable_service_ready_cb);
// When the SyncableService gets ready, the bridge should propagate this
// information to the processor.
EXPECT_CALL(mock_processor_, ModelReadyToSync(_));
std::move(syncable_service_ready_cb).Run();
// Required to initialize the store.
base::RunLoop().RunUntilIdle();
}
TEST_F(SyncableServiceBasedBridgeTest, TEST_F(SyncableServiceBasedBridgeTest,
ShouldStopSyncableServiceIfPreviouslyStarted) { ShouldStopSyncableServiceIfPreviouslyStarted) {
InitializeBridge(); InitializeBridge();
......
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