|  | // Copyright 2020 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_OS_INTEGRATION_OS_INTEGRATION_MANAGER_H_ | 
|  | #define CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_OS_INTEGRATION_MANAGER_H_ | 
|  |  | 
|  | #include <bitset> | 
|  | #include <memory> | 
|  | #include <optional> | 
|  | #include <string_view> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/functional/callback_forward.h" | 
|  | #include "base/memory/raw_ptr.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/types/pass_key.h" | 
|  | #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h" | 
|  | #include "chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h" | 
|  | #include "chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h" | 
|  | #include "chrome/browser/web_applications/os_integration/web_app_run_on_os_login.h" | 
|  | #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h" | 
|  | #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" | 
|  | #include "chrome/browser/web_applications/web_app.h" | 
|  | #include "chrome/browser/web_applications/web_app_constants.h" | 
|  | #include "chrome/browser/web_applications/web_app_install_info.h" | 
|  | #include "components/custom_handlers/protocol_handler.h" | 
|  | #include "components/pref_registry/pref_registry_syncable.h" | 
|  | #include "components/services/app_service/public/cpp/file_handler.h" | 
|  | #include "components/webapps/common/web_app_id.h" | 
|  |  | 
|  | class Profile; | 
|  | class ScopedProfileKeepAlive; | 
|  |  | 
|  | namespace web_app { | 
|  |  | 
|  | class FakeOsIntegrationManager; | 
|  | class WebAppProvider; | 
|  | class WebAppProfileDeletionManager; | 
|  |  | 
|  | using ShortcutLocationCallback = | 
|  | base::OnceCallback<void(ShortcutLocations shortcut_locations)>; | 
|  |  | 
|  | // Returns the ShortcutInfo for an app. | 
|  | using GetShortcutInfoCallback = | 
|  | base::OnceCallback<void(std::unique_ptr<ShortcutInfo>)>; | 
|  |  | 
|  | // OsIntegrationManager is responsible of creating/updating/deleting | 
|  | // all OS hooks during Web App lifecycle. | 
|  | // It contains individual OS integration managers and takes | 
|  | // care of inter-dependencies among them. | 
|  | class OsIntegrationManager { | 
|  | public: | 
|  | using UpdateShortcutsForAllAppsCallback = | 
|  | base::RepeatingCallback<void(Profile*, base::OnceClosure)>; | 
|  |  | 
|  | // Used to suppress OS hooks during this object's lifetime. | 
|  | class ScopedSuppressForTesting { | 
|  | public: | 
|  | ScopedSuppressForTesting(); | 
|  | ~ScopedSuppressForTesting(); | 
|  | }; | 
|  | static bool AreOsHooksSuppressedForTesting(); | 
|  |  | 
|  | static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); | 
|  |  | 
|  | // Sets a callback to be called when this class determines that all shortcuts | 
|  | // for a particular profile need to be rebuild, for example because the app | 
|  | // shortcut version has changed since the last time these were created. | 
|  | // This is used by the legacy extensions based app code in | 
|  | // chrome/browser/web_applications/extensions to ensure those app shortcuts | 
|  | // also get updated. Calling out to that code directly would violate | 
|  | // dependency layering. | 
|  | static void SetUpdateShortcutsForAllAppsCallback( | 
|  | UpdateShortcutsForAllAppsCallback callback); | 
|  |  | 
|  | static base::OnceClosure& OnSetCurrentAppShortcutsVersionCallbackForTesting(); | 
|  |  | 
|  | OsIntegrationManager( | 
|  | Profile* profile, | 
|  | std::unique_ptr<WebAppFileHandlerManager> file_handler_manager, | 
|  | std::unique_ptr<WebAppProtocolHandlerManager> protocol_handler_manager); | 
|  | virtual ~OsIntegrationManager(); | 
|  |  | 
|  | // Sets internal WebAppProvider reference and threads it through to all sub | 
|  | // managers. | 
|  | virtual void SetProvider(base::PassKey<WebAppProvider>, | 
|  | WebAppProvider& provider); | 
|  |  | 
|  | virtual void Start(); | 
|  |  | 
|  | // Start OS Integration synchronization from external callsites. This should | 
|  | // be the only point of call into OsIntegrationManager from external places | 
|  | // after the OS integration sub managers have been implemented. | 
|  | virtual void Synchronize( | 
|  | const webapps::AppId& app_id, | 
|  | base::OnceClosure callback, | 
|  | std::optional<SynchronizeOsOptions> options = std::nullopt); | 
|  |  | 
|  | // Asynchronously gathers existing shortcut locations according to | 
|  | // `shortcut_info`, the results of which will be passed into `callback`. | 
|  | // Virtual for testing. | 
|  | virtual void GetAppExistingShortCutLocation( | 
|  | ShortcutLocationCallback callback, | 
|  | std::unique_ptr<ShortcutInfo> shortcut_info); | 
|  |  | 
|  | // Asynchronously gets the information required to create a shortcut for | 
|  | // `app_id` from the WebAppRegistrar along with the icon bitmaps. Do note that | 
|  | // this information is obtained from fields other than the web app's | 
|  | // `current_os_integration_state_` field, so there is still a slight chance | 
|  | // that the information returned from the registrar might not match the web | 
|  | // app's current OS integration state (for example if this API is triggered in | 
|  | // between the registrar being updated and OS integration being completed). | 
|  | // | 
|  | // If ShortcutInfo creation requires using the current OS integration state of | 
|  | // the web_app, prefer calling `web_app::BuildShortcutInfoWithoutFavicon()` | 
|  | // instead. | 
|  | virtual void GetShortcutInfoForAppFromRegistrar( | 
|  | const webapps::AppId& app_id, | 
|  | GetShortcutInfoCallback callback); | 
|  |  | 
|  | // Proxy calls for WebAppFileHandlerManager. | 
|  | bool IsFileHandlingAPIAvailable(const webapps::AppId& app_id); | 
|  | const apps::FileHandlers* GetEnabledFileHandlers( | 
|  | const webapps::AppId& app_id) const; | 
|  |  | 
|  | // Proxy calls for WebAppProtocolHandlerManager. | 
|  | virtual std::optional<GURL> TranslateProtocolUrl(const webapps::AppId& app_id, | 
|  | const GURL& protocol_url); | 
|  | std::vector<custom_handlers::ProtocolHandler> GetAppProtocolHandlers( | 
|  | const webapps::AppId& app_id) const; | 
|  | virtual std::vector<custom_handlers::ProtocolHandler> | 
|  | GetAllowedHandlersForProtocol(const std::string& protocol); | 
|  | virtual std::vector<custom_handlers::ProtocolHandler> | 
|  | GetDisallowedHandlersForProtocol(const std::string& protocol); | 
|  |  | 
|  | WebAppFileHandlerManager& file_handler_manager() { | 
|  | return *file_handler_manager_; | 
|  | } | 
|  |  | 
|  | WebAppProtocolHandlerManager& protocol_handler_manager_for_testing(); | 
|  |  | 
|  | virtual FakeOsIntegrationManager* AsTestOsIntegrationManager(); | 
|  |  | 
|  | void SetForceUnregisterCalledForTesting( | 
|  | base::RepeatingCallback<void(const webapps::AppId&)> on_force_unregister); | 
|  |  | 
|  | // If a profile is marked for deletion, remove all OS integration for an app | 
|  | // installed for that profile. | 
|  | void UnregisterOsIntegrationOnProfileMarkedForDeletion( | 
|  | base::PassKey<WebAppProfileDeletionManager>, | 
|  | const webapps::AppId& app_id); | 
|  |  | 
|  | protected: | 
|  | WebAppProtocolHandlerManager* protocol_handler_manager() { | 
|  | return protocol_handler_manager_.get(); | 
|  | } | 
|  | bool has_file_handler_manager() { return !!file_handler_manager_; } | 
|  | void set_file_handler_manager( | 
|  | std::unique_ptr<WebAppFileHandlerManager> file_handler_manager) { | 
|  | file_handler_manager_ = std::move(file_handler_manager); | 
|  | } | 
|  | void set_protocol_handler_manager( | 
|  | std::unique_ptr<WebAppProtocolHandlerManager> protocol_handler_manager) { | 
|  | protocol_handler_manager_ = std::move(protocol_handler_manager); | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Synchronize: | 
|  | void StartSubManagerExecutionIfRequired( | 
|  | const webapps::AppId& app_id, | 
|  | std::optional<SynchronizeOsOptions> options, | 
|  | std::unique_ptr<proto::os_state::WebAppOsIntegration> desired_states, | 
|  | base::OnceClosure on_all_execution_done); | 
|  |  | 
|  | // Use to call Execute() on each sub manager recursively through callbacks | 
|  | // so as to ensure that execution happens serially in the order the sub | 
|  | // managers are stored inside the sub_managers_ vector, and that consecutive | 
|  | // sub managers execute only if the one before it has finished executing. | 
|  | void ExecuteNextSubmanager( | 
|  | const webapps::AppId& app_id, | 
|  | std::optional<SynchronizeOsOptions> options, | 
|  | proto::os_state::WebAppOsIntegration* desired_state, | 
|  | const proto::os_state::WebAppOsIntegration current_state, | 
|  | size_t index, | 
|  | base::OnceClosure on_all_execution_done_db_write); | 
|  |  | 
|  | void WriteStateToDB( | 
|  | const webapps::AppId& app_id, | 
|  | std::unique_ptr<proto::os_state::WebAppOsIntegration> desired_states, | 
|  | base::OnceClosure callback); | 
|  |  | 
|  | // Called when ForceUnregisterOsIntegrationSubManager has finished | 
|  | // unregistering sub managers. `keep_alive` is reset to allow the | 
|  | // profile to be deleted. | 
|  | void SubManagersUnregistered( | 
|  | const webapps::AppId& app_id, | 
|  | std::unique_ptr<ScopedProfileKeepAlive> keep_alive); | 
|  |  | 
|  | // Used to call ForceUnregister() on all sub managers to remove | 
|  | // any OS integrations from the OS. This runs synchronously in the order that | 
|  | // the sub managers are stored inside the sub_managers_ vector. | 
|  | void ForceUnregisterOsIntegrationOnSubManager( | 
|  | const webapps::AppId& app_id, | 
|  | size_t index, | 
|  | base::OnceClosure final_callback); | 
|  |  | 
|  | // Schedules a call to UpdateShortcutsForAllAppsNow() if kAppShortcutsVersion | 
|  | // in prefs is less than kCurrentAppShortcutsVersion. | 
|  | void UpdateShortcutsForAllAppsIfNeeded(); | 
|  | void UpdateShortcutsForAllAppsNow(); | 
|  | void SetCurrentAppShortcutsVersion(); | 
|  |  | 
|  | void OnIconsRead(const webapps::AppId& app_id, | 
|  | GetShortcutInfoCallback callback, | 
|  | std::map<SquareSizePx, SkBitmap> icon_bitmaps); | 
|  |  | 
|  | std::unique_ptr<ShortcutInfo> BuildShortcutInfoForWebApp(const WebApp* app); | 
|  |  | 
|  | const raw_ptr<Profile> profile_; | 
|  | raw_ptr<WebAppProvider> provider_ = nullptr; | 
|  |  | 
|  | std::unique_ptr<WebAppFileHandlerManager> file_handler_manager_; | 
|  | std::unique_ptr<WebAppProtocolHandlerManager> protocol_handler_manager_; | 
|  |  | 
|  | std::vector<std::unique_ptr<OsIntegrationSubManager>> sub_managers_; | 
|  | bool set_provider_called_ = false; | 
|  | bool first_synchronize_called_ = false; | 
|  |  | 
|  | base::RepeatingCallback<void(const webapps::AppId&)> | 
|  | force_unregister_callback_for_testing_ = base::DoNothing(); | 
|  |  | 
|  | base::WeakPtrFactory<OsIntegrationManager> weak_ptr_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace web_app | 
|  |  | 
|  | #endif  // CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_OS_INTEGRATION_MANAGER_H_ |