1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNCABLE_SERVICE_H_
6 #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNCABLE_SERVICE_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <string>
12 #include <unordered_map>
13 
14 #include "base/macros.h"
15 #include "chrome/browser/sync/glue/sync_start_util.h"
16 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
17 #include "components/keyed_service/core/keyed_service.h"
18 #include "components/sync/model/sync_change.h"
19 #include "components/sync/model/sync_change_processor.h"
20 #include "components/sync/model/sync_error_factory.h"
21 #include "components/sync/model/syncable_service.h"
22 #include "components/sync/protocol/arc_package_specifics.pb.h"
23 
24 class Profile;
25 
26 namespace content {
27 class BrowserContext;
28 }  // namespace content
29 
30 namespace arc {
31 
32 // Class that syncs ARC pakcages install/uninstall.
33 class ArcPackageSyncableService : public syncer::SyncableService,
34                                   public KeyedService,
35                                   public ArcAppListPrefs::Observer {
36  public:
37   struct SyncItem {
38     SyncItem(const std::string& package_name,
39              int32_t package_version,
40              int64_t last_backup_android_id,
41              int64_t last_backup_time);
42     const std::string package_name;
43     int32_t package_version;
44     int64_t last_backup_android_id;
45     int64_t last_backup_time;
46   };
47 
48   ~ArcPackageSyncableService() override;
49 
50   static ArcPackageSyncableService* Create(Profile* profile,
51                                            ArcAppListPrefs* prefs);
52   static ArcPackageSyncableService* Get(content::BrowserContext* context);
53 
54   // Returns true if requested package has pending sync request.
55   bool IsPackageSyncing(const std::string& package_name) const;
56 
57   // syncer::SyncableService:
58   void WaitUntilReadyToSync(base::OnceClosure done) override;
59   base::Optional<syncer::ModelError> MergeDataAndStartSyncing(
60       syncer::ModelType type,
61       const syncer::SyncDataList& initial_sync_data,
62       std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
63       std::unique_ptr<syncer::SyncErrorFactory> error_handler) override;
64   void StopSyncing(syncer::ModelType type) override;
65   base::Optional<syncer::ModelError> ProcessSyncChanges(
66       const base::Location& from_here,
67       const syncer::SyncChangeList& change_list) override;
68 
69   bool SyncStarted();
70 
71  private:
72   using SyncItemMap =
73       std::unordered_map<std::string, std::unique_ptr<SyncItem>>;
74 
75   ArcPackageSyncableService(Profile* profile, ArcAppListPrefs* prefs);
76 
77   // ArcAppListPrefs::Observer:
78   void OnPackageInstalled(const mojom::ArcPackageInfo& package_info) override;
79   void OnPackageModified(const mojom::ArcPackageInfo& package_info) override;
80   void OnPackageRemoved(const std::string& package_name,
81                         bool uninstalled) override;
82   void OnPackageListInitialRefreshed() override;
83 
84   // Sends adds/updates sync change to sync server.
85   void SendSyncChange(
86       const mojom::ArcPackageInfo& package_info,
87       const syncer::SyncChange::SyncChangeType& sync_change_type);
88 
89   // Creates or updates local syncItem with data change from sync server. Sends
90   // request to install/update package to Android.
91   bool ProcessSyncItemSpecifics(const sync_pb::ArcPackageSpecifics& specifics);
92 
93   // Deletes local syncItem corresponding to data change from sync server.
94   // Sends request to uninstall package to Android.
95   bool DeleteSyncItemSpecifics(const sync_pb::ArcPackageSpecifics& specifics);
96 
97   // Sends install notification for given package to Android.
98   void InstallPackage(const SyncItem* sync_item);
99 
100   // Sends uninstall notification for given package to Android.
101   void UninstallPackage(const SyncItem* sync_item);
102 
103   // Returns if a package should be synced.
104   // TODO(lgcheng@) Support may need to be added in this function for different
105   // use cases.
106   bool ShouldSyncPackage(const std::string& package_name) const;
107 
108   Profile* const profile_;
109   base::OnceClosure wait_until_ready_to_sync_cb_;
110   std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
111   std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler_;
112 
113   // Items which are synced.
114   SyncItemMap sync_items_;
115 
116   // Items new from sync service, waiting for confirmation of installation.
117   // These items may never be approved for installation and this structure is
118   // used to ensure syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
119   // returns consistent results from different devices.
120   // API to re-install pending_install_items_ can be created when needed.
121   SyncItemMap pending_install_items_;
122 
123   // Items to delete from sync service, waiting for confirmation of
124   // uninstallation. These items will no longer be counted in
125   // syncer::SyncDataList GetAllSyncData(syncer::ModelType type).
126   // API to re-uninstall pending_uninstall_items_ can be created when needed.
127   SyncItemMap pending_uninstall_items_;
128 
129   // Run()ning tells sync to try and start soon, because syncable changes
130   // have started happening. It will cause sync to call us back
131   // asynchronously via MergeDataAndStartSyncing as soon as possible.
132   syncer::SyncableService::StartSyncFlare flare_;
133 
134   ArcAppListPrefs* const prefs_;
135 
136   DISALLOW_COPY_AND_ASSIGN(ArcPackageSyncableService);
137 };
138 
139 }  // namespace arc
140 
141 #endif  // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNCABLE_SERVICE_H_
142