summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/component_loader.cc
diff options
context:
space:
mode:
authordubroy@chromium.org <dubroy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-18 14:40:02 +0000
committerdubroy@chromium.org <dubroy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-18 14:40:02 +0000
commit25ae0154d995ac643a1e61d43107ba10e2ee55ec (patch)
tree99545fea59a9c2d6eece030917b884e7967d1dd9 /chrome/browser/extensions/component_loader.cc
parent3b0836d46ed49b74e52fdaa32d4b7b9545b10b2e (diff)
downloadchromium_src-25ae0154d995ac643a1e61d43107ba10e2ee55ec.zip
chromium_src-25ae0154d995ac643a1e61d43107ba10e2ee55ec.tar.gz
chromium_src-25ae0154d995ac643a1e61d43107ba10e2ee55ec.tar.bz2
Add policies to specify an enterprise web store.
Admins can specify the URL, name, and icon to be used for the enterprise web store. The app itself is implemented as a component extension, with some of the manifest values being specified by policy. BUG=88464 TEST=New ComponentLoaderTest class added to unit_tests. Additional manual testing: set "EnterpriseWebStoreURL" policy to a valid URL and start up Chrome. Verify that there is an app on the new tab page that links to the specified URL. If possible, try installing an extension from somewhere on that URL, and ensure that no warning is shown before showing the permission dialog. Review URL: http://codereview.chromium.org/8477005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110698 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions/component_loader.cc')
-rw-r--r--chrome/browser/extensions/component_loader.cc286
1 files changed, 170 insertions, 116 deletions
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 624befa..87b48d7 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -9,10 +9,16 @@
#include "base/json/json_value_serializer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/prefs/pref_notifier.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
#include "grit/browser_resources.h"
#include "ui/base/resource/resource_bundle.h"
@@ -20,41 +26,19 @@
#include "chrome/browser/defaults.h"
#endif
-namespace {
-
-typedef std::list<std::pair<FilePath::StringType, int> >
- ComponentExtensionList;
-
-#if defined(FILE_MANAGER_EXTENSION)
-void AddFileManagerExtension(ComponentExtensionList* component_extensions) {
-#ifndef NDEBUG
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
- FilePath filemgr_extension_path =
- command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath);
- component_extensions->push_back(std::make_pair(
- filemgr_extension_path.value(),
- IDR_FILEMANAGER_MANIFEST));
- return;
- }
-#endif // NDEBUG
- component_extensions->push_back(std::make_pair(
- FILE_PATH_LITERAL("file_manager"),
- IDR_FILEMANAGER_MANIFEST));
-}
-#endif // defined(FILE_MANAGER_EXTENSION)
-
-} // namespace
-
namespace extensions {
-bool ComponentLoader::ComponentExtensionInfo::Equals(
- const ComponentExtensionInfo& other) const {
- return other.manifest == manifest && other.root_directory == root_directory;
-}
+ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
+ PrefService* prefs,
+ PrefService* local_state)
+ : prefs_(prefs),
+ local_state_(local_state),
+ extension_service_(extension_service) {
+ pref_change_registrar_.Init(prefs);
-ComponentLoader::ComponentLoader(ExtensionService* extension_service)
- : extension_service_(extension_service) {
+ // This pref is set by policy. We have to watch it for change because on
+ // ChromeOS, policy isn't loaded until after the browser process is started.
+ pref_change_registrar_.Add(prefs::kEnterpriseWebStoreURL, this);
}
ComponentLoader::~ComponentLoader() {
@@ -68,23 +52,60 @@ void ComponentLoader::LoadAll() {
}
}
+DictionaryValue* ComponentLoader::ParseManifest(
+ const std::string& manifest_contents) const {
+ JSONStringValueSerializer serializer(manifest_contents);
+ scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
+
+ if (!manifest.get() || !manifest->IsType(Value::TYPE_DICTIONARY)) {
+ LOG(ERROR) << "Failed to parse extension manifest.";
+ return NULL;
+ }
+ // Transfer ownership to the caller.
+ return static_cast<DictionaryValue*>(manifest.release());
+}
+
+const Extension* ComponentLoader::Add(
+ int manifest_resource_id,
+ const FilePath& root_directory) {
+ std::string manifest_contents =
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ manifest_resource_id).as_string();
+ return Add(manifest_contents, root_directory);
+}
+
+const Extension* ComponentLoader::Add(
+ std::string& manifest_contents,
+ const FilePath& root_directory) {
+ // The Value is kept for the lifetime of the ComponentLoader. This is
+ // required in case LoadAll() is called again.
+ DictionaryValue* manifest = ParseManifest(manifest_contents);
+ if (manifest)
+ return Add(manifest, root_directory);
+ return NULL;
+}
+
const Extension* ComponentLoader::Add(
- const std::string& manifest, const FilePath& root_directory) {
- ComponentExtensionInfo info(manifest, root_directory);
- Register(info);
+ const DictionaryValue* parsed_manifest,
+ const FilePath& root_directory) {
+ // Get the absolute path to the extension.
+ FilePath absolute_path(root_directory);
+ if (!absolute_path.IsAbsolute()) {
+ if (PathService::Get(chrome::DIR_RESOURCES, &absolute_path)) {
+ absolute_path = absolute_path.Append(root_directory);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ ComponentExtensionInfo info(parsed_manifest, absolute_path);
+ component_extensions_.push_back(info);
if (extension_service_->is_ready())
return Load(info);
return NULL;
}
const Extension* ComponentLoader::Load(const ComponentExtensionInfo& info) {
- JSONStringValueSerializer serializer(info.manifest);
- scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
- if (!manifest.get()) {
- LOG(ERROR) << "Failed to parse manifest for extension";
- return NULL;
- }
-
int flags = Extension::REQUIRE_KEY;
if (Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT))
flags |= Extension::STRICT_ERROR_CHECKS;
@@ -92,7 +113,7 @@ const Extension* ComponentLoader::Load(const ComponentExtensionInfo& info) {
scoped_refptr<const Extension> extension(Extension::Create(
info.root_directory,
Extension::COMPONENT,
- *static_cast<DictionaryValue*>(manifest.get()),
+ *info.manifest,
flags,
&error));
if (!extension.get()) {
@@ -103,19 +124,29 @@ const Extension* ComponentLoader::Load(const ComponentExtensionInfo& info) {
return extension;
}
-void ComponentLoader::Remove(const std::string& manifest_str) {
- // Unload the extension.
- JSONStringValueSerializer serializer(manifest_str);
- scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
- if (!manifest.get()) {
- LOG(ERROR) << "Failed to parse manifest for extension";
- return;
+void ComponentLoader::Remove(const FilePath& root_directory) {
+ // Find the ComponentExtensionInfo for the extension.
+ RegisteredComponentExtensions::iterator it = component_extensions_.begin();
+ for (; it != component_extensions_.end(); ++it) {
+ if (it->root_directory == root_directory)
+ break;
}
+ // If the extension is not in the list, there's nothing to do.
+ if (it == component_extensions_.end())
+ return;
+
+ const DictionaryValue* manifest = it->manifest;
+
+ // Remove the extension from the list of registered extensions.
+ *it = component_extensions_.back();
+ component_extensions_.pop_back();
+
+ // Determine the extension id and unload the extension.
std::string public_key;
std::string public_key_bytes;
std::string id;
- if (!static_cast<DictionaryValue*>(manifest.get())->
- GetString(extension_manifest_keys::kPublicKey, &public_key) ||
+ if (!manifest->GetString(
+ extension_manifest_keys::kPublicKey, &public_key) ||
!Extension::ParsePEMKeyBytes(public_key, &public_key_bytes) ||
!Extension::GenerateId(public_key_bytes, &id)) {
LOG(ERROR) << "Failed to get extension id";
@@ -123,106 +154,129 @@ void ComponentLoader::Remove(const std::string& manifest_str) {
}
extension_service_->
UnloadExtension(id, extension_misc::UNLOAD_REASON_DISABLE);
+}
- // Unregister the extension.
- RegisteredComponentExtensions new_component_extensions;
- for (RegisteredComponentExtensions::iterator it =
- component_extensions_.begin();
- it != component_extensions_.end(); ++it) {
- if (it->manifest != manifest_str)
- new_component_extensions.push_back(*it);
+void ComponentLoader::AddFileManagerExtension() {
+#if defined(FILE_MANAGER_EXTENSION)
+#ifndef NDEBUG
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
+ FilePath filemgr_extension_path(
+ command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath));
+ Add(IDR_FILEMANAGER_MANIFEST, filemgr_extension_path);
+ return;
}
- component_extensions_.swap(new_component_extensions);
+#endif // NDEBUG
+ Add(IDR_FILEMANAGER_MANIFEST, FilePath(FILE_PATH_LITERAL("file_manager")));
+#endif // defined(FILE_MANAGER_EXTENSION)
}
-// We take ComponentExtensionList:
-// path, manifest ID => full manifest, absolute path
-void ComponentLoader::AddDefaultComponentExtensions() {
- ComponentExtensionList component_extensions;
+void ComponentLoader::AddOrReloadEnterpriseWebStore() {
+ FilePath path(FILE_PATH_LITERAL("enterprise_web_store"));
- // Bookmark manager.
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("bookmark_manager"),
- IDR_BOOKMARKS_MANIFEST));
+ // Remove the extension if it was already loaded.
+ Remove(path);
+
+ std::string enterprise_webstore_url =
+ prefs_->GetString(prefs::kEnterpriseWebStoreURL);
+
+ // Load the extension only if the URL preference is set.
+ if (!enterprise_webstore_url.empty()) {
+ std::string manifest_contents =
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_ENTERPRISE_WEBSTORE_MANIFEST).as_string();
+
+ // The manifest is missing some values that are provided by policy.
+ DictionaryValue* manifest = ParseManifest(manifest_contents);
+ if (manifest) {
+ std::string name = prefs_->GetString(prefs::kEnterpriseWebStoreName);
+ manifest->SetString("app.launch.web_url", enterprise_webstore_url);
+ manifest->SetString("name", name);
+ Add(manifest, path);
+ }
+ }
+}
+
+void ComponentLoader::AddDefaultComponentExtensions() {
+ Add(IDR_BOOKMARKS_MANIFEST, FilePath(FILE_PATH_LITERAL("bookmark_manager")));
#if defined(FILE_MANAGER_EXTENSION)
- AddFileManagerExtension(&component_extensions);
+ AddFileManagerExtension();
#endif
#if defined(USE_VIRTUAL_KEYBOARD)
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("keyboard"),
- IDR_KEYBOARD_MANIFEST));
+ Add(IDR_KEYBOARD_MANIFEST, FilePath(FILE_PATH_LITERAL("keyboard")));
#endif
#if defined(OS_CHROMEOS)
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile"),
- IDR_MOBILE_MANIFEST));
+ Add(IDR_MOBILE_MANIFEST,
+ FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kAuthExtensionPath)) {
FilePath auth_extension_path =
command_line->GetSwitchValuePath(switches::kAuthExtensionPath);
- component_extensions.push_back(std::make_pair(
- auth_extension_path.value(),
- IDR_GAIA_TEST_AUTH_MANIFEST));
+ Add(IDR_GAIA_TEST_AUTH_MANIFEST, auth_extension_path);
} else {
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("/usr/share/chromeos-assets/gaia_auth"),
- IDR_GAIA_AUTH_MANIFEST));
+ Add(IDR_GAIA_AUTH_MANIFEST,
+ FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/gaia_auth")));
}
#if defined(OFFICIAL_BUILD)
if (browser_defaults::enable_help_app) {
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp"),
- IDR_HELP_MANIFEST));
+ Add(IDR_HELP_MANIFEST,
+ FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp")));
}
#endif
-#endif
+#endif // !defined(OS_CHROMEOS)
- // Web Store.
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("web_store"),
- IDR_WEBSTORE_MANIFEST));
+ Add(IDR_WEBSTORE_MANIFEST, FilePath(FILE_PATH_LITERAL("web_store")));
#if !defined(OS_CHROMEOS)
// Cloud Print component app. Not required on Chrome OS.
- component_extensions.push_back(std::make_pair(
- FILE_PATH_LITERAL("cloud_print"),
- IDR_CLOUDPRINT_MANIFEST));
-#endif // !defined(OS_CHROMEOS)
-
- for (ComponentExtensionList::iterator iter = component_extensions.begin();
- iter != component_extensions.end(); ++iter) {
- FilePath path(iter->first);
- if (!path.IsAbsolute()) {
- if (PathService::Get(chrome::DIR_RESOURCES, &path)) {
- path = path.Append(iter->first);
- } else {
- NOTREACHED();
- }
- }
-
- std::string manifest =
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- iter->second).as_string();
- Add(manifest, path);
- }
+ Add(IDR_CLOUDPRINT_MANIFEST, FilePath(FILE_PATH_LITERAL("cloud_print")));
+#endif
#if defined(OS_CHROMEOS)
// Register access extensions only if accessibility is enabled.
- if (g_browser_process->local_state()->
- GetBoolean(prefs::kAccessibilityEnabled)) {
+ if (local_state_->GetBoolean(prefs::kAccessibilityEnabled)) {
FilePath path = FilePath(extension_misc::kAccessExtensionPath)
.AppendASCII(extension_misc::kChromeVoxDirectoryName);
- std::string manifest =
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_CHROMEVOX_MANIFEST).as_string();
- Add(manifest, path);
+ Add(IDR_CHROMEVOX_MANIFEST, path);
}
#endif
+
+ // If a URL for the enterprise webstore has been specified, load the
+ // component extension. This extension might also be loaded later, because
+ // it is specified by policy, and on ChromeOS policies are loaded after
+ // the browser process has started.
+ AddOrReloadEnterpriseWebStore();
+}
+
+void ComponentLoader::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ const std::string* name =
+ content::Details<const std::string>(details).ptr();
+ if (*name == prefs::kEnterpriseWebStoreURL)
+ AddOrReloadEnterpriseWebStore();
+ else
+ NOTREACHED();
+ } else {
+ NOTREACHED();
+ }
+}
+
+// static
+void ComponentLoader::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterStringPref(prefs::kEnterpriseWebStoreURL,
+ std::string() /* default_value */,
+ PrefService::UNSYNCABLE_PREF);
+ prefs->RegisterStringPref(prefs::kEnterpriseWebStoreName,
+ std::string() /* default_value */,
+ PrefService::UNSYNCABLE_PREF);
}
} // namespace extensions