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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/component_loader.h" 5 #include "chrome/browser/extensions/component_loader.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/path_service.h" 8 #include "base/path_service.h"
9 #include "base/json/json_value_serializer.h" 9 #include "base/json/json_value_serializer.h"
10 #include "chrome/browser/browser_process.h" 10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/prefs/pref_change_registrar.h"
13 #include "chrome/browser/prefs/pref_notifier.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_notification_types.h"
12 #include "chrome/common/chrome_paths.h" 16 #include "chrome/common/chrome_paths.h"
13 #include "chrome/common/chrome_switches.h" 17 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/extensions/extension.h" 18 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/pref_names.h" 19 #include "chrome/common/pref_names.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
16 #include "grit/browser_resources.h" 22 #include "grit/browser_resources.h"
17 #include "ui/base/resource/resource_bundle.h" 23 #include "ui/base/resource/resource_bundle.h"
18 24
19 #if defined(OFFICIAL_BUILD) 25 #if defined(OFFICIAL_BUILD)
20 #include "chrome/browser/defaults.h" 26 #include "chrome/browser/defaults.h"
21 #endif 27 #endif
22 28
23 namespace {
24
25 typedef std::list<std::pair<FilePath::StringType, int> >
26 ComponentExtensionList;
27
28 #if defined(FILE_MANAGER_EXTENSION)
29 void AddFileManagerExtension(ComponentExtensionList* component_extensions) {
30 #ifndef NDEBUG
31 const CommandLine* command_line = CommandLine::ForCurrentProcess();
32 if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
33 FilePath filemgr_extension_path =
34 command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath);
35 component_extensions->push_back(std::make_pair(
36 filemgr_extension_path.value(),
37 IDR_FILEMANAGER_MANIFEST));
38 return;
39 }
40 #endif // NDEBUG
41 component_extensions->push_back(std::make_pair(
42 FILE_PATH_LITERAL("file_manager"),
43 IDR_FILEMANAGER_MANIFEST));
44 }
45 #endif // defined(FILE_MANAGER_EXTENSION)
46
47 } // namespace
48
49 namespace extensions { 29 namespace extensions {
50 30
51 bool ComponentLoader::ComponentExtensionInfo::Equals( 31 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
52 const ComponentExtensionInfo& other) const { 32 PrefService* prefs,
53 return other.manifest == manifest && other.root_directory == root_directory; 33 PrefService* local_state)
54 } 34 : prefs_(prefs),
35 local_state_(local_state),
36 extension_service_(extension_service) {
37 pref_change_registrar_.Init(prefs);
55 38
56 ComponentLoader::ComponentLoader(ExtensionService* extension_service) 39 // This pref is set by policy. We have to watch it for change because on
57 : extension_service_(extension_service) { 40 // ChromeOS, policy isn't loaded until after the browser process is started.
41 pref_change_registrar_.Add(prefs::kEnterpriseWebStoreURL, this);
58 } 42 }
59 43
60 ComponentLoader::~ComponentLoader() { 44 ComponentLoader::~ComponentLoader() {
61 } 45 }
62 46
63 void ComponentLoader::LoadAll() { 47 void ComponentLoader::LoadAll() {
64 for (RegisteredComponentExtensions::iterator it = 48 for (RegisteredComponentExtensions::iterator it =
65 component_extensions_.begin(); 49 component_extensions_.begin();
66 it != component_extensions_.end(); ++it) { 50 it != component_extensions_.end(); ++it) {
67 Load(*it); 51 Load(*it);
68 } 52 }
69 } 53 }
70 54
55 DictionaryValue* ComponentLoader::ParseManifest(
56 const std::string& manifest_contents) const {
57 JSONStringValueSerializer serializer(manifest_contents);
58 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
59
60 if (!manifest.get() || !manifest->IsType(Value::TYPE_DICTIONARY)) {
61 LOG(ERROR) << "Failed to parse extension manifest.";
62 return NULL;
63 }
64 // Transfer ownership to the caller.
65 return static_cast<DictionaryValue*>(manifest.release());
66 }
67
71 const Extension* ComponentLoader::Add( 68 const Extension* ComponentLoader::Add(
72 const std::string& manifest, const FilePath& root_directory) { 69 int manifest_resource_id,
73 ComponentExtensionInfo info(manifest, root_directory); 70 const FilePath& root_directory) {
74 Register(info); 71 std::string manifest_contents =
72 ResourceBundle::GetSharedInstance().GetRawDataResource(
73 manifest_resource_id).as_string();
74 return Add(manifest_contents, root_directory);
75 }
76
77 const Extension* ComponentLoader::Add(
78 std::string& manifest_contents,
79 const FilePath& root_directory) {
80 // The Value is kept for the lifetime of the ComponentLoader. This is
81 // required in case LoadAll() is called again.
82 DictionaryValue* manifest = ParseManifest(manifest_contents);
83 if (manifest)
84 return Add(manifest, root_directory);
85 return NULL;
86 }
87
88 const Extension* ComponentLoader::Add(
89 const DictionaryValue* parsed_manifest,
90 const FilePath& root_directory) {
91 // Get the absolute path to the extension.
92 FilePath absolute_path(root_directory);
93 if (!absolute_path.IsAbsolute()) {
94 if (PathService::Get(chrome::DIR_RESOURCES, &absolute_path)) {
95 absolute_path = absolute_path.Append(root_directory);
96 } else {
97 NOTREACHED();
98 }
99 }
100
101 ComponentExtensionInfo info(parsed_manifest, absolute_path);
102 component_extensions_.push_back(info);
75 if (extension_service_->is_ready()) 103 if (extension_service_->is_ready())
76 return Load(info); 104 return Load(info);
77 return NULL; 105 return NULL;
78 } 106 }
79 107
80 const Extension* ComponentLoader::Load(const ComponentExtensionInfo& info) { 108 const Extension* ComponentLoader::Load(const ComponentExtensionInfo& info) {
81 JSONStringValueSerializer serializer(info.manifest);
82 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
83 if (!manifest.get()) {
84 LOG(ERROR) << "Failed to parse manifest for extension";
85 return NULL;
86 }
87
88 int flags = Extension::REQUIRE_KEY; 109 int flags = Extension::REQUIRE_KEY;
89 if (Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT)) 110 if (Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT))
90 flags |= Extension::STRICT_ERROR_CHECKS; 111 flags |= Extension::STRICT_ERROR_CHECKS;
91 std::string error; 112 std::string error;
92 scoped_refptr<const Extension> extension(Extension::Create( 113 scoped_refptr<const Extension> extension(Extension::Create(
93 info.root_directory, 114 info.root_directory,
94 Extension::COMPONENT, 115 Extension::COMPONENT,
95 *static_cast<DictionaryValue*>(manifest.get()), 116 *info.manifest,
96 flags, 117 flags,
97 &error)); 118 &error));
98 if (!extension.get()) { 119 if (!extension.get()) {
99 LOG(ERROR) << error; 120 LOG(ERROR) << error;
100 return NULL; 121 return NULL;
101 } 122 }
102 extension_service_->AddExtension(extension); 123 extension_service_->AddExtension(extension);
103 return extension; 124 return extension;
104 } 125 }
105 126
106 void ComponentLoader::Remove(const std::string& manifest_str) { 127 void ComponentLoader::Remove(const FilePath& root_directory) {
107 // Unload the extension. 128 // Find the ComponentExtensionInfo for the extension.
108 JSONStringValueSerializer serializer(manifest_str); 129 RegisteredComponentExtensions::iterator it = component_extensions_.begin();
109 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL)); 130 for (; it != component_extensions_.end(); ++it) {
110 if (!manifest.get()) { 131 if (it->root_directory == root_directory)
111 LOG(ERROR) << "Failed to parse manifest for extension"; 132 break;
133 }
134 // If the extension is not in the list, there's nothing to do.
135 if (it == component_extensions_.end())
112 return; 136 return;
113 } 137
138 const DictionaryValue* manifest = it->manifest;
139
140 // Remove the extension from the list of registered extensions.
141 *it = component_extensions_.back();
142 component_extensions_.pop_back();
143
144 // Determine the extension id and unload the extension.
114 std::string public_key; 145 std::string public_key;
115 std::string public_key_bytes; 146 std::string public_key_bytes;
116 std::string id; 147 std::string id;
117 if (!static_cast<DictionaryValue*>(manifest.get())-> 148 if (!manifest->GetString(
118 GetString(extension_manifest_keys::kPublicKey, &public_key) || 149 extension_manifest_keys::kPublicKey, &public_key) ||
119 !Extension::ParsePEMKeyBytes(public_key, &public_key_bytes) || 150 !Extension::ParsePEMKeyBytes(public_key, &public_key_bytes) ||
120 !Extension::GenerateId(public_key_bytes, &id)) { 151 !Extension::GenerateId(public_key_bytes, &id)) {
121 LOG(ERROR) << "Failed to get extension id"; 152 LOG(ERROR) << "Failed to get extension id";
122 return; 153 return;
123 } 154 }
124 extension_service_-> 155 extension_service_->
125 UnloadExtension(id, extension_misc::UNLOAD_REASON_DISABLE); 156 UnloadExtension(id, extension_misc::UNLOAD_REASON_DISABLE);
126
127 // Unregister the extension.
128 RegisteredComponentExtensions new_component_extensions;
129 for (RegisteredComponentExtensions::iterator it =
130 component_extensions_.begin();
131 it != component_extensions_.end(); ++it) {
132 if (it->manifest != manifest_str)
133 new_component_extensions.push_back(*it);
134 }
135 component_extensions_.swap(new_component_extensions);
136 } 157 }
137 158
138 // We take ComponentExtensionList: 159 void ComponentLoader::AddFileManagerExtension() {
139 // path, manifest ID => full manifest, absolute path 160 #if defined(FILE_MANAGER_EXTENSION)
161 #ifndef NDEBUG
162 const CommandLine* command_line = CommandLine::ForCurrentProcess();
163 if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
164 FilePath filemgr_extension_path(
165 command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath));
166 Add(IDR_FILEMANAGER_MANIFEST, filemgr_extension_path);
167 return;
168 }
169 #endif // NDEBUG
170 Add(IDR_FILEMANAGER_MANIFEST, FilePath(FILE_PATH_LITERAL("file_manager")));
171 #endif // defined(FILE_MANAGER_EXTENSION)
172 }
173
174 void ComponentLoader::AddOrReloadEnterpriseWebStore() {
175 FilePath path(FILE_PATH_LITERAL("enterprise_web_store"));
176
177 // Remove the extension if it was already loaded.
178 Remove(path);
Jeffrey Yasskin 2013/05/14 02:26:32 This Remove() call isn't working anymore, at least
179
180 std::string enterprise_webstore_url =
181 prefs_->GetString(prefs::kEnterpriseWebStoreURL);
182
183 // Load the extension only if the URL preference is set.
184 if (!enterprise_webstore_url.empty()) {
185 std::string manifest_contents =
186 ResourceBundle::GetSharedInstance().GetRawDataResource(
187 IDR_ENTERPRISE_WEBSTORE_MANIFEST).as_string();
188
189 // The manifest is missing some values that are provided by policy.
190 DictionaryValue* manifest = ParseManifest(manifest_contents);
191 if (manifest) {
192 std::string name = prefs_->GetString(prefs::kEnterpriseWebStoreName);
193 manifest->SetString("app.launch.web_url", enterprise_webstore_url);
194 manifest->SetString("name", name);
195 Add(manifest, path);
196 }
197 }
198 }
199
140 void ComponentLoader::AddDefaultComponentExtensions() { 200 void ComponentLoader::AddDefaultComponentExtensions() {
141 ComponentExtensionList component_extensions; 201 Add(IDR_BOOKMARKS_MANIFEST, FilePath(FILE_PATH_LITERAL("bookmark_manager")));
142
143 // Bookmark manager.
144 component_extensions.push_back(std::make_pair(
145 FILE_PATH_LITERAL("bookmark_manager"),
146 IDR_BOOKMARKS_MANIFEST));
147 202
148 #if defined(FILE_MANAGER_EXTENSION) 203 #if defined(FILE_MANAGER_EXTENSION)
149 AddFileManagerExtension(&component_extensions); 204 AddFileManagerExtension();
150 #endif 205 #endif
151 206
152 #if defined(USE_VIRTUAL_KEYBOARD) 207 #if defined(USE_VIRTUAL_KEYBOARD)
153 component_extensions.push_back(std::make_pair( 208 Add(IDR_KEYBOARD_MANIFEST, FilePath(FILE_PATH_LITERAL("keyboard")));
154 FILE_PATH_LITERAL("keyboard"),
155 IDR_KEYBOARD_MANIFEST));
156 #endif 209 #endif
157 210
158 #if defined(OS_CHROMEOS) 211 #if defined(OS_CHROMEOS)
159 component_extensions.push_back(std::make_pair( 212 Add(IDR_MOBILE_MANIFEST,
160 FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile"), 213 FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
161 IDR_MOBILE_MANIFEST));
162 214
163 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 215 const CommandLine* command_line = CommandLine::ForCurrentProcess();
164 if (command_line->HasSwitch(switches::kAuthExtensionPath)) { 216 if (command_line->HasSwitch(switches::kAuthExtensionPath)) {
165 FilePath auth_extension_path = 217 FilePath auth_extension_path =
166 command_line->GetSwitchValuePath(switches::kAuthExtensionPath); 218 command_line->GetSwitchValuePath(switches::kAuthExtensionPath);
167 component_extensions.push_back(std::make_pair( 219 Add(IDR_GAIA_TEST_AUTH_MANIFEST, auth_extension_path);
168 auth_extension_path.value(),
169 IDR_GAIA_TEST_AUTH_MANIFEST));
170 } else { 220 } else {
171 component_extensions.push_back(std::make_pair( 221 Add(IDR_GAIA_AUTH_MANIFEST,
172 FILE_PATH_LITERAL("/usr/share/chromeos-assets/gaia_auth"), 222 FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/gaia_auth")));
173 IDR_GAIA_AUTH_MANIFEST));
174 } 223 }
175 224
176 #if defined(OFFICIAL_BUILD) 225 #if defined(OFFICIAL_BUILD)
177 if (browser_defaults::enable_help_app) { 226 if (browser_defaults::enable_help_app) {
178 component_extensions.push_back(std::make_pair( 227 Add(IDR_HELP_MANIFEST,
179 FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp"), 228 FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp")));
180 IDR_HELP_MANIFEST));
181 } 229 }
182 #endif 230 #endif
183 #endif 231 #endif // !defined(OS_CHROMEOS)
184 232
185 // Web Store. 233 Add(IDR_WEBSTORE_MANIFEST, FilePath(FILE_PATH_LITERAL("web_store")));
186 component_extensions.push_back(std::make_pair(
187 FILE_PATH_LITERAL("web_store"),
188 IDR_WEBSTORE_MANIFEST));
189 234
190 #if !defined(OS_CHROMEOS) 235 #if !defined(OS_CHROMEOS)
191 // Cloud Print component app. Not required on Chrome OS. 236 // Cloud Print component app. Not required on Chrome OS.
192 component_extensions.push_back(std::make_pair( 237 Add(IDR_CLOUDPRINT_MANIFEST, FilePath(FILE_PATH_LITERAL("cloud_print")));
193 FILE_PATH_LITERAL("cloud_print"), 238 #endif
194 IDR_CLOUDPRINT_MANIFEST));
195 #endif // !defined(OS_CHROMEOS)
196
197 for (ComponentExtensionList::iterator iter = component_extensions.begin();
198 iter != component_extensions.end(); ++iter) {
199 FilePath path(iter->first);
200 if (!path.IsAbsolute()) {
201 if (PathService::Get(chrome::DIR_RESOURCES, &path)) {
202 path = path.Append(iter->first);
203 } else {
204 NOTREACHED();
205 }
206 }
207
208 std::string manifest =
209 ResourceBundle::GetSharedInstance().GetRawDataResource(
210 iter->second).as_string();
211 Add(manifest, path);
212 }
213 239
214 #if defined(OS_CHROMEOS) 240 #if defined(OS_CHROMEOS)
215 // Register access extensions only if accessibility is enabled. 241 // Register access extensions only if accessibility is enabled.
216 if (g_browser_process->local_state()-> 242 if (local_state_->GetBoolean(prefs::kAccessibilityEnabled)) {
217 GetBoolean(prefs::kAccessibilityEnabled)) {
218 FilePath path = FilePath(extension_misc::kAccessExtensionPath) 243 FilePath path = FilePath(extension_misc::kAccessExtensionPath)
219 .AppendASCII(extension_misc::kChromeVoxDirectoryName); 244 .AppendASCII(extension_misc::kChromeVoxDirectoryName);
220 std::string manifest = 245 Add(IDR_CHROMEVOX_MANIFEST, path);
221 ResourceBundle::GetSharedInstance().GetRawDataResource(
222 IDR_CHROMEVOX_MANIFEST).as_string();
223 Add(manifest, path);
224 } 246 }
225 #endif 247 #endif
248
249 // If a URL for the enterprise webstore has been specified, load the
250 // component extension. This extension might also be loaded later, because
251 // it is specified by policy, and on ChromeOS policies are loaded after
252 // the browser process has started.
253 AddOrReloadEnterpriseWebStore();
254 }
255
256 void ComponentLoader::Observe(
257 int type,
258 const content::NotificationSource& source,
259 const content::NotificationDetails& details) {
260 if (type == chrome::NOTIFICATION_PREF_CHANGED) {
261 const std::string* name =
262 content::Details<const std::string>(details).ptr();
263 if (*name == prefs::kEnterpriseWebStoreURL)
264 AddOrReloadEnterpriseWebStore();
265 else
266 NOTREACHED();
267 } else {
268 NOTREACHED();
269 }
270 }
271
272 // static
273 void ComponentLoader::RegisterUserPrefs(PrefService* prefs) {
274 prefs->RegisterStringPref(prefs::kEnterpriseWebStoreURL,
275 std::string() /* default_value */,
276 PrefService::UNSYNCABLE_PREF);
277 prefs->RegisterStringPref(prefs::kEnterpriseWebStoreName,
278 std::string() /* default_value */,
279 PrefService::UNSYNCABLE_PREF);
226 } 280 }
227 281
228 } // namespace extensions 282 } // namespace extensions
OLDNEW
« 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