1 // Copyright 2018 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_WEB_APPLICATIONS_COMPONENTS_PENDING_APP_MANAGER_H_
6 #define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_PENDING_APP_MANAGER_H_
7 
8 #include <map>
9 #include <memory>
10 #include <ostream>
11 #include <string>
12 #include <vector>
13 
14 #include "base/callback.h"
15 #include "base/containers/flat_map.h"
16 #include "base/memory/weak_ptr.h"
17 #include "chrome/browser/web_applications/components/external_install_options.h"
18 #include "chrome/browser/web_applications/components/web_app_id.h"
19 #include "url/gurl.h"
20 
21 namespace web_app {
22 
23 enum class InstallResultCode;
24 
25 class AppRegistrar;
26 class OsIntegrationManager;
27 class InstallFinalizer;
28 class InstallManager;
29 class WebAppUiManager;
30 
31 enum class RegistrationResultCode { kSuccess, kAlreadyRegistered, kTimeout };
32 
33 // PendingAppManager installs, uninstalls, and updates apps.
34 //
35 // Implementations of this class should perform each set of operations serially
36 // in the order in which they arrive. For example, if an uninstall request gets
37 // queued while an update request for the same app is pending, implementations
38 // should wait for the update request to finish before uninstalling the app.
39 class PendingAppManager {
40  public:
41   using OnceInstallCallback =
42       base::OnceCallback<void(const GURL& app_url, InstallResultCode code)>;
43   using RepeatingInstallCallback =
44       base::RepeatingCallback<void(const GURL& app_url,
45                                    InstallResultCode code)>;
46   using RegistrationCallback =
47       base::RepeatingCallback<void(const GURL& launch_url,
48                                    RegistrationResultCode code)>;
49   using UninstallCallback =
50       base::RepeatingCallback<void(const GURL& app_url, bool succeeded)>;
51   using SynchronizeCallback =
52       base::OnceCallback<void(std::map<GURL, InstallResultCode> install_results,
53                               std::map<GURL, bool> uninstall_results)>;
54 
55   PendingAppManager();
56   PendingAppManager(const PendingAppManager&) = delete;
57   PendingAppManager& operator=(const PendingAppManager&) = delete;
58   virtual ~PendingAppManager();
59 
60   void SetSubsystems(AppRegistrar* registrar,
61                      OsIntegrationManager* os_integration_manager,
62                      WebAppUiManager* ui_manager,
63                      InstallFinalizer* finalizer,
64                      InstallManager* install_manager);
65 
66   // Queues an installation operation with the highest priority. Essentially
67   // installing the app immediately if there are no ongoing operations or
68   // installing the app right after the current operation finishes. Runs its
69   // callback with the URL in |install_options| and with the id of the installed
70   // app or an empty string if the installation fails.
71   //
72   // Fails if the same operation has been queued before. Should only be used in
73   // response to a user action e.g. the user clicked an install button.
74   virtual void Install(ExternalInstallOptions install_options,
75                        OnceInstallCallback callback) = 0;
76 
77   // Adds a task to the queue of operations for each ExternalInstallOptions in
78   // |install_options_list|. Runs |callback| with the URL of the corresponding
79   // ExternalInstallOptions in |install_options_list| and with the id of the
80   // installed app or an empty string if the installation fails. Runs |callback|
81   // for every completed installation - whether or not the installation actually
82   // succeeded.
83   virtual void InstallApps(
84       std::vector<ExternalInstallOptions> install_options_list,
85       const RepeatingInstallCallback& callback) = 0;
86 
87   // Adds a task to the queue of operations for each GURL in
88   // |uninstall_urls|. Runs |callback| with the URL of the corresponding
89   // app in |uninstall_urls| and with a bool indicating whether or not the
90   // uninstall succeeded. Runs |callback| for every completed uninstallation -
91   // whether or not the uninstallation actually succeeded.
92   virtual void UninstallApps(std::vector<GURL> uninstall_urls,
93                              ExternalInstallSource install_source,
94                              const UninstallCallback& callback) = 0;
95 
96   // Installs an app for each ExternalInstallOptions in
97   // |desired_apps_install_options| and uninstalls any apps in
98   // GetInstalledAppUrls(install_source) that are not in
99   // |desired_apps_install_options|'s URLs.
100   //
101   // All apps in |desired_apps_install_options| should have |install_source| as
102   // their source.
103   //
104   // Once all installs/uninstalls are complete, |callback| will be run with the
105   // success/failure status of the synchronization.
106   //
107   // Note that this returns after queueing work (installation and
108   // uninstallation) to be done. It does not wait until that work is complete.
109   void SynchronizeInstalledApps(
110       std::vector<ExternalInstallOptions> desired_apps_install_options,
111       ExternalInstallSource install_source,
112       SynchronizeCallback callback);
113 
114   void SetRegistrationCallbackForTesting(RegistrationCallback callback);
115   void ClearRegistrationCallbackForTesting();
116   void SetRegistrationsCompleteCallbackForTesting(base::OnceClosure callback);
117   void ClearSynchronizeRequestsForTesting();
118 
119   virtual void Shutdown() = 0;
120 
121  protected:
registrar()122   AppRegistrar* registrar() { return registrar_; }
os_integration_manager()123   OsIntegrationManager* os_integration_manager() {
124     return os_integration_manager_;
125   }
ui_manager()126   WebAppUiManager* ui_manager() { return ui_manager_; }
finalizer()127   InstallFinalizer* finalizer() { return finalizer_; }
install_manager()128   InstallManager* install_manager() { return install_manager_; }
129 
130   virtual void OnRegistrationFinished(const GURL& launch_url,
131                                       RegistrationResultCode result);
132 
133   base::OnceClosure registrations_complete_callback_;
134 
135  private:
136   struct SynchronizeRequest {
137     SynchronizeRequest(SynchronizeCallback callback, int remaining_requests);
138     SynchronizeRequest(const SynchronizeRequest&) = delete;
139     SynchronizeRequest& operator=(const SynchronizeRequest&) = delete;
140     ~SynchronizeRequest();
141 
142     SynchronizeRequest& operator=(SynchronizeRequest&&);
143     SynchronizeRequest(SynchronizeRequest&& other);
144 
145     SynchronizeCallback callback;
146     int remaining_requests;
147     std::map<GURL, InstallResultCode> install_results;
148     std::map<GURL, bool> uninstall_results;
149 
150   };
151 
152   void InstallForSynchronizeCallback(ExternalInstallSource source,
153                                      const GURL& app_url,
154                                      InstallResultCode code);
155   void UninstallForSynchronizeCallback(ExternalInstallSource source,
156                                        const GURL& app_url,
157                                        bool succeeded);
158   void OnAppSynchronized(ExternalInstallSource source, const GURL& app_url);
159 
160   AppRegistrar* registrar_ = nullptr;
161   OsIntegrationManager* os_integration_manager_ = nullptr;
162   WebAppUiManager* ui_manager_ = nullptr;
163   InstallFinalizer* finalizer_ = nullptr;
164   InstallManager* install_manager_ = nullptr;
165 
166   base::flat_map<ExternalInstallSource, SynchronizeRequest>
167       synchronize_requests_;
168 
169   RegistrationCallback registration_callback_;
170 
171   base::WeakPtrFactory<PendingAppManager> weak_ptr_factory_{this};
172 
173 };
174 
175 }  // namespace web_app
176 
177 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_PENDING_APP_MANAGER_H_
178