Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Unified Diff: chrome/browser/extensions/component_loader.cc

Issue 8477005: Add policies to specify an enterprise web store. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebasse. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/component_loader.cc
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 624befad35a4d33548f132dc5c65735e785e4ff7..87b48d7c1d3c07414b496928f796e893688bf2fe 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);
Jeffrey Yasskin 2013/05/14 02:26:32 This Remove() call isn't working anymore, at least
+
+ 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
« no previous file with comments | « chrome/browser/extensions/component_loader.h ('k') | chrome/browser/extensions/component_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698