Commit f8fb8c69 authored by Alexey Baskakov's avatar Alexey Baskakov Committed by Commit Bot

WebApp: Implement WebAppSyncBridge in full.

This code is disabled by default behind kDesktopPWAsWithoutExtensions and
kDesktopPWAsUSS base features.

- Implement WebAppSyncBridge::MergeSyncData and ApplySyncChanges.
- Implement "Local changes" propagation to change_processor.

Unit tests and browser tests will be added later in a follow up CL.
An MVP implementation of the bridge needed first.

This CL follows Chrome Sync's Model API doc
https://chromium.googlesource.com/chromium/src/+/HEAD/docs/sync/model_api.md

In next CLs:
Implement sync-initiated installs and uninstalls.

TBR=alancutter@chromium.org

Bug: 860583
Change-Id: I65d3cae6f47dd8fc8fdbe2c7cfb2ed13012f90f3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1830494Reviewed-by: default avatarAlexey Baskakov <loyso@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Commit-Queue: Alexey Baskakov <loyso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704482}
parent 92809357
......@@ -45,6 +45,7 @@ source_set("web_applications") {
"web_app_registry_update.h",
"web_app_sync_bridge.cc",
"web_app_sync_bridge.h",
"web_app_sync_install_delegate.h",
]
deps = [
......
......@@ -19,6 +19,9 @@ enum Type {
kSystem = kMinValue,
kPolicy,
kWebAppStore,
// We sync only regular user-installed apps from the open web. For
// user-installed apps without overlaps this is the only source that will be
// set.
kSync,
kDefault,
kMaxValue
......
......@@ -7,6 +7,7 @@
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/web_applications/test/test_web_app_database_factory.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
......@@ -21,7 +22,7 @@ void TestWebAppRegistryController::SetUp(Profile* profile) {
mutable_registrar_ = std::make_unique<WebAppRegistrarMutable>(profile);
sync_bridge_ = std::make_unique<WebAppSyncBridge>(
profile, database_factory_.get(), mutable_registrar_.get(),
profile, database_factory_.get(), mutable_registrar_.get(), this,
mock_processor_.CreateForwardingProcessor());
ON_CALL(processor(), IsTrackingMetadata())
......@@ -51,6 +52,12 @@ void TestWebAppRegistryController::UnregisterAll() {
update->DeleteApp(app_id);
}
void TestWebAppRegistryController::InstallWebAppsAfterSync(
std::vector<WebApp*> web_apps) {}
void TestWebAppRegistryController::UninstallWebAppsAfterSync(
std::vector<std::unique_ptr<WebApp>> web_apps) {}
void TestWebAppRegistryController::DestroySubsystems() {
mutable_registrar_.reset();
sync_bridge_.reset();
......
......@@ -9,6 +9,7 @@
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_sync_install_delegate.h"
#include "components/sync/model/mock_model_type_change_processor.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -20,7 +21,7 @@ class TestWebAppDatabaseFactory;
class WebAppSyncBridge;
class WebApp;
class TestWebAppRegistryController {
class TestWebAppRegistryController : public SyncInstallDelegate {
public:
TestWebAppRegistryController();
~TestWebAppRegistryController();
......@@ -35,6 +36,11 @@ class TestWebAppRegistryController {
void UnregisterApp(const AppId& app_id);
void UnregisterAll();
// SyncInstallDelegate:
void InstallWebAppsAfterSync(std::vector<WebApp*> web_apps) override;
void UninstallWebAppsAfterSync(
std::vector<std::unique_ptr<WebApp>> web_apps) override;
void DestroySubsystems();
TestWebAppDatabaseFactory& database_factory() { return *database_factory_; }
......
......@@ -33,6 +33,9 @@ class WebApp {
const GURL& scope() const { return scope_; }
const base::Optional<SkColor>& theme_color() const { return theme_color_; }
blink::mojom::DisplayMode display_mode() const { return display_mode_; }
// Locally installed apps have shortcuts installed on various UI surfaces.
// If app isn't locally installed, it is excluded from UIs and only listed as
// a part of user's app library.
bool is_locally_installed() const { return is_locally_installed_; }
// Sync-initiated installation produces a sync placeholder app awaiting for
// full installation process. The sync placeholder app has only app_id,
......
......@@ -13,6 +13,7 @@
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "components/sync/base/model_type.h"
#include "components/sync/model/metadata_batch.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
......@@ -50,14 +51,18 @@ void WebAppDatabase::BeginTransaction() {
write_batch_ = store_->CreateWriteBatch();
}
void WebAppDatabase::CommitTransaction(const RegistryUpdateData& update_data,
CompletionCallback callback) {
void WebAppDatabase::CommitTransaction(
const RegistryUpdateData& update_data,
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
CompletionCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(opened_);
DCHECK(write_batch_);
DCHECK(!update_data.IsEmpty());
write_batch_->TakeMetadataChangesFrom(std::move(metadata_change_list));
for (const std::unique_ptr<WebApp>& web_app : update_data.apps_to_create) {
auto proto = CreateWebAppProto(*web_app);
write_batch_->WriteData(web_app->app_id(), proto->SerializeAsString());
......
......@@ -21,6 +21,7 @@
namespace syncer {
class ModelError;
class MetadataBatch;
class MetadataChangeList;
} // namespace syncer
namespace web_app {
......@@ -49,8 +50,10 @@ class WebAppDatabase {
using CompletionCallback = base::OnceCallback<void(bool success)>;
// There can be only 1 transaction at a time.
void BeginTransaction();
void CommitTransaction(const RegistryUpdateData& update_data,
CompletionCallback callback);
void CommitTransaction(
const RegistryUpdateData& update_data,
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
CompletionCallback callback);
void CancelTransaction();
// Exposed for testing.
......
......@@ -14,6 +14,7 @@
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_data_retriever.h"
#include "chrome/browser/web_applications/components/web_app_utils.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_install_task.h"
#include "chrome/common/web_application_info.h"
#include "content/public/browser/web_contents.h"
......@@ -154,6 +155,18 @@ void WebAppInstallManager::Shutdown() {
web_contents_.reset();
}
void WebAppInstallManager::InstallWebAppsAfterSync(
std::vector<WebApp*> web_apps) {
// TODO(crbug.com/860583): Implement sync-initiated app installs.
NOTIMPLEMENTED();
}
void WebAppInstallManager::UninstallWebAppsAfterSync(
std::vector<std::unique_ptr<WebApp>> web_apps) {
// TODO(crbug.com/860583): Implement sync-initiated app uninstalls.
NOTIMPLEMENTED();
}
void WebAppInstallManager::SetUrlLoaderForTesting(
std::unique_ptr<WebAppUrlLoader> url_loader) {
url_loader_ = std::move(url_loader);
......
......@@ -16,6 +16,7 @@
#include "chrome/browser/web_applications/components/install_manager.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_url_loader.h"
#include "chrome/browser/web_applications/web_app_sync_install_delegate.h"
class Profile;
......@@ -29,7 +30,8 @@ enum class InstallResultCode;
class WebAppDataRetriever;
class WebAppInstallTask;
class WebAppInstallManager final : public InstallManager {
class WebAppInstallManager final : public InstallManager,
public SyncInstallDelegate {
public:
explicit WebAppInstallManager(Profile* profile);
~WebAppInstallManager() override;
......@@ -64,6 +66,11 @@ class WebAppInstallManager final : public InstallManager {
OnceInstallCallback callback) override;
void Shutdown() override;
// For the new USS-based system only. SyncInstallDelegate:
void InstallWebAppsAfterSync(std::vector<WebApp*> web_apps) override;
void UninstallWebAppsAfterSync(
std::vector<std::unique_ptr<WebApp>> web_apps) override;
using DataRetrieverFactory =
base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()>;
void SetDataRetrieverFactoryForTesting(
......
......@@ -170,7 +170,8 @@ void WebAppProvider::CreateWebAppsSubsystems(Profile* profile) {
auto mutable_registrar = std::make_unique<WebAppRegistrarMutable>(profile);
sync_bridge = std::make_unique<WebAppSyncBridge>(
profile, database_factory_.get(), mutable_registrar.get());
profile, database_factory_.get(), mutable_registrar.get(),
install_manager_.get());
// Upcast to read-only WebAppRegistrar.
registrar = std::move(mutable_registrar);
......
......@@ -5,16 +5,20 @@
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/logging.h"
#include "base/optional.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_database.h"
#include "chrome/browser/web_applications/web_app_database_factory.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_install_delegate.h"
#include "chrome/common/channel_info.h"
#include "components/sync/base/model_type.h"
#include "components/sync/base/report_unrecoverable_error.h"
......@@ -36,27 +40,71 @@ std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app) {
auto entity_data = std::make_unique<syncer::EntityData>();
entity_data->name = app.name();
sync_pb::WebAppSpecifics* specifics =
sync_pb::WebAppSpecifics* sync_data =
entity_data->specifics.mutable_web_app();
specifics->set_launch_url(app.launch_url().spec());
specifics->set_name(app.name());
specifics->set_display_mode(ToWebAppSpecificsDisplayMode(app.display_mode()));
if (app.theme_color().has_value())
specifics->set_theme_color(app.theme_color().value());
sync_data->set_launch_url(app.launch_url().spec());
sync_data->set_display_mode(ToWebAppSpecificsDisplayMode(app.display_mode()));
sync_data->set_name(app.sync_data().name);
if (app.sync_data().theme_color.has_value())
sync_data->set_theme_color(app.sync_data().theme_color.value());
return entity_data;
}
void ApplySyncDataToApp(const sync_pb::WebAppSpecifics& sync_data,
WebApp* app) {
app->AddSource(Source::kSync);
// app_id is a hash of launch_url. Parse launch_url first:
GURL launch_url(sync_data.launch_url());
if (launch_url.is_empty() || !launch_url.is_valid()) {
DLOG(ERROR) << "ApplySyncDataToApp: launch_url parse error.";
return;
}
if (app->app_id() != GenerateAppIdFromURL(launch_url)) {
DLOG(ERROR) << "ApplySyncDataToApp: app_id doesn't match launch_url.";
return;
}
if (app->launch_url().is_empty()) {
app->SetLaunchUrl(std::move(launch_url));
} else if (app->launch_url() != launch_url) {
DLOG(ERROR)
<< "ApplySyncDataToApp: existing launch_url doesn't match launch_url.";
return;
}
// Always override display mode with a synced value.
app->SetDisplayMode(ToMojomDisplayMode(sync_data.display_mode()));
WebApp::SyncData parsed_sync_data;
parsed_sync_data.name = sync_data.name();
if (sync_data.has_theme_color())
parsed_sync_data.theme_color = sync_data.theme_color();
app->SetSyncData(parsed_sync_data);
}
bool AreAppsLocallyInstalledByDefault() {
#if defined(OS_CHROMEOS)
// On Chrome OS, sync always locally installs an app.
return true;
#else
return false;
#endif
}
} // namespace
WebAppSyncBridge::WebAppSyncBridge(
Profile* profile,
AbstractWebAppDatabaseFactory* database_factory,
WebAppRegistrarMutable* registrar)
WebAppRegistrarMutable* registrar,
SyncInstallDelegate* install_delegate)
: WebAppSyncBridge(
profile,
database_factory,
registrar,
install_delegate,
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
syncer::WEB_APPS,
base::BindRepeating(&syncer::ReportUnrecoverableError,
......@@ -66,10 +114,12 @@ WebAppSyncBridge::WebAppSyncBridge(
Profile* profile,
AbstractWebAppDatabaseFactory* database_factory,
WebAppRegistrarMutable* registrar,
SyncInstallDelegate* install_delegate,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor)
: AppRegistryController(profile),
syncer::ModelTypeSyncBridge(std::move(change_processor)),
registrar_(registrar) {
registrar_(registrar),
install_delegate_(install_delegate) {
DCHECK(database_factory);
DCHECK(registrar_);
database_ = std::make_unique<WebAppDatabase>(
......@@ -103,12 +153,14 @@ void WebAppSyncBridge::CommitUpdate(
CheckRegistryUpdateData(update->update_data());
registrar_->CountMutation();
std::unique_ptr<RegistryUpdateData> update_data = update->TakeUpdateData();
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list =
CreateMetadataChangeList();
UpdateSync(*update_data, metadata_change_list.get());
database_->CommitTransaction(
*update_data,
*update_data, std::move(metadata_change_list),
base::BindOnce(&WebAppSyncBridge::OnDataWritten,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
......@@ -157,19 +209,73 @@ void WebAppSyncBridge::CheckRegistryUpdateData(
#endif
}
void WebAppSyncBridge::UpdateRegistrar(
std::vector<std::unique_ptr<WebApp>> WebAppSyncBridge::UpdateRegistrar(
std::unique_ptr<RegistryUpdateData> update_data) {
registrar_->CountMutation();
std::vector<std::unique_ptr<WebApp>> apps_unregistered;
for (std::unique_ptr<WebApp>& web_app : update_data->apps_to_create) {
AppId app_id = web_app->app_id();
DCHECK(!registrar_->GetAppById(app_id));
registrar_->registry().emplace(std::move(app_id), std::move(web_app));
}
// update_data->apps_to_update are ignored here because we do in-place
// updates.
for (const AppId& app_id : update_data->apps_to_delete) {
auto it = registrar_->registry().find(app_id);
DCHECK(it != registrar_->registry().end());
apps_unregistered.push_back(std::move(it->second));
registrar_->registry().erase(it);
}
return apps_unregistered;
}
void WebAppSyncBridge::UpdateSync(
const RegistryUpdateData& update_data,
syncer::MetadataChangeList* metadata_change_list) {
// We don't block web app subsystems on WebAppSyncBridge::MergeSyncData: we
// call WebAppProvider::OnRegistryControllerReady() right after
// change_processor()->ModelReadyToSync. As a result, subsystems may produce
// some local changes between OnRegistryControllerReady and MergeSyncData.
// Return early in this case. The processor cannot do any useful metadata
// tracking until MergeSyncData is called:
if (!change_processor()->IsTrackingMetadata())
return;
for (const std::unique_ptr<WebApp>& app : update_data.apps_to_create) {
if (app->IsSynced()) {
change_processor()->Put(app->app_id(), CreateSyncEntityData(*app),
metadata_change_list);
}
}
// An app may obtain or may loose IsSynced flag without being deleted. We
// should conservatively include or exclude the app from the synced apps
// subset.
//
// TODO(loyso): Send an update to sync server only if any sync-specific
// data was changed. Implement some dirty flags in WebApp setter methods.
for (const WebApp* app : update_data.apps_to_update) {
if (app->IsSynced()) {
change_processor()->Put(app->app_id(), CreateSyncEntityData(*app),
metadata_change_list);
} else {
change_processor()->Delete(app->app_id(), metadata_change_list);
}
}
// We should unconditionally delete from sync (in case IsSynced flag was
// removed during the update).
for (const AppId& app_id : update_data.apps_to_delete) {
const WebApp* app = registrar_->GetAppById(app_id);
DCHECK(app);
change_processor()->Delete(app_id, metadata_change_list);
}
}
void WebAppSyncBridge::OnDatabaseOpened(
......@@ -195,6 +301,102 @@ void WebAppSyncBridge::ReportErrorToChangeProcessor(
change_processor()->ReportError(error);
}
void WebAppSyncBridge::MergeLocalAppsToSync(
const syncer::EntityChangeList& entity_data,
syncer::MetadataChangeList* metadata_change_list) {
// Build a helper set of the sync server apps to speed up lookups. The
// flat_set will reuse the underlying memory of this vector. app_id is storage
// key.
std::vector<AppId> storage_keys;
storage_keys.reserve(entity_data.size());
for (const auto& change : entity_data)
storage_keys.push_back(change->storage_key());
// Sort only once.
base::flat_set<AppId> sync_server_apps(std::move(storage_keys));
for (const WebApp& app : registrar_->AllApps()) {
if (!app.IsSynced())
continue;
bool exists_remotely = sync_server_apps.contains(app.app_id());
if (!exists_remotely) {
change_processor()->Put(app.app_id(), CreateSyncEntityData(app),
metadata_change_list);
}
}
}
void WebAppSyncBridge::ApplySyncDataChange(
const syncer::EntityChange& change,
RegistryUpdateData* update_local_data) {
// app_id is storage key.
const AppId& app_id = change.storage_key();
WebApp* existing_web_app = registrar_->GetAppByIdMutable(app_id);
// Handle deletion first.
if (change.type() == syncer::EntityChange::ACTION_DELETE) {
if (!existing_web_app) {
DLOG(ERROR) << "ApplySyncDataChange error: no app to delete";
return;
}
existing_web_app->RemoveSource(Source::kSync);
if (existing_web_app->HasAnySources())
update_local_data->apps_to_update.insert(existing_web_app);
else
update_local_data->apps_to_delete.push_back(app_id);
return;
}
// Handle EntityChange::ACTION_ADD and EntityChange::ACTION_UPDATE.
DCHECK(change.data().specifics.has_web_app());
const sync_pb::WebAppSpecifics& specifics = change.data().specifics.web_app();
if (existing_web_app) {
// Any entities that appear in both sets must be merged.
ApplySyncDataToApp(specifics, existing_web_app);
// Preserve web_app->is_locally_installed user's choice here.
update_local_data->apps_to_update.insert(existing_web_app);
} else {
// Any remote entities that don’t exist locally must be written to local
// storage.
auto web_app = std::make_unique<WebApp>(app_id);
// Request a followup sync-initiated install for this placeholder to fetch
// full local data and all the icons.
web_app->SetIsSyncPlaceholder(true);
ApplySyncDataToApp(specifics, web_app.get());
// For a new app, automatically choose if we want to install it locally.
web_app->SetIsLocallyInstalled(AreAppsLocallyInstalledByDefault());
update_local_data->apps_to_create.push_back(std::move(web_app));
}
}
void WebAppSyncBridge::ApplySyncChangesToRegistrar(
std::unique_ptr<RegistryUpdateData> update_local_data) {
std::vector<WebApp*> apps_to_install;
for (const auto& web_app : update_local_data->apps_to_create)
apps_to_install.push_back(web_app.get());
std::vector<std::unique_ptr<WebApp>> apps_unregistered =
UpdateRegistrar(std::move(update_local_data));
// Do a full follow up install for all remote entities that don’t exist
// locally.
install_delegate_->InstallWebAppsAfterSync(std::move(apps_to_install));
// Do a full follow up uninstall for all deleted remote entities that exist
// locally and not needed by other sources. We need to clean up disk data
// (icons).
install_delegate_->UninstallWebAppsAfterSync(std::move(apps_unregistered));
}
std::unique_ptr<syncer::MetadataChangeList>
WebAppSyncBridge::CreateMetadataChangeList() {
return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
......@@ -203,14 +405,42 @@ WebAppSyncBridge::CreateMetadataChangeList() {
base::Optional<syncer::ModelError> WebAppSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
NOTIMPLEMENTED();
DCHECK(change_processor()->IsTrackingMetadata());
auto update_local_data = std::make_unique<RegistryUpdateData>();
database_->BeginTransaction();
for (const auto& change : entity_data) {
DCHECK_NE(change->type(), syncer::EntityChange::ACTION_DELETE);
ApplySyncDataChange(*change, update_local_data.get());
}
MergeLocalAppsToSync(entity_data, metadata_change_list.get());
database_->CommitTransaction(
*update_local_data, std::move(metadata_change_list), base::DoNothing());
ApplySyncChangesToRegistrar(std::move(update_local_data));
return base::nullopt;
}
base::Optional<syncer::ModelError> WebAppSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
NOTIMPLEMENTED();
DCHECK(change_processor()->IsTrackingMetadata());
auto update_local_data = std::make_unique<RegistryUpdateData>();
database_->BeginTransaction();
for (const auto& change : entity_changes)
ApplySyncDataChange(*change, update_local_data.get());
database_->CommitTransaction(
*update_local_data, std::move(metadata_change_list), base::DoNothing());
ApplySyncChangesToRegistrar(std::move(update_local_data));
return base::nullopt;
}
......
......@@ -14,12 +14,14 @@
#include "chrome/browser/web_applications/components/app_registry_controller.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/sync/model/entity_change.h"
#include "components/sync/model/model_type_sync_bridge.h"
class Profile;
namespace syncer {
class MetadataBatch;
class MetadataChangeList;
class ModelError;
class ModelTypeChangeProcessor;
} // namespace syncer
......@@ -27,6 +29,7 @@ class ModelTypeChangeProcessor;
namespace web_app {
class AbstractWebAppDatabaseFactory;
class SyncInstallDelegate;
class WebAppDatabase;
class WebAppRegistryUpdate;
struct RegistryUpdateData;
......@@ -38,12 +41,14 @@ class WebAppSyncBridge : public AppRegistryController,
public:
WebAppSyncBridge(Profile* profile,
AbstractWebAppDatabaseFactory* database_factory,
WebAppRegistrarMutable* registrar);
WebAppRegistrarMutable* registrar,
SyncInstallDelegate* install_delegate);
// Tests may inject mocks using this ctor.
WebAppSyncBridge(
Profile* profile,
AbstractWebAppDatabaseFactory* database_factory,
WebAppRegistrarMutable* registrar,
SyncInstallDelegate* install_delegate,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor);
~WebAppSyncBridge() override;
......@@ -64,8 +69,15 @@ class WebAppSyncBridge : public AppRegistryController,
private:
void CheckRegistryUpdateData(const RegistryUpdateData& update_data) const;
// Update the in-memory model.
void UpdateRegistrar(std::unique_ptr<RegistryUpdateData> update_data);
// Update the in-memory model. Returns unregistered apps which may be
// disposed.
std::vector<std::unique_ptr<WebApp>> UpdateRegistrar(
std::unique_ptr<RegistryUpdateData> update_data);
// Update the remote sync server.
void UpdateSync(const RegistryUpdateData& update_data,
syncer::MetadataChangeList* metadata_change_list);
void OnDatabaseOpened(base::OnceClosure callback,
Registry registry,
......@@ -74,6 +86,17 @@ class WebAppSyncBridge : public AppRegistryController,
void ReportErrorToChangeProcessor(const syncer::ModelError& error);
// Any local entities that don’t exist remotely must be provided to sync.
void MergeLocalAppsToSync(const syncer::EntityChangeList& entity_data,
syncer::MetadataChangeList* metadata_change_list);
void ApplySyncDataChange(const syncer::EntityChange& change,
RegistryUpdateData* update_local_data);
// Update registrar and Install/Uninstall missing/excessive local apps.
void ApplySyncChangesToRegistrar(
std::unique_ptr<RegistryUpdateData> update_local_data);
// syncer::ModelTypeSyncBridge:
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
......@@ -90,6 +113,7 @@ class WebAppSyncBridge : public AppRegistryController,
std::unique_ptr<WebAppDatabase> database_;
WebAppRegistrarMutable* const registrar_;
SyncInstallDelegate* const install_delegate_;
bool is_in_update_ = false;
......
// 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_WEB_APPLICATIONS_WEB_APP_SYNC_INSTALL_DELEGATE_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_SYNC_INSTALL_DELEGATE_H_
#include <memory>
#include <vector>
namespace web_app {
class WebApp;
// WebAppSyncBridge delegates sync-initiated installs and uninstalls using
// this interface.
class SyncInstallDelegate {
public:
virtual ~SyncInstallDelegate() = default;
// |web_apps| are already registered and owned by the registrar.
virtual void InstallWebAppsAfterSync(std::vector<WebApp*> web_apps) = 0;
// |web_apps| are already unregistered and not owned by the registrar.
virtual void UninstallWebAppsAfterSync(
std::vector<std::unique_ptr<WebApp>> web_apps) = 0;
};
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_SYNC_INSTALL_DELEGATE_H_
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