blob: e3d226e09726cef692875826c5a3a7ebe0b7e6bd [file] [log] [blame]
// Copyright 2018 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_EXTERNALLY_MANAGED_APP_MANAGER_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_EXTERNALLY_MANAGED_APP_MANAGER_H_
#include <map>
#include <memory>
#include <ostream>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/web_applications/external_install_options.h"
#include "chrome/browser/web_applications/web_app_id.h"
#include "url/gurl.h"
namespace webapps {
enum class InstallResultCode;
}
namespace web_app {
class FullSystemLock;
class WebAppInstallFinalizer;
class WebAppCommandScheduler;
class WebAppUiManager;
enum class RegistrationResultCode { kSuccess, kAlreadyRegistered, kTimeout };
// ExternallyManagedAppManager installs, uninstalls, and updates apps that are
// externally managed. This means that they are not installed by the user, but
// instead through a different system (enterprise installs, device default
// installs, etc). See ExternalInstallSource for all of the different externally
// managed app types. Typically there is one "manager" class per externally
// managed app type that figures out the list of apps to have installed, and
// that class will call SynchronizeApps for a given external install type.
//
// Implementations of this class should perform each set of operations serially
// in the order in which they arrive. For example, if an uninstall request gets
// queued while an update request for the same app is pending, implementations
// should wait for the update request to finish before uninstalling the app.
//
// This class also supports installing a "placeholder" app by the
// |install_placeholder| in ExternalInstallOptions. This placeholder app is
// installed if the install url given fails to fully load so a manifest cannot
// be resolved, and a placeholder app is installed instead. Every time the user
// navigates a page, if that page is ever a URL that a placeholder app is
// 'holding' (as the app failed to load originally), then the install is
// re-initiated, and if successful, the placeholder app is removed.
class ExternallyManagedAppManager {
public:
struct InstallResult {
InstallResult();
explicit InstallResult(webapps::InstallResultCode code,
absl::optional<AppId> app_id = absl::nullopt,
bool did_uninstall_and_replace = false);
InstallResult(const InstallResult&);
~InstallResult();
bool operator==(const InstallResult& other) const;
webapps::InstallResultCode code;
absl::optional<AppId> app_id;
bool did_uninstall_and_replace = false;
};
using OnceInstallCallback =
base::OnceCallback<void(const GURL& install_url, InstallResult result)>;
using RepeatingInstallCallback =
base::RepeatingCallback<void(const GURL& install_url,
InstallResult result)>;
using RegistrationCallback =
base::RepeatingCallback<void(const GURL& launch_url,
RegistrationResultCode code)>;
using UninstallCallback =
base::RepeatingCallback<void(const GURL& install_url, bool succeeded)>;
using SynchronizeCallback = base::OnceCallback<void(
std::map<GURL /*install_url*/, InstallResult> install_results,
std::map<GURL /*install_url*/, bool /*succeeded*/> uninstall_results)>;
ExternallyManagedAppManager();
ExternallyManagedAppManager(const ExternallyManagedAppManager&) = delete;
ExternallyManagedAppManager& operator=(const ExternallyManagedAppManager&) =
delete;
virtual ~ExternallyManagedAppManager();
void SetSubsystems(WebAppUiManager* ui_manager,
WebAppInstallFinalizer* finalizer,
WebAppCommandScheduler* command_scheduler);
// Queues an installation operation with the highest priority. Essentially
// installing the app immediately if there are no ongoing operations or
// installing the app right after the current operation finishes. Runs its
// callback with the URL in |install_options| and with the id of the installed
// app or an empty string if the installation fails.
//
// Fails if the same operation has been queued before. Should only be used in
// response to a user action e.g. the user clicked an install button.
virtual void InstallNow(ExternalInstallOptions install_options,
OnceInstallCallback callback) = 0;
// Queues an installation operation the end of current tasks. Runs its
// callback with the URL in |install_options| and with the id of the installed
// app or an empty string if the installation fails.
//
// Fails if the same operation has been queued before.
virtual void Install(ExternalInstallOptions install_options,
OnceInstallCallback callback) = 0;
// Adds a task to the queue of operations for each ExternalInstallOptions in
// |install_options_list|. Runs |callback| with the URL of the corresponding
// ExternalInstallOptions in |install_options_list| and with the id of the
// installed app or an empty string if the installation fails. Runs |callback|
// for every completed installation - whether or not the installation actually
// succeeded.
virtual void InstallApps(
std::vector<ExternalInstallOptions> install_options_list,
const RepeatingInstallCallback& callback) = 0;
// Adds a task to the queue of operations for each GURL in
// |uninstall_urls|. Runs |callback| with the URL of the corresponding
// app in |uninstall_urls| and with a bool indicating whether or not the
// uninstall succeeded. Runs |callback| for every completed uninstallation -
// whether or not the uninstallation actually succeeded.
virtual void UninstallApps(std::vector<GURL> uninstall_urls,
ExternalInstallSource install_source,
const UninstallCallback& callback) = 0;
// Installs an app for each ExternalInstallOptions in
// |desired_apps_install_options| and uninstalls any apps in
// GetInstalledAppUrls(install_source) that are not in
// |desired_apps_install_options|'s URLs.
//
// All apps in |desired_apps_install_options| should have |install_source| as
// their source.
//
// Once all installs/uninstalls are complete, |callback| will be run with the
// success/failure status of the synchronization.
//
// Note that this returns after queueing work (installation and
// uninstallation) to be done. It does not wait until that work is complete.
void SynchronizeInstalledApps(
std::vector<ExternalInstallOptions> desired_apps_install_options,
ExternalInstallSource install_source,
SynchronizeCallback callback);
void SetRegistrationCallbackForTesting(RegistrationCallback callback);
void ClearRegistrationCallbackForTesting();
void SetRegistrationsCompleteCallbackForTesting(base::OnceClosure callback);
void ClearSynchronizeRequestsForTesting();
virtual void Shutdown() = 0;
protected:
WebAppUiManager* ui_manager() { return ui_manager_; }
WebAppInstallFinalizer* finalizer() { return finalizer_; }
WebAppCommandScheduler* command_scheduler() { return command_scheduler_; }
virtual void OnRegistrationFinished(const GURL& launch_url,
RegistrationResultCode result);
base::OnceClosure registrations_complete_callback_;
private:
struct SynchronizeRequest {
SynchronizeRequest(SynchronizeCallback callback,
std::vector<ExternalInstallOptions> pending_installs,
int remaining_uninstall_requests);
SynchronizeRequest(const SynchronizeRequest&) = delete;
SynchronizeRequest& operator=(const SynchronizeRequest&) = delete;
~SynchronizeRequest();
SynchronizeRequest& operator=(SynchronizeRequest&&);
SynchronizeRequest(SynchronizeRequest&& other);
SynchronizeCallback callback;
int remaining_install_requests;
std::vector<ExternalInstallOptions> pending_installs;
int remaining_uninstall_requests;
std::map<GURL, InstallResult> install_results;
std::map<GURL, bool> uninstall_results;
};
void SynchronizeInstalledAppsOnLockAcquired(
std::vector<ExternalInstallOptions> desired_apps_install_options,
ExternalInstallSource install_source,
SynchronizeCallback callback,
FullSystemLock& lock);
void InstallForSynchronizeCallback(
ExternalInstallSource source,
const GURL& install_url,
ExternallyManagedAppManager::InstallResult result);
void UninstallForSynchronizeCallback(ExternalInstallSource source,
const GURL& install_url,
bool succeeded);
void ContinueOrCompleteSynchronization(ExternalInstallSource source);
raw_ptr<WebAppUiManager, DanglingUntriaged> ui_manager_ = nullptr;
raw_ptr<WebAppInstallFinalizer> finalizer_ = nullptr;
raw_ptr<WebAppCommandScheduler, DanglingUntriaged> command_scheduler_ =
nullptr;
base::flat_map<ExternalInstallSource, SynchronizeRequest>
synchronize_requests_;
RegistrationCallback registration_callback_;
base::WeakPtrFactory<ExternallyManagedAppManager> weak_ptr_factory_{this};
};
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_EXTERNALLY_MANAGED_APP_MANAGER_H_