blob: 7feb344c65618b5440bb6b4cd7a1811baf47ba34 [file] [log] [blame]
// Copyright 2024 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_ACCESSIBILITY_EMBEDDED_A11Y_EXTENSION_LOADER_H_
#define CHROME_BROWSER_ACCESSIBILITY_EMBEDDED_A11Y_EXTENSION_LOADER_H_
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_manager_observer.h"
#include "chrome/browser/profiles/profile_observer.h"
namespace extensions {
class ComponentLoader;
}
class Profile;
///////////////////////////////////////////////////////////////////////////////
// EmbeddedA11yExtensionLoader
//
// A class that manages the installation and uninstallation of the
// Accessibility helper extension on every profile (including guest and
// incognito) for Chrome Accessibility services and features on all platforms
// except Lacros, where it just informs EmbeddedA11yHelperLacros.
//
class EmbeddedA11yExtensionLoader : public ProfileObserver,
public ProfileManagerObserver {
public:
// Simple struct to hold information about each extension installed on all
// profiles.
struct ExtensionInfo {
ExtensionInfo(const std::string& extension_id,
const std::string& extension_path,
const base::FilePath::CharType* extension_manifest_file,
bool should_localize);
ExtensionInfo(const ExtensionInfo& other);
ExtensionInfo(ExtensionInfo&&);
ExtensionInfo& operator=(const ExtensionInfo&);
ExtensionInfo& operator=(ExtensionInfo&&);
~ExtensionInfo();
// The id of the extension.
const std::string extension_id;
// The path to the extension manifest file.
const std::string extension_path;
// The name of the extension manifest file.
const base::FilePath::CharType* extension_manifest_file;
// Whether the extension should be localized or not.
bool should_localize;
};
// Gets the current instance of EmbeddedA11yExtensionLoader. There
// should be one of these across all profiles.
static EmbeddedA11yExtensionLoader* GetInstance();
EmbeddedA11yExtensionLoader();
~EmbeddedA11yExtensionLoader() override;
EmbeddedA11yExtensionLoader(EmbeddedA11yExtensionLoader&) = delete;
EmbeddedA11yExtensionLoader& operator=(EmbeddedA11yExtensionLoader&) = delete;
// Should be called when the browser starts up.
void Init();
// TODO(crbug.com/324143642): Observe the reading mode enabled/disabled state
// in this class instead of informing EmbeddedA11yManagerLacros to
// enable/disable reading mode.
virtual void InstallA11yHelperExtensionForReadingMode();
virtual void RemoveA11yHelperExtensionForReadingMode();
// Install an extension.
// `manifest_name` must live for the duration of the program. (e.g. be
// statically allocated)
void InstallExtensionWithId(const std::string& extension_id,
const std::string& extension_path,
const base::FilePath::CharType* manifest_name,
bool should_localize);
void RemoveExtensionWithId(const std::string& extension_id);
// We can't use extensions::ExtensionHostTestHelper as those require a
// background page, and these extensions do not have background pages.
void AddExtensionChangedCallbackForTest(base::RepeatingClosure callback);
private:
// ProfileObserver:
void OnProfileWillBeDestroyed(Profile* profile) override;
void OnOffTheRecordProfileCreated(Profile* off_the_record) override;
// ProfileManagerObserver:
void OnProfileAdded(Profile* profile) override;
void OnProfileManagerDestroying() override;
void UpdateAllProfiles(const std::string& extension_id);
void UpdateProfile(Profile* profile, const std::string& extension_id);
// Removes the helper extension with `extension_id` from the given `profile`
// if it is installed.
void MaybeRemoveExtension(Profile* profile, const std::string& extension_id);
// Installs the helper extension with `extension_id` from the given `profile`
// if it isn't yet installed.
void MaybeInstallExtension(Profile* profile,
const std::string& extension_id,
const std::string& extension_path,
const base::FilePath::CharType* manifest_name,
bool should_localize);
// Installs the helper extension with the given `extension_id`, `manifest` and
// `path` using the given `component_loader` for some profile.
void InstallExtension(extensions::ComponentLoader* component_loader,
const base::FilePath& path,
const std::string& extension_id,
std::optional<base::Value::Dict> manifest);
bool initialized_ = false;
// A map to store all accessibility helper extensions installed.
std::map<std::string, ExtensionInfo> extension_map_;
base::RepeatingClosure extension_installation_changed_callback_for_test_;
base::ScopedMultiSourceObservation<Profile, ProfileObserver>
observed_profiles_{this};
base::ScopedObservation<ProfileManager, ProfileManagerObserver>
profile_manager_observation_{this};
base::WeakPtrFactory<EmbeddedA11yExtensionLoader> weak_ptr_factory_{this};
friend struct base::DefaultSingletonTraits<EmbeddedA11yExtensionLoader>;
};
#endif // CHROME_BROWSER_ACCESSIBILITY_EMBEDDED_A11Y_EXTENSION_LOADER_H_