File: web_app_sync_bridge.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (315 lines) | stat: -rw-r--r-- 12,965 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
// Copyright 2019 The Chromium Authors
// 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_BRIDGE_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_SYNC_BRIDGE_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/auto_reset.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/one_shot_event.h"
#include "build/build_config.h"
#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
#include "chrome/browser/web_applications/web_app_database.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/sync/model/data_type_sync_bridge.h"
#include "components/sync/model/entity_change.h"
#include "components/webapps/common/web_app_id.h"

namespace base {
class Time;
}

namespace syncer {
class DataTypeLocalChangeProcessor;
struct EntityData;
class MetadataBatch;
class MetadataChangeList;
class ModelError;
class StringOrdinal;
}  // namespace syncer

namespace sync_pb {
class WebAppSpecifics;
}  // namespace sync_pb

namespace webapps {
enum class UninstallResultCode;
enum class InstallResultCode;
}  // namespace webapps

namespace web_app {

class AbstractWebAppDatabaseFactory;
class AppLock;
class ScopedRegistryUpdate;
class WebApp;
class WebAppCommandManager;
class WebAppInstallManager;
class WebAppRegistryUpdate;
class WebAppCommandScheduler;
enum class ApiApprovalState;
struct RegistryUpdateData;

// These errors cause the sync entity to no longer be parsable, and results in
// `IsEntityDataValid` returning false below.
//
// Used in metrics, do not re-number or remove entities.
enum class StorageKeyParseResult {
  // This is needed for normalization
  kSuccess = 0,
  kNoStartUrl = 1,
  kInvalidStartUrl = 2,
  kInvalidManifestId = 3,
  kMaxValue = kInvalidManifestId
};

// After parsing the storage key, other problems with parsing the manifest id
// can occur. In the future, these errors could result in deletion of sync
// and/or local data to clean things up.
//
// Used in metrics, do not re-number or remove entities.
enum class ManifestIdParseResult {
  // This is needed for normalization.
  kSuccess = 0,
  // The origin of the start_url and resolved manifest_id do not match.
  kManifestIdResolutionFailure = 1,
  // The manifest_id resolved from sync doesn't match the local app's
  // manifest_id.
  kManifestIdDoesNotMatchLocalData = 2,
  kMaxValue = kManifestIdDoesNotMatchLocalData
};

// A unified sync and storage controller.
//
// While WebAppRegistrar is a read-only model, WebAppSyncBridge is a
// controller for that model. WebAppSyncBridge is responsible for:
// - Registry initialization (reading model from a persistent storage like
// LevelDb or prefs).
// - Writing all the registry updates to a persistent store and sync.
//
// WebAppSyncBridge is the key class to support integration with Unified Sync
// and Storage (USS) system. The sync bridge exclusively owns
// DataTypeLocalChangeProcessor and WebAppDatabase (the storage).
class WebAppSyncBridge : public syncer::DataTypeSyncBridge {
 public:
  // Disable the logic that resumes pending sync installs, and fixes cases where
  // os integration is missing but the app's install_state indicates OS
  // integration should be present. Only intended for use in tests that need to
  // check the app state before these operations are done.
  static base::AutoReset<bool>
  DisableResumeSyncInstallAndMissingOsIntegrationForTesting();

  explicit WebAppSyncBridge(WebAppRegistrarMutable* registrar);
  // Tests may inject mocks using this ctor.
  WebAppSyncBridge(
      WebAppRegistrarMutable* registrar,
      std::unique_ptr<syncer::DataTypeLocalChangeProcessor> change_processor);
  WebAppSyncBridge(const WebAppSyncBridge&) = delete;
  WebAppSyncBridge& operator=(const WebAppSyncBridge&) = delete;
  ~WebAppSyncBridge() override;

  void SetSubsystems(AbstractWebAppDatabaseFactory* database_factory,
                     WebAppCommandManager* command_manager,
                     WebAppCommandScheduler* command_scheduler,
                     WebAppInstallManager* install_manager);

  using CommitCallback = base::OnceCallback<void(bool success)>;
  using RepeatingUninstallCallback =
      base::RepeatingCallback<void(const webapps::AppId& app_id,
                                   webapps::UninstallResultCode code)>;
  // This is the writable API for the registry. Any updates will be written to
  // LevelDb and sync service. There can be only 1 update at a time. The
  // returned update will be committed to the database automatically on
  // destruction.
  //
  // Writes to the RAM database are synchronous. It is normally not necessary to
  // wait for the disk write to complete, because:
  // - All reads and writes happen from the RAM database.
  // - The disk database is only read during startup before the system starts,
  //   and is only written to during the rest of the browser's lifetime.
  //
  // The only reason waiting may be necessary here is to handle the edge case
  // that a crash happens and the operation wants to ensure that the disk state
  // is updated before continuing. This may be necessary for, say, a two-phase
  // commit involving another browser system with its own storage.
  [[nodiscard]] ScopedRegistryUpdate BeginUpdate(
      CommitCallback callback = base::DoNothing());

  void Init(base::OnceClosure callback);

  // Non testing code should use SetUserDisplayModeCommand instead.
  void SetAppUserDisplayModeForTesting(
      const webapps::AppId& app_id,
      mojom::UserDisplayMode user_display_mode);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppIsDisabled(AppLock& lock,
                        const webapps::AppId& app_id,
                        bool is_disabled);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void UpdateAppsDisableMode();

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppLastBadgingTime(const webapps::AppId& app_id,
                             const base::Time& time);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppLastLaunchTime(const webapps::AppId& app_id,
                            const base::Time& time);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppFirstInstallTime(const webapps::AppId& app_id,
                              const base::Time& time);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppManifestUpdateTime(const webapps::AppId& app_id,
                                const base::Time& time);

  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppWindowControlsOverlayEnabled(const webapps::AppId& app_id,
                                          bool enabled);

  // These methods are used by extensions::AppSorting, which manages the sorting
  // of web apps on chrome://apps.
  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetUserPageOrdinal(const webapps::AppId& app_id,
                          syncer::StringOrdinal user_page_ordinal);
  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetUserLaunchOrdinal(const webapps::AppId& app_id,
                            syncer::StringOrdinal user_launch_ordinal);

  // Stores the user's preference for the app's use of the File Handling API.
  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAppFileHandlerApprovalState(const webapps::AppId& app_id,
                                      ApiApprovalState state);

#if BUILDFLAG(IS_MAC)
  // TODO(crbug.com/41490924): Remove this and use a command instead.
  void SetAlwaysShowToolbarInFullscreen(const webapps::AppId& app_id,
                                        bool show);
#endif

  // An access to read-only registry. Does an upcast to read-only type.
  const WebAppRegistrar& registrar() const { return *registrar_; }

  // syncer::DataTypeSyncBridge:
  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
      override;
  std::optional<syncer::ModelError> MergeFullSyncData(
      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
      syncer::EntityChangeList entity_data) override;
  std::optional<syncer::ModelError> ApplyIncrementalSyncChanges(
      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
      syncer::EntityChangeList entity_changes) override;
  void ApplyDisableSyncChanges(std::unique_ptr<syncer::MetadataChangeList>
                                   delete_metadata_change_list) override;
  std::unique_ptr<syncer::DataBatch> GetDataForCommit(
      StorageKeyList storage_keys) override;
  std::unique_ptr<syncer::DataBatch> GetAllDataForDebugging() override;
  std::string GetClientTag(
      const syncer::EntityData& entity_data) const override;
  std::string GetStorageKey(
      const syncer::EntityData& entity_data) const override;
  bool IsEntityDataValid(const syncer::EntityData& entity_data) const override;

  // Signals that the sync system has received data from the server at some
  // point, potentially on a previous startup. Apps may still be installing or
  // uninstalling.
  const base::OneShotEvent& on_sync_connected() const {
    return on_sync_connected_;
  }

  // Used for testing only.
  void set_disable_checks_for_testing(bool disable_checks_for_testing) {
    disable_checks_for_testing_ = disable_checks_for_testing;
  }

  WebAppDatabase* GetDatabaseForTesting() const { return database_.get(); }

  // TODO(crbug.com/41490924): Remove this and make it so tests can
  // install via sync instead to reach this state.
  // Note: This doesn't synchronize the OS integration manager, so the os
  // integration state is not cleared.
  void SetAppNotLocallyInstalledForTesting(const webapps::AppId& app_id);

 private:
  void CommitUpdate(CommitCallback callback,
                    std::unique_ptr<WebAppRegistryUpdate> update);

  void CheckRegistryUpdateData(const RegistryUpdateData& update_data) const;

  // Update the in-memory model.
  void 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,
                        std::unique_ptr<syncer::MetadataBatch> metadata_batch);

  void EnsureShortcutAppToDiyAppMigration();

  // Update apps that don't have a UserDisplayMode set for the current platform.
  void EnsureAppsHaveUserDisplayModeForCurrentPlatform();
  void EnsurePartiallyInstalledAppsHaveCorrectStatus();
  void OnDataWritten(CommitCallback callback, bool success);
  void OnWebAppUninstallComplete(const webapps::AppId& app,
                                 webapps::UninstallResultCode code);

  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);

  // Returns if the data was parsed.
  ManifestIdParseResult PrepareLocalUpdateFromSyncChange(
      const syncer::EntityChange& change,
      RegistryUpdateData* update_local_data,
      std::vector<webapps::AppId>& apps_display_mode_changed);

  // Update registrar and Install/Uninstall missing/excessive local apps.
  void ApplyIncrementalSyncChangesToRegistrar(
      std::unique_ptr<RegistryUpdateData> update_local_data,
      const std::vector<webapps::AppId>& apps_display_mode_changed);

  void MaybeUninstallAppsPendingUninstall();
  void MaybeInstallAppsFromSyncAndPendingInstallOrSyncOsIntegration();

  std::unique_ptr<WebAppDatabase> database_;
  const raw_ptr<WebAppRegistrarMutable, DanglingUntriaged> registrar_;
  raw_ptr<WebAppCommandManager, AcrossTasksDanglingUntriaged> command_manager_ =
      nullptr;
  raw_ptr<WebAppCommandScheduler, AcrossTasksDanglingUntriaged>
      command_scheduler_ = nullptr;
  raw_ptr<WebAppInstallManager, AcrossTasksDanglingUntriaged> install_manager_ =
      nullptr;

  base::OneShotEvent on_sync_connected_;

  bool is_in_update_ = false;
  bool disable_checks_for_testing_ = false;

  base::WeakPtrFactory<WebAppSyncBridge> weak_ptr_factory_{this};
};

std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app);

void ApplySyncDataToApp(const sync_pb::WebAppSpecifics& sync_data, WebApp* app);

}  // namespace web_app

#endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_SYNC_BRIDGE_H_