1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_ 6 #define EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_ 7 8 #include <memory> 9 10 #include "base/macros.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/weak_ptr.h" 13 #include "extensions/browser/unloaded_extension_reason.h" 14 #include "extensions/common/extension.h" 15 #include "extensions/common/extension_id.h" 16 17 namespace base { 18 class FilePath; 19 } // namespace base 20 21 namespace content { 22 class BrowserContext; 23 class DevToolsAgentHost; 24 } // namespace content 25 26 namespace extensions { 27 28 class Extension; 29 class ExtensionHost; 30 class ExtensionPrefs; 31 class ExtensionRegistry; 32 class ExtensionSystem; 33 class RendererStartupHelper; 34 35 // ExtensionRegistrar drives the stages of registering and unregistering 36 // extensions for a BrowserContext. It uses the ExtensionRegistry to track 37 // extension states. Other classes may query the ExtensionRegistry directly, 38 // but eventually only ExtensionRegistrar will be able to make changes to it. 39 class ExtensionRegistrar { 40 public: 41 // How to surface an extension load error, e.g. showing an error dialog. The 42 // actual behavior is up to the embedder. 43 enum class LoadErrorBehavior { 44 kQuiet = 0, // Just log the error. 45 kNoisy, // Show an error dialog. 46 }; 47 48 // Delegate for embedder-specific functionality like policy and permissions. 49 class Delegate { 50 public: 51 Delegate() = default; 52 virtual ~Delegate() = default; 53 54 // Called before |extension| is added. |old_extension| is the extension 55 // being replaced, in the case of a reload or upgrade. 56 virtual void PreAddExtension(const Extension* extension, 57 const Extension* old_extension) = 0; 58 59 // Handles updating the browser context when an extension is activated 60 // (becomes enabled). 61 virtual void PostActivateExtension( 62 scoped_refptr<const Extension> extension) = 0; 63 64 // Handles updating the browser context when an enabled extension is 65 // deactivated (whether disabled or removed). 66 virtual void PostDeactivateExtension( 67 scoped_refptr<const Extension> extension) = 0; 68 69 // Given an extension ID and/or path, loads that extension as a reload. 70 virtual void LoadExtensionForReload( 71 const ExtensionId& extension_id, 72 const base::FilePath& path, 73 LoadErrorBehavior load_error_behavior) = 0; 74 75 // Returns true if the extension is allowed to be enabled or disabled, 76 // respectively. 77 virtual bool CanEnableExtension(const Extension* extension) = 0; 78 virtual bool CanDisableExtension(const Extension* extension) = 0; 79 80 // Returns true if the extension should be blocked. 81 virtual bool ShouldBlockExtension(const Extension* extension) = 0; 82 83 private: 84 DISALLOW_COPY_AND_ASSIGN(Delegate); 85 }; 86 87 // The provided Delegate should outlive this object. 88 ExtensionRegistrar(content::BrowserContext* browser_context, 89 Delegate* delegate); 90 virtual ~ExtensionRegistrar(); 91 92 // Adds the extension to the ExtensionRegistry. The extension will be added to 93 // the enabled, disabled, blocklisted or blocked set. If the extension is 94 // added as enabled, it will be activated. 95 void AddExtension(scoped_refptr<const Extension> extension); 96 97 // Removes |extension| from the extension system by deactivating it if it is 98 // enabled and removing references to it from the ExtensionRegistry's 99 // enabled or disabled sets. 100 // Note: Extensions will not be removed from other sets (terminated, 101 // blocklisted or blocked). ExtensionService handles that, since it also adds 102 // it to those sets. TODO(michaelpg): Make ExtensionRegistrar the sole mutator 103 // of ExtensionRegsitry to simplify this usage. 104 void RemoveExtension(const ExtensionId& extension_id, 105 UnloadedExtensionReason reason); 106 107 // If the extension is disabled, marks it as enabled and activates it for use. 108 // Otherwise, simply updates the ExtensionPrefs. (Blocklisted or blocked 109 // extensions cannot be enabled.) 110 void EnableExtension(const ExtensionId& extension_id); 111 112 // Marks |extension| as disabled and deactivates it. The ExtensionRegistry 113 // retains a reference to it, so it can be enabled later. 114 void DisableExtension(const ExtensionId& extension_id, int disable_reasons); 115 116 // Attempts to reload the specified extension by disabling it if it is enabled 117 // and requesting the Delegate load it again. 118 // NOTE: Reloading an extension can invalidate |extension_id| and Extension 119 // pointers for the given extension. Consider making a copy of |extension_id| 120 // first and retrieving a new Extension pointer afterwards. 121 void ReloadExtension(const ExtensionId extension_id, 122 LoadErrorBehavior load_error_behavior); 123 124 // TODO(michaelpg): Add methods for blocklisting and blocking extensions. 125 126 // Deactivates the extension, adding its id to the list of terminated 127 // extensions. 128 void TerminateExtension(const ExtensionId& extension_id); 129 130 // Removes the extension from the terminated list. TODO(michaelpg): Make a 131 // private implementation detail when no longer called from ExtensionService. 132 void UntrackTerminatedExtension(const ExtensionId& extension_id); 133 134 // Returns true if the extension is enabled (including terminated), or if it 135 // is not loaded but isn't explicitly disabled in preferences. 136 bool IsExtensionEnabled(const ExtensionId& extension_id) const; 137 138 // Called after the render view for the background page with the associated 139 // host is created. 140 void DidCreateRenderViewForBackgroundPage(ExtensionHost* host); 141 142 void OnUnpackedExtensionReloadFailed(const base::FilePath& path); 143 144 private: 145 // Adds the extension to the appropriate registry set, based on ExtensionPrefs 146 // and our |delegate_|. Activates the extension if it's added to the enabled 147 // set. 148 void AddNewExtension(scoped_refptr<const Extension> extension); 149 150 // Activates |extension| by marking it enabled and notifying other components 151 // about it. 152 void ActivateExtension(const Extension* extension, bool is_newly_added); 153 154 // Triggers the unloaded notifications to deactivate an extension. 155 void DeactivateExtension(const Extension* extension, 156 UnloadedExtensionReason reason); 157 158 // Given an extension that was disabled for reloading, completes the reload 159 // by replacing the old extension with the new version and enabling it. 160 // Returns true on success. 161 bool ReplaceReloadedExtension(scoped_refptr<const Extension> extension); 162 163 // Marks the extension ready after URLRequestContexts have been updated on 164 // the IO thread. 165 void OnExtensionRegisteredWithRequestContexts( 166 scoped_refptr<const Extension> extension); 167 168 // Upon reloading an extension, spins up its lazy background page if 169 // necessary. 170 void MaybeSpinUpLazyBackgroundPage(const Extension* extension); 171 172 content::BrowserContext* const browser_context_; 173 174 // Delegate provided in the constructor. Should outlive this object. 175 Delegate* const delegate_; 176 177 // Keyed services we depend on. Cached here for repeated access. 178 ExtensionSystem* const extension_system_; 179 ExtensionPrefs* const extension_prefs_; 180 ExtensionRegistry* const registry_; 181 RendererStartupHelper* const renderer_helper_; 182 183 // Map of DevToolsAgentHost instances that are detached, 184 // waiting for an extension to be reloaded. 185 using OrphanedDevTools = 186 std::map<std::string, scoped_refptr<content::DevToolsAgentHost>>; 187 OrphanedDevTools orphaned_dev_tools_; 188 189 // Map unloaded extensions' ids to their paths. When a temporarily loaded 190 // extension is unloaded, we lose the information about it and don't have 191 // any in the extension preferences file. 192 using UnloadedExtensionPathMap = std::map<ExtensionId, base::FilePath>; 193 UnloadedExtensionPathMap unloaded_extension_paths_; 194 195 // Store the ids of reloading extensions. We use this to re-enable extensions 196 // which were disabled for a reload. 197 ExtensionIdSet reloading_extensions_; 198 199 // Store the paths of extensions that failed to reload. We use this to retry 200 // reload. 201 std::set<base::FilePath> failed_to_reload_unpacked_extensions_; 202 203 base::WeakPtrFactory<ExtensionRegistrar> weak_factory_{this}; 204 205 DISALLOW_COPY_AND_ASSIGN(ExtensionRegistrar); 206 }; 207 208 } // namespace extensions 209 210 #endif // EXTENSIONS_BROWSER_EXTENSION_REGISTRAR_H_ 211