| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef EXTENSIONS_BROWSER_PENDING_EXTENSION_MANAGER_H_ |
| #define EXTENSIONS_BROWSER_PENDING_EXTENSION_MANAGER_H_ |
| |
| #include <list> |
| #include <map> |
| #include <optional> |
| #include <string> |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "components/keyed_service/core/keyed_service.h" |
| #include "extensions/browser/pending_extension_info.h" |
| #include "extensions/common/extension_id.h" |
| #include "extensions/common/manifest.h" |
| #include "third_party/blink/public/mojom/manifest/manifest.mojom-shared.h" |
| |
| class GURL; |
| |
| namespace base { |
| class Version; |
| } |
| |
| namespace content { |
| class BrowserContext; |
| } |
| |
| namespace extensions { |
| FORWARD_DECLARE_TEST(ExtensionServiceTest, |
| UpdatePendingExtensionAlreadyInstalled); |
| |
| class PendingExtensionManager; |
| |
| class ExtensionUpdaterTest; |
| void SetupPendingExtensionManagerForTest( |
| int count, |
| const GURL& update_url, |
| PendingExtensionManager* pending_extension_manager); |
| |
| // Class PendingExtensionManager manages the set of extensions which are |
| // being installed or updated. In general, installation and updates take |
| // time, because they involve downloading, unpacking, and installing. |
| // This class allows us to avoid race cases where multiple sources install |
| // the same extension. |
| // The ExtensionService creates an instance of this class, and manages its |
| // lifetime. This class should only be used from the UI thread. |
| class PendingExtensionManager : public KeyedService { |
| public: |
| // Observer of changes in the PendingExtensionManager state |
| class Observer : public base::CheckedObserver { |
| public: |
| // Called when an extension is added to the pending list. |
| // |
| // This means the extension with the given `id` is currently being |
| // installed or updated. |
| virtual void OnExtensionAdded(const std::string& id) {} |
| |
| // Called when an extension is removed from the pending list. |
| // |
| // This means the extension with the given `id` is no longer being installed |
| // or updated. Note that this doesn't mean the operation actually succeeded. |
| // It just means the operation on this extenison is no longer taking place |
| // (ie, pending completion). |
| virtual void OnExtensionRemoved(const std::string& id) {} |
| }; |
| |
| explicit PendingExtensionManager(content::BrowserContext* context); |
| |
| PendingExtensionManager(const PendingExtensionManager&) = delete; |
| PendingExtensionManager& operator=(const PendingExtensionManager&) = delete; |
| |
| ~PendingExtensionManager() override; |
| |
| // Returns the instance for the given `browser_context`. |
| static PendingExtensionManager* Get(content::BrowserContext* browser_context); |
| |
| // TODO(skerner): Many of these methods can be private once code in |
| // ExtensionService is moved into methods of this class. |
| |
| // Remove extension with id `id` from the set of pending extensions. Returns |
| // true if such an extension was found and removed, false otherwise. |
| bool Remove(const std::string& id); |
| |
| // Get the information for a pending extension. Returns a pointer to the |
| // pending extension with id `id`, or NULL if there is no such extension. |
| const PendingExtensionInfo* GetById(const std::string& id) const; |
| |
| // Is `id` in the set of pending extensions? |
| bool IsIdPending(const std::string& id) const; |
| |
| // Returns true if there are any extensions pending. |
| bool HasPendingExtensions() const; |
| |
| // Whether there is pending extension install from sync. |
| bool HasPendingExtensionFromSync() const; |
| |
| // Whether there is a high-priority pending extension (one from either policy |
| // or an external component extension). |
| bool HasHighPriorityPendingExtension() const; |
| |
| // Adds an extension in a pending state; the extension with the |
| // given info will be installed on the next auto-update cycle. |
| // Return true if the extension was added. Will return false |
| // if the extension is pending from another source which overrides |
| // sync installs (such as a policy extension) or if the extension |
| // is already installed. |
| // After installation, the extension will be granted permissions iff |
| // `version` is valid and matches the actual installed version. |
| bool AddFromSync( |
| const std::string& id, |
| const GURL& update_url, |
| const base::Version& version, |
| PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install, |
| bool remote_install); |
| |
| // Adds an extension that was depended on by another extension. |
| bool AddFromExtensionImport( |
| const std::string& id, |
| const GURL& update_url, |
| PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install); |
| |
| // Given an extension id and an update URL, schedule the extension |
| // to be fetched, installed, and activated. |
| bool AddFromExternalUpdateUrl(const std::string& id, |
| const std::string& install_parameter, |
| const GURL& update_url, |
| mojom::ManifestLocation location, |
| int creation_flags, |
| bool mark_acknowledged); |
| |
| // Add a pending extension record for an external CRX file. |
| // Return true if the CRX should be installed, false if an existing |
| // pending record overrides it. |
| bool AddFromExternalFile(const std::string& id, |
| mojom::ManifestLocation location, |
| const base::Version& version, |
| int creation_flags, |
| bool mark_acknowledged); |
| |
| // Get the list of pending IDs that should be installed from an update URL. |
| // Pending extensions that will be installed from local files will not be |
| // included in the set. |
| std::list<std::string> GetPendingIdsForUpdateCheck() const; |
| |
| // Adds an observer to the observer list. |
| void AddObserver(Observer* observer); |
| |
| // Removes an observer from the observer list. |
| void RemoveObserver(Observer* observer); |
| |
| private: |
| // Assumes an extension with id `id` is not already installed. |
| // Return true if the extension was added. |
| bool AddExtensionImpl( |
| const std::string& id, |
| const std::string& install_parameter, |
| const GURL& update_url, |
| const base::Version& version, |
| PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install, |
| bool is_from_sync, |
| mojom::ManifestLocation install_source, |
| int creation_flags, |
| bool mark_acknowledged, |
| bool remote_install); |
| |
| // Add a pending extension record directly. Used for unit tests that need |
| // to set an inital state. Use friendship to allow the tests to call this |
| // method. |
| void AddForTesting(PendingExtensionInfo pending_extension_info); |
| |
| // Adds the given key and value to the pending_extensions_ map. |
| // Do it only via this method to ensure observers are consistently |
| // notified. |
| void AddToMap(const std::string& id, PendingExtensionInfo info); |
| |
| // The BrowserContext with which the manager is associated. |
| raw_ptr<content::BrowserContext, DanglingUntriaged> context_; |
| |
| std::map<std::string, PendingExtensionInfo> pending_extensions_; |
| |
| base::ObserverList<Observer> observers_; |
| |
| FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest, |
| UpdatePendingExtensionAlreadyInstalled); |
| friend class ExtensionUpdaterTest; |
| friend void SetupPendingExtensionManagerForTest( |
| int count, |
| const GURL& update_url, |
| PendingExtensionManager* pending_extension_manager); |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_BROWSER_PENDING_EXTENSION_MANAGER_H_ |