15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/callback_forward.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/weak_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionServiceInterface;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrefService;
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BrowserContext;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For registering, loading, and unloading component extensions.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ComponentLoader {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ComponentLoader(ExtensionServiceInterface* extension_service,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PrefService* prefs,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  PrefService* local_state,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  content::BrowserContext* browser_context);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ComponentLoader();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t registered_extensions_count() const {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return component_extensions_.size();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates and loads all registered component extensions.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LoadAll();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers and possibly loads a component extension. If ExtensionService
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been initialized, the extension is loaded; otherwise, the load is
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deferred until LoadAll is called. The ID of the added extension is
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returned.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Component extension manifests must contain a "key" property with a unique
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // public key, serialized in base64. You can create a suitable value with the
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // following commands on a unixy system:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ssh-keygen -t rsa -b 1024 -N '' -f /tmp/key.pem
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   openssl rsa -pubout -outform DER < /tmp/key.pem 2>/dev/null | base64 -w 0
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Add(const std::string& manifest_contents,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const base::FilePath& root_directory);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method for registering a component extension by resource id.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Add(int manifest_resource_id,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const base::FilePath& root_directory);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads a component extension from file system. Replaces previously added
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension with the same ID.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string AddOrReplace(const base::FilePath& path);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Returns the extension ID of a component extension specified by resource
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // id of its manifest file.
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string GetExtensionID(int manifest_resource_id,
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             const base::FilePath& root_directory);
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if an extension with the specified id has been added.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Exists(const std::string& id) const;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unloads a component extension and removes it from the list of component
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extensions to be loaded.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Remove(const base::FilePath& root_directory);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Remove(const std::string& id);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Call this during test setup to load component extensions that have
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // background pages for testing, which could otherwise interfere with tests.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void EnableBackgroundExtensionsForTesting();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds the default component extensions. If |skip_session_components|
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the loader will skip loading component extensions that weren't supposed to
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // be loaded unless we are in signed user session (ChromeOS). For all other
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // platforms this |skip_session_components| is expected to be unset.
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddDefaultComponentExtensions(bool skip_session_components);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Similar to above but adds the default component extensions for kiosk mode.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddDefaultComponentExtensionsForKioskMode(bool skip_session_components);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the given JSON manifest. Returns NULL if it cannot be parsed, or if
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the result is not a DictionaryValue.
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* ParseManifest(
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& manifest_contents) const;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the list of registered extensions.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearAllRegistered();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reloads a registered component extension.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reload(const std::string& extension_id);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS)
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Calls |done_cb|, if not a null callback, on success.
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // NOTE: |done_cb| is not called if the component loader is shut down
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // during loading.
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void AddChromeVoxExtension(const base::Closure& done_cb);
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string AddChromeOsSpeechSynthesisExtension();
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Information about a registered component extension.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ComponentExtensionInfo {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ComponentExtensionInfo(const base::DictionaryValue* manifest,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const base::FilePath& root_directory);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The parsed contents of the extensions's manifest file.
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* manifest;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Directory where the extension is stored.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath root_directory;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The component extension's ID.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string extension_id;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string Add(const base::DictionaryValue* parsed_manifest,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const base::FilePath& root_directory);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads a registered component extension.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Load(const ComponentExtensionInfo& info);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddDefaultComponentExtensionsWithBackgroundPages(
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool skip_session_components);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddFileManagerExtension();
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void AddVideoPlayerExtension();
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void AddGalleryExtension();
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void AddHangoutServicesExtension();
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddHotwordHelperExtension();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddImageLoaderExtension();
1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  void AddNetworkSpeechSynthesisExtension();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void AddWithNameAndDescription(int manifest_resource_id,
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 const base::FilePath& root_directory,
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 int name_string_id,
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 int description_string_id);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddChromeApp();
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void AddHotwordAudioVerificationApp();
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void AddKeyboardApp();
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void AddWebStoreApp();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unloads |component| from the memory.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UnloadComponent(ComponentExtensionInfo* component);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Enable HTML5 FileSystem for given component extension in Guest mode.
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void EnableFileSystemInGuestMode(const std::string& id);
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_CHROMEOS)
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Used as a reply callback when loading the ChromeVox extension.
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Called with a |chromevox_path| and parsed |manifest| and invokes
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // |done_cb| after adding the extension.
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void AddChromeVoxExtensionWithManifest(
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const base::FilePath& chromevox_path,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const base::Closure& done_cb,
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<base::DictionaryValue> manifest);
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrefService* profile_prefs_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* local_state_;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::BrowserContext* browser_context_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionServiceInterface* extension_service_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // List of registered component extensions (see Manifest::Location).
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<ComponentExtensionInfo> RegisteredComponentExtensions;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisteredComponentExtensions component_extensions_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtrFactory<ComponentLoader> weak_factory_;
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(TtsApiTest, NetworkSpeechEngine);
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(TtsApiTest, NoNetworkSpeechEngineWhenOffline);
1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ComponentLoader);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_COMPONENT_LOADER_H_
187