blob: 17a26f02c282bcc0dc9097eadbb0290ba7162017 [file] [log] [blame]
// Copyright 2021 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_ASH_SYSTEM_EXTENSIONS_SYSTEM_EXTENSIONS_INSTALL_MANAGER_H_
#define CHROME_BROWSER_ASH_SYSTEM_EXTENSIONS_SYSTEM_EXTENSIONS_INSTALL_MANAGER_H_
#include <map>
#include "base/files/file_path.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/one_shot_event.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequence_bound.h"
#include "chrome/browser/ash/system_extensions/system_extensions_install_status.h"
#include "chrome/browser/ash/system_extensions/system_extensions_sandboxed_unpacker.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
class Profile;
namespace ash {
class SystemExtensionsPersistentStorage;
class SystemExtensionsRegistry;
class SystemExtensionsRegistryManager;
class SystemExtensionsServiceWorkerManager;
class SystemExtensionsInstallManager {
public:
// Observer for installation and uninstallation steps events. This should be
// used for classes that need to perform an action in response to an
// installation step.
// TODO(b/241308071): Once it's implemented, suggest using
// SystemExtensionsRegistry::Observer for clients that only care about when
// a System Extension is installed or uninstalled.
class Observer : public base::CheckedObserver {
public:
virtual void OnSystemExtensionAssetsDeleted(
const SystemExtensionId& system_extension_id,
bool succeeded) {}
};
SystemExtensionsInstallManager(
Profile* profile,
SystemExtensionsRegistryManager& registry_manager,
SystemExtensionsRegistry& registry,
SystemExtensionsServiceWorkerManager& service_worker_manager,
SystemExtensionsPersistentStorage& persistent_storage);
SystemExtensionsInstallManager(const SystemExtensionsInstallManager&) =
delete;
SystemExtensionsInstallManager& operator=(
const SystemExtensionsInstallManager&) = delete;
~SystemExtensionsInstallManager();
void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
void RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
using OnceInstallCallback =
base::OnceCallback<void(InstallStatusOrSystemExtensionId)>;
void InstallUnpackedExtensionFromDir(
const base::FilePath& unpacked_system_extension_dir,
OnceInstallCallback final_callback);
// Event that signals when a System Extension is installed from the command
// line. Signals even if the System Extension failed to be installed, but
// doesn't if there were no command line arguments to install.
const base::OneShotEvent& on_command_line_install_finished() {
return on_command_line_install_finished_;
}
// Event that signals when all System Extensions that were persisted in a
// previous session are registered.
const base::OneShotEvent& on_register_previously_persisted_finished() {
return on_register_previously_persisted_finished_;
}
// Uninstallation always succeeds.
//
// Currently only two operations can fail, unregistering the Service Worker,
// and deleting the System Extension's assets. Regardless of these operations
// failing, the System Extension will be considered uninstalled. Both of these
// failure cases will be handled by a garbage collector outside of this class.
// TODO(b/241198799): Change this comment once the garbage collector is
// implemented.
void Uninstall(const SystemExtensionId& system_extension_id);
private:
// Helper class to run blocking IO operations on a separate thread.
class IOHelper {
public:
bool CopyExtensionAssets(const base::FilePath& unpacked_extension_dir,
const base::FilePath& dest_dir,
const base::FilePath& system_extensions_dir);
bool RemoveExtensionAssets(const base::FilePath& system_extension_dir);
};
void RegisterPreviouslyPersistedSystemExtensions();
void InstallFromCommandLineIfNecessary();
void OnInstallFromCommandLineFinished(
InstallStatusOrSystemExtensionId result);
void StartInstallation(OnceInstallCallback final_callback,
const base::FilePath& unpacked_system_extension_dir);
void OnGetSystemExtensionFromDir(
OnceInstallCallback final_callback,
const base::FilePath& unpacked_system_extension_dir,
InstallStatusOrSystemExtension result);
void OnAssetsCopiedToProfileDir(OnceInstallCallback final_callback,
SystemExtension system_extension,
bool did_succeed);
void RegisterSystemExtension(SystemExtension system_extension);
void RegisterServiceWorker(const SystemExtensionId& id);
void DispatchWindowManagerStartEvent(const SystemExtensionId& id,
int64_t version_id,
int process_id,
int thread_id);
void NotifyServiceWorkerRegistered(
const SystemExtensionId& id,
blink::ServiceWorkerStatusCode status_code);
void NotifyServiceWorkerUnregistered(const SystemExtensionId& id,
bool succeeded);
void NotifyAssetsRemoved(const SystemExtensionId&, bool succeeded);
// Safe because this class is owned by SystemExtensionsProvider which is owned
// by the profile.
raw_ptr<Profile> profile_;
// Safe to hold references because the parent class,
// SystemExtensionsProvider, ensures this class is constructed after and
// destroyed before the classes below.
const raw_ref<SystemExtensionsServiceWorkerManager> service_worker_manager_;
const raw_ref<SystemExtensionsRegistryManager> registry_manager_;
const raw_ref<SystemExtensionsRegistry> registry_;
const raw_ref<SystemExtensionsPersistentStorage> persistent_storage_;
std::map<SystemExtensionId, SystemExtension> system_extensions_;
base::OneShotEvent on_command_line_install_finished_;
base::OneShotEvent on_register_previously_persisted_finished_;
SystemExtensionsSandboxedUnpacker sandboxed_unpacker_;
base::ObserverList<Observer> observers_;
base::SequenceBound<IOHelper> io_helper_{
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
base::TaskPriority::USER_VISIBLE})};
base::WeakPtrFactory<SystemExtensionsInstallManager> weak_ptr_factory_{this};
};
} // namespace ash
#endif // CHROME_BROWSER_ASH_SYSTEM_EXTENSIONS_SYSTEM_EXTENSIONS_INSTALL_MANAGER_H_