1 // Copyright (c) 2012 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 CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/callback_forward.h" 15 #include "base/files/file_path.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/macros.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/optional.h" 21 #include "base/values.h" 22 #include "build/build_config.h" 23 #include "chrome/common/buildflags.h" 24 25 class Profile; 26 27 namespace extensions { 28 29 class Extension; 30 class ExtensionSystem; 31 32 // For registering, loading, and unloading component extensions. 33 class ComponentLoader { 34 public: 35 ComponentLoader(ExtensionSystem* extension_system, Profile* browser_context); 36 virtual ~ComponentLoader(); 37 registered_extensions_count()38 size_t registered_extensions_count() const { 39 return component_extensions_.size(); 40 } 41 42 // Creates and loads all registered component extensions. 43 void LoadAll(); 44 45 // Registers and possibly loads a component extension. If ExtensionService 46 // has been initialized, the extension is loaded; otherwise, the load is 47 // deferred until LoadAll is called. The ID of the added extension is 48 // returned. 49 // 50 // Component extension manifests must contain a "key" property with a unique 51 // public key, serialized in base64. You can create a suitable value with the 52 // following commands on a unixy system: 53 // 54 // ssh-keygen -t rsa -b 1024 -N '' -f /tmp/key.pem 55 // openssl rsa -pubout -outform DER < /tmp/key.pem 2>/dev/null | base64 -w 0 56 std::string Add(const base::StringPiece& manifest_contents, 57 const base::FilePath& root_directory); 58 59 // Convenience method for registering a component extension by resource id. 60 std::string Add(int manifest_resource_id, 61 const base::FilePath& root_directory); 62 63 // Loads a component extension from file system. Replaces previously added 64 // extension with the same ID. 65 std::string AddOrReplace(const base::FilePath& path); 66 67 // Returns true if an extension with the specified id has been added. 68 bool Exists(const std::string& id) const; 69 70 // Unloads a component extension and removes it from the list of component 71 // extensions to be loaded. 72 void Remove(const base::FilePath& root_directory); 73 void Remove(const std::string& id); 74 75 // Call this during test setup to load component extensions that have 76 // background pages for testing, which could otherwise interfere with tests. 77 static void EnableBackgroundExtensionsForTesting(); 78 79 // Adds the default component extensions. If |skip_session_components| 80 // the loader will skip loading component extensions that weren't supposed to 81 // be loaded unless we are in signed user session (ChromeOS). For all other 82 // platforms this |skip_session_components| is expected to be unset. 83 void AddDefaultComponentExtensions(bool skip_session_components); 84 85 // Similar to above but adds the default component extensions for kiosk mode. 86 void AddDefaultComponentExtensionsForKioskMode(bool skip_session_components); 87 88 // Reloads a registered component extension. 89 void Reload(const std::string& extension_id); 90 91 // Return ids of all registered extensions. 92 std::vector<std::string> GetRegisteredComponentExtensionsIds() const; 93 94 #if defined(OS_CHROMEOS) 95 // Add a component extension from a specific directory. Assumes that the 96 // extension uses a different manifest file when this is a guest session 97 // and that the manifest file lives in |root_directory|. Calls |done_cb| 98 // on success, unless the component loader is shut down during loading. 99 void AddComponentFromDir( 100 const base::FilePath& root_directory, 101 const char* extension_id, 102 const base::Closure& done_cb); 103 104 // Identical to above except allows for the caller to supply the name of the 105 // manifest file. 106 void AddComponentFromDirWithManifestFilename( 107 const base::FilePath& root_directory, 108 const char* extension_id, 109 const base::FilePath::CharType* manifest_file_name, 110 const base::FilePath::CharType* guest_manifest_file_name, 111 const base::Closure& done_cb); 112 113 // Add a component extension from a specific directory. Assumes that the 114 // extension's manifest file lives in |root_directory| and its name is 115 // 'manifest.json'. |name_string| and |description_string| are used to 116 // localize component extension's name and description text exclusively. 117 void AddWithNameAndDescriptionFromDir(const base::FilePath& root_directory, 118 const char* extension_id, 119 const std::string& name_string, 120 const std::string& description_string); 121 122 void AddChromeOsSpeechSynthesisExtensions(); 123 #endif 124 set_ignore_allowlist_for_testing(bool value)125 void set_ignore_allowlist_for_testing(bool value) { 126 ignore_allowlist_for_testing_ = value; 127 } 128 129 private: 130 FRIEND_TEST_ALL_PREFIXES(ComponentLoaderTest, ParseManifest); 131 132 // Information about a registered component extension. 133 struct ComponentExtensionInfo { 134 ComponentExtensionInfo( 135 std::unique_ptr<base::DictionaryValue> manifest_param, 136 const base::FilePath& root_directory); 137 ~ComponentExtensionInfo(); 138 139 ComponentExtensionInfo(ComponentExtensionInfo&& other); 140 ComponentExtensionInfo& operator=(ComponentExtensionInfo&& other); 141 142 // The parsed contents of the extensions's manifest file. 143 std::unique_ptr<base::DictionaryValue> manifest; 144 145 // Directory where the extension is stored. 146 base::FilePath root_directory; 147 148 // The component extension's ID. 149 std::string extension_id; 150 151 private: 152 DISALLOW_COPY_AND_ASSIGN(ComponentExtensionInfo); 153 }; 154 155 // Parses the given JSON manifest. Returns nullptr if it cannot be parsed or 156 // if the result is not a DictionaryValue. 157 std::unique_ptr<base::DictionaryValue> ParseManifest( 158 base::StringPiece manifest_contents) const; 159 160 std::string Add(const base::StringPiece& manifest_contents, 161 const base::FilePath& root_directory, 162 bool skip_allowlist); 163 std::string Add(std::unique_ptr<base::DictionaryValue> parsed_manifest, 164 const base::FilePath& root_directory, 165 bool skip_allowlist); 166 167 // Loads a registered component extension. 168 void Load(const ComponentExtensionInfo& info); 169 170 void AddDefaultComponentExtensionsWithBackgroundPages( 171 bool skip_session_components); 172 void AddDefaultComponentExtensionsWithBackgroundPagesForKioskMode(); 173 174 #if BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) 175 void AddHangoutServicesExtension(); 176 #endif // BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) 177 178 void AddNetworkSpeechSynthesisExtension(); 179 180 void AddWithNameAndDescription(int manifest_resource_id, 181 const base::FilePath& root_directory, 182 const std::string& name_string, 183 const std::string& description_string); 184 void AddWebStoreApp(); 185 186 #if defined(OS_CHROMEOS) 187 void AddChromeApp(); 188 void AddFileManagerExtension(); 189 void AddVideoPlayerExtension(); 190 void AddAudioPlayerExtension(); 191 void AddGalleryExtension(); 192 void AddImageLoaderExtension(); 193 void AddKeyboardApp(); 194 void AddChromeCameraApp(); 195 void AddZipArchiverExtension(); 196 #endif // defined(OS_CHROMEOS) 197 198 scoped_refptr<const Extension> CreateExtension( 199 const ComponentExtensionInfo& info, std::string* utf8_error); 200 201 // Unloads |component| from the memory. 202 void UnloadComponent(ComponentExtensionInfo* component); 203 204 #if defined(OS_CHROMEOS) 205 // Used as a reply callback by |AddComponentFromDir|. 206 // Called with a |root_directory| and parsed |manifest| and invokes 207 // |done_cb| after adding the extension. 208 void FinishAddComponentFromDir( 209 const base::FilePath& root_directory, 210 const char* extension_id, 211 const base::Optional<std::string>& name_string, 212 const base::Optional<std::string>& description_string, 213 const base::Closure& done_cb, 214 std::unique_ptr<base::DictionaryValue> manifest); 215 216 // Finishes loading an extension tts engine. 217 void FinishLoadSpeechSynthesisExtension(const char* extension_id); 218 #endif 219 220 Profile* profile_; 221 222 ExtensionSystem* extension_system_; 223 224 // List of registered component extensions (see Manifest::Location). 225 typedef std::vector<ComponentExtensionInfo> RegisteredComponentExtensions; 226 RegisteredComponentExtensions component_extensions_; 227 228 bool ignore_allowlist_for_testing_; 229 230 base::WeakPtrFactory<ComponentLoader> weak_factory_{this}; 231 232 friend class TtsApiTest; 233 234 DISALLOW_COPY_AND_ASSIGN(ComponentLoader); 235 }; 236 237 } // namespace extensions 238 239 #endif // CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_ 240