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_SYSTEM_WEB_APP_MANAGER_H_
6 #define CHROME_BROWSER_WEB_APPLICATIONS_SYSTEM_WEB_APP_MANAGER_H_
7 
8 #include <map>
9 #include <memory>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "base/callback_forward.h"
15 #include "base/containers/flat_map.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/one_shot_event.h"
18 #include "chrome/browser/web_applications/components/pending_app_manager.h"
19 #include "chrome/browser/web_applications/components/web_application_info.h"
20 #include "components/prefs/pref_change_registrar.h"
21 #include "ui/gfx/geometry/size.h"
22 #include "url/gurl.h"
23 #include "url/origin.h"
24 
25 namespace base {
26 class Version;
27 }
28 
29 namespace content {
30 class NavigationHandle;
31 }
32 
33 namespace user_prefs {
34 class PrefRegistrySyncable;
35 }
36 
37 class PrefService;
38 class Profile;
39 
40 namespace web_app {
41 
42 class WebAppUiManager;
43 class OsIntegrationManager;
44 class AppRegistryController;
45 
46 // An enum that lists the different System Apps that exist. Can be used to
47 // retrieve the App ID from the underlying Web App system.
48 enum class SystemAppType {
49   SETTINGS,
50   CAMERA,
51   TERMINAL,
52   MEDIA,
53   HELP,
54   PRINT_MANAGEMENT,
55   SCANNING,
56   DIAGNOSTICS,
57   CONNECTIVITY_DIAGNOSTICS,
58 #if !defined(OFFICIAL_BUILD)
59   FILE_MANAGER,
60   TELEMETRY,
61   SAMPLE,
62 #endif  // !defined(OFFICIAL_BUILD)
63 
64   // When adding a new System App, add a corresponding histogram suffix in
65   // WebAppSystemAppInternalName (histograms.xml). The suffix name should match
66   // the App's |internal_name|. This is for reporting per-app install results.
67 };
68 
69 using OriginTrialsMap = std::map<url::Origin, std::vector<std::string>>;
70 using WebApplicationInfoFactory =
71     base::RepeatingCallback<std::unique_ptr<WebApplicationInfo>()>;
72 
73 // The configuration options for a System App.
74 struct SystemAppInfo {
75   SystemAppInfo(const std::string& internal_name, const GURL& install_url);
76   // When installing via a WebApplicationInfo, the url is never loaded. It's
77   // needed only for various legacy reasons, maps for tracking state, and
78   // generating the AppId and things of that nature.
79   SystemAppInfo(const std::string& internal_name,
80                 const GURL& install_url,
81                 const WebApplicationInfoFactory& info_factory);
82   SystemAppInfo(const SystemAppInfo& other);
83   ~SystemAppInfo();
84 
85   // A developer-friendly name for, among other things, reporting metrics and
86   // interacting with tast tests. It should follow PascalCase convention, and
87   // have a corresponding entry in WebAppSystemAppInternalName histogram
88   // suffixes. The internal name shouldn't be changed afterwards.
89   std::string internal_name;
90 
91   // The URL that the System App will be installed from.
92   GURL install_url;
93 
94   // If specified, the apps in |uninstall_and_replace| will have their data
95   // migrated to this System App.
96   std::vector<AppId> uninstall_and_replace;
97 
98   // Minimum window size in DIPs. Empty if the app does not have a minimum.
99   // TODO(https://github.com/w3c/manifest/issues/436): Replace with PWA manifest
100   // properties for window size.
101   gfx::Size minimum_window_size;
102 
103   // If set, we allow only a single window for this app.
104   bool single_window = true;
105 
106   // If set, when the app is launched through the File Handling Web API, we will
107   // include the file's directory in window.launchQueue as the first value.
108   bool include_launch_directory = false;
109 
110   // Map from origin to enabled origin trial names for this app. For example,
111   // "chrome://sample-web-app/" to ["Frobulate"]. If set, we will enable the
112   // given origin trials when the corresponding origin is loaded in the app.
113   OriginTrialsMap enabled_origin_trials;
114 
115   // Resource Ids for additional search terms.
116   std::vector<int> additional_search_terms;
117 
118   // If set to false, this app will be hidden from the Chrome OS app launcher.
119   bool show_in_launcher = true;
120 
121   // If set to false, this app will be hidden from the Chrome OS search.
122   bool show_in_search = true;
123 
124   // If set to true, navigations (e.g. Omnibox URL, anchor link) to this app
125   // will open in the app's window instead of the navigation's context (e.g.
126   // browser tab).
127   bool capture_navigations = false;
128 
129   WebApplicationInfoFactory app_info_factory;
130 };
131 
132 // Installs, uninstalls, and updates System Web Apps.
133 // System Web Apps are built-in, highly-privileged Web Apps for Chrome OS. They
134 // have access to more APIs and are part of the Chrome OS image.
135 class SystemWebAppManager {
136  public:
137   // Policy for when the SystemWebAppManager will update apps/install new apps.
138   enum class UpdatePolicy {
139     // Update every system start.
140     kAlwaysUpdate,
141     // Update when the Chrome version number changes.
142     kOnVersionChange,
143   };
144 
145   static constexpr char kInstallResultHistogramName[] =
146       "Webapp.InstallResult.System";
147   static constexpr char kInstallDurationHistogramName[] =
148       "Webapp.SystemApps.FreshInstallDuration";
149 
150   // Returns whether the given app type is enabled.
151   static bool IsAppEnabled(SystemAppType type);
152 
153   explicit SystemWebAppManager(Profile* profile);
154   SystemWebAppManager(const SystemWebAppManager&) = delete;
155   SystemWebAppManager& operator=(const SystemWebAppManager&) = delete;
156   virtual ~SystemWebAppManager();
157 
158   void SetSubsystems(PendingAppManager* pending_app_manager,
159                      AppRegistrar* registrar,
160                      AppRegistryController* registry_controller,
161                      WebAppUiManager* ui_manager,
162                      OsIntegrationManager* os_integration_manager);
163 
164   void Start();
165 
166   // The SystemWebAppManager is disabled in browser tests by default because it
167   // pollutes the startup state (several tests expect the Extensions state to be
168   // clean).
169   //
170   // Call this to install apps for SystemWebApp specific tests, e.g if a test
171   // needs to open OS Settings.
172   //
173   // This can also be called multiple times to simulate reinstallation from
174   // system restart, e.g.
175   void InstallSystemAppsForTesting();
176 
177   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
178 
179   // Returns the app id for the given System App |type|.
180   base::Optional<AppId> GetAppIdForSystemApp(SystemAppType type) const;
181 
182   // Returns the System App Type for the given |app_id|.
183   base::Optional<SystemAppType> GetSystemAppTypeForAppId(AppId app_id) const;
184 
185   // Returns the App Ids for all installed System Web Apps.
186   std::vector<AppId> GetAppIds() const;
187 
188   // Returns whether |app_id| points to an installed System App.
189   bool IsSystemWebApp(const AppId& app_id) const;
190 
191   // Returns whether the given System App |type| should use a single window.
192   bool IsSingleWindow(SystemAppType type) const;
193 
194   // Returns whether the given System App |type| should get launch directory in
195   // launch parameter.
196   bool AppShouldReceiveLaunchDirectory(SystemAppType type) const;
197 
198   // Perform tab-specific setup when a navigation in a System Web App is about
199   // to be committed.
200   void OnReadyToCommitNavigation(const AppId& app_id,
201                                  content::NavigationHandle* navigation_handle);
202 
203   // Returns terms to be used when searching for the app.
204   std::vector<std::string> GetAdditionalSearchTerms(SystemAppType type) const;
205 
206   // Returns whether the app should be shown in the launcher.
207   bool ShouldShowInLauncher(SystemAppType type) const;
208 
209   // Returns whether the app should be shown in search.
210   bool ShouldShowInSearch(SystemAppType type) const;
211 
212   // Returns the SystemAppType that should capture the navigation to |url|.
213   base::Optional<SystemAppType> GetCapturingSystemAppForURL(
214       const GURL& url) const;
215 
216   // Returns the minimum window size for |app_id| or an empty size if the app
217   // doesn't specify a minimum.
218   gfx::Size GetMinimumWindowSize(const AppId& app_id) const;
219 
220   // Returns a map of registered system app types and infos, these apps will be
221   // installed on the system.
222   const base::flat_map<SystemAppType, SystemAppInfo>&
223   GetRegisteredSystemAppsForTesting() const;
224 
on_apps_synchronized()225   const base::OneShotEvent& on_apps_synchronized() const {
226     return *on_apps_synchronized_;
227   }
228 
229   // This call will override default System Apps configuration. You should call
230   // Start() after this call to install |system_apps|.
231   void SetSystemAppsForTesting(
232       base::flat_map<SystemAppType, SystemAppInfo> system_apps);
233 
234   // Overrides the update policy. If AlwaysReinstallSystemWebApps feature is
235   // enabled, this method does nothing, and system apps will be reinstalled.
236   void SetUpdatePolicyForTesting(UpdatePolicy policy);
237 
238   void ResetOnAppsSynchronizedForTesting();
239 
240   // Updates each system app either disabled/not disabled.
241   void OnAppsPolicyChanged();
242 
243   void Shutdown();
244 
245  protected:
246   virtual const base::Version& CurrentVersion() const;
247   virtual const std::string& CurrentLocale() const;
248 
249  private:
250   // Returns the list of origin trials to enable for |url| loaded in System App
251   // |type|. Returns nullptr if the App does not specify origin trials for
252   // |url|.
253   const std::vector<std::string>* GetEnabledOriginTrials(SystemAppType type,
254                                                          const GURL& url);
255 
256   bool AppHasFileHandlingOriginTrial(SystemAppType type);
257 
258   void OnAppsSynchronized(bool did_force_install_apps,
259                           const base::TimeTicks& install_start_time,
260                           std::map<GURL, InstallResultCode> install_results,
261                           std::map<GURL, bool> uninstall_results);
262   bool ShouldForceInstallApps() const;
263   void UpdateLastAttemptedInfo();
264   // Returns if we have exceeded the number of retry attempts allowed for this
265   // version.
266   bool CheckAndIncrementRetryAttempts();
267 
268   void RecordSystemWebAppInstallResults(
269       const std::map<GURL, InstallResultCode>& install_results) const;
270 
271   void RecordSystemWebAppInstallDuration(
272       const base::TimeDelta& time_duration) const;
273 
274   Profile* profile_;
275 
276   std::unique_ptr<base::OneShotEvent> on_apps_synchronized_;
277 
278   bool shutting_down_ = false;
279 
280   std::string install_result_per_profile_histogram_name_;
281 
282   UpdatePolicy update_policy_;
283 
284   base::flat_map<SystemAppType, SystemAppInfo> system_app_infos_;
285 
286   base::flat_map<AppId, SystemAppType> app_id_to_app_type_;
287 
288   PrefService* const pref_service_;
289 
290   // Used to install, uninstall, and update apps. Should outlive this class.
291   PendingAppManager* pending_app_manager_ = nullptr;
292 
293   AppRegistrar* registrar_ = nullptr;
294 
295   AppRegistryController* registry_controller_ = nullptr;
296 
297   WebAppUiManager* ui_manager_ = nullptr;
298 
299   OsIntegrationManager* os_integration_manager_ = nullptr;
300 
301   PrefChangeRegistrar local_state_pref_change_registrar_;
302 
303   base::WeakPtrFactory<SystemWebAppManager> weak_ptr_factory_{this};
304 
305 };
306 
307 }  // namespace web_app
308 
309 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_SYSTEM_WEB_APP_MANAGER_H_
310