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

Side by Side Diff: chrome/browser/extensions/extension_service.cc

Issue 8417012: Refactor loading out of ExtensionService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: finally 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/extension_service.h" 5 #include "chrome/browser/extensions/extension_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/file_util.h" 14 #include "base/file_util.h"
15 #include "base/json/json_value_serializer.h"
16 #include "base/logging.h" 15 #include "base/logging.h"
17 #include "base/metrics/field_trial.h" 16 #include "base/metrics/field_trial.h"
18 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
19 #include "base/path_service.h"
20 #include "base/stl_util.h" 18 #include "base/stl_util.h"
21 #include "base/string16.h" 19 #include "base/string16.h"
22 #include "base/string_number_conversions.h" 20 #include "base/string_number_conversions.h"
23 #include "base/string_util.h" 21 #include "base/string_util.h"
24 #include "base/stringprintf.h" 22 #include "base/stringprintf.h"
25 #include "base/threading/thread_restrictions.h" 23 #include "base/threading/thread_restrictions.h"
26 #include "base/time.h" 24 #include "base/time.h"
27 #include "base/utf_string_conversions.h" 25 #include "base/utf_string_conversions.h"
28 #include "base/values.h" 26 #include "base/values.h"
29 #include "base/version.h" 27 #include "base/version.h"
30 #include "chrome/browser/bookmarks/bookmark_extension_api.h" 28 #include "chrome/browser/bookmarks/bookmark_extension_api.h"
31 #include "chrome/browser/browser_process.h" 29 #include "chrome/browser/browser_process.h"
32 #include "chrome/browser/chrome_plugin_service_filter.h" 30 #include "chrome/browser/chrome_plugin_service_filter.h"
33 #include "chrome/browser/extensions/app_notification_manager.h" 31 #include "chrome/browser/extensions/app_notification_manager.h"
34 #include "chrome/browser/extensions/apps_promo.h" 32 #include "chrome/browser/extensions/apps_promo.h"
33 #include "chrome/browser/extensions/component_loader.h"
35 #include "chrome/browser/extensions/crx_installer.h" 34 #include "chrome/browser/extensions/crx_installer.h"
36 #include "chrome/browser/extensions/default_apps_trial.h" 35 #include "chrome/browser/extensions/default_apps_trial.h"
37 #include "chrome/browser/extensions/extension_accessibility_api.h" 36 #include "chrome/browser/extensions/extension_accessibility_api.h"
38 #include "chrome/browser/extensions/extension_browser_event_router.h" 37 #include "chrome/browser/extensions/extension_browser_event_router.h"
39 #include "chrome/browser/extensions/extension_cookies_api.h" 38 #include "chrome/browser/extensions/extension_cookies_api.h"
40 #include "chrome/browser/extensions/extension_data_deleter.h" 39 #include "chrome/browser/extensions/extension_data_deleter.h"
41 #include "chrome/browser/extensions/extension_downloads_api.h" 40 #include "chrome/browser/extensions/extension_downloads_api.h"
42 #include "chrome/browser/extensions/extension_error_reporter.h" 41 #include "chrome/browser/extensions/extension_error_reporter.h"
43 #include "chrome/browser/extensions/extension_global_error.h" 42 #include "chrome/browser/extensions/extension_global_error.h"
44 #include "chrome/browser/extensions/extension_host.h" 43 #include "chrome/browser/extensions/extension_host.h"
45 #include "chrome/browser/extensions/extension_input_ime_api.h" 44 #include "chrome/browser/extensions/extension_input_ime_api.h"
46 #include "chrome/browser/extensions/extension_install_ui.h"
47 #include "chrome/browser/extensions/extension_management_api.h" 45 #include "chrome/browser/extensions/extension_management_api.h"
48 #include "chrome/browser/extensions/extension_preference_api.h" 46 #include "chrome/browser/extensions/extension_preference_api.h"
49 #include "chrome/browser/extensions/extension_process_manager.h" 47 #include "chrome/browser/extensions/extension_process_manager.h"
50 #include "chrome/browser/extensions/extension_processes_api.h" 48 #include "chrome/browser/extensions/extension_processes_api.h"
51 #include "chrome/browser/extensions/extension_special_storage_policy.h" 49 #include "chrome/browser/extensions/extension_special_storage_policy.h"
52 #include "chrome/browser/extensions/extension_sync_data.h" 50 #include "chrome/browser/extensions/extension_sync_data.h"
53 #include "chrome/browser/extensions/extension_updater.h" 51 #include "chrome/browser/extensions/extension_updater.h"
54 #include "chrome/browser/extensions/extension_web_ui.h" 52 #include "chrome/browser/extensions/extension_web_ui.h"
55 #include "chrome/browser/extensions/extension_webnavigation_api.h" 53 #include "chrome/browser/extensions/extension_webnavigation_api.h"
56 #include "chrome/browser/extensions/external_extension_provider_impl.h" 54 #include "chrome/browser/extensions/external_extension_provider_impl.h"
57 #include "chrome/browser/extensions/external_extension_provider_interface.h" 55 #include "chrome/browser/extensions/external_extension_provider_interface.h"
56 #include "chrome/browser/extensions/installed_loader.h"
58 #include "chrome/browser/extensions/pending_extension_manager.h" 57 #include "chrome/browser/extensions/pending_extension_manager.h"
58 #include "chrome/browser/extensions/unpacked_installer.h"
59 #include "chrome/browser/history/history_extension_api.h" 59 #include "chrome/browser/history/history_extension_api.h"
60 #include "chrome/browser/net/chrome_url_request_context.h" 60 #include "chrome/browser/net/chrome_url_request_context.h"
61 #include "chrome/browser/prefs/pref_service.h" 61 #include "chrome/browser/prefs/pref_service.h"
62 #include "chrome/browser/profiles/profile.h" 62 #include "chrome/browser/profiles/profile.h"
63 #include "chrome/browser/search_engines/template_url_service.h" 63 #include "chrome/browser/search_engines/template_url_service.h"
64 #include "chrome/browser/search_engines/template_url_service_factory.h" 64 #include "chrome/browser/search_engines/template_url_service_factory.h"
65 #include "chrome/browser/sync/api/sync_change.h" 65 #include "chrome/browser/sync/api/sync_change.h"
66 #include "chrome/browser/themes/theme_service.h" 66 #include "chrome/browser/themes/theme_service.h"
67 #include "chrome/browser/themes/theme_service_factory.h" 67 #include "chrome/browser/themes/theme_service_factory.h"
68 #include "chrome/browser/ui/browser.h" 68 #include "chrome/browser/ui/browser.h"
69 #include "chrome/browser/ui/browser_list.h" 69 #include "chrome/browser/ui/browser_list.h"
70 #include "chrome/browser/ui/global_error_service.h" 70 #include "chrome/browser/ui/global_error_service.h"
71 #include "chrome/browser/ui/global_error_service_factory.h" 71 #include "chrome/browser/ui/global_error_service_factory.h"
72 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" 72 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
73 #include "chrome/browser/ui/webui/favicon_source.h" 73 #include "chrome/browser/ui/webui/favicon_source.h"
74 #include "chrome/browser/ui/webui/ntp/shown_sections_handler.h" 74 #include "chrome/browser/ui/webui/ntp/shown_sections_handler.h"
75 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 75 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
76 #include "chrome/common/child_process_logging.h" 76 #include "chrome/common/child_process_logging.h"
77 #include "chrome/common/chrome_notification_types.h" 77 #include "chrome/common/chrome_notification_types.h"
78 #include "chrome/common/chrome_paths.h"
79 #include "chrome/common/chrome_switches.h" 78 #include "chrome/common/chrome_switches.h"
80 #include "chrome/common/extensions/extension.h" 79 #include "chrome/common/extensions/extension.h"
81 #include "chrome/common/extensions/extension_constants.h" 80 #include "chrome/common/extensions/extension_constants.h"
82 #include "chrome/common/extensions/extension_error_utils.h" 81 #include "chrome/common/extensions/extension_error_utils.h"
83 #include "chrome/common/extensions/extension_file_util.h" 82 #include "chrome/common/extensions/extension_file_util.h"
84 #include "chrome/common/extensions/extension_l10n_util.h"
85 #include "chrome/common/extensions/extension_messages.h" 83 #include "chrome/common/extensions/extension_messages.h"
86 #include "chrome/common/extensions/extension_resource.h" 84 #include "chrome/common/extensions/extension_resource.h"
87 #include "chrome/common/pref_names.h" 85 #include "chrome/common/pref_names.h"
88 #include "chrome/common/url_constants.h" 86 #include "chrome/common/url_constants.h"
89 #include "content/browser/debugger/devtools_manager.h" 87 #include "content/browser/debugger/devtools_manager.h"
90 #include "content/browser/plugin_process_host.h" 88 #include "content/browser/plugin_process_host.h"
91 #include "content/browser/plugin_service.h" 89 #include "content/browser/plugin_service.h"
92 #include "content/browser/renderer_host/render_process_host.h" 90 #include "content/browser/renderer_host/render_process_host.h"
93 #include "content/browser/user_metrics.h" 91 #include "content/browser/user_metrics.h"
94 #include "content/common/pepper_plugin_registry.h" 92 #include "content/common/pepper_plugin_registry.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 #elif defined(OS_MACOSX) 127 #elif defined(OS_MACOSX)
130 static const int kOmniboxIconPaddingLeft = 0; 128 static const int kOmniboxIconPaddingLeft = 0;
131 static const int kOmniboxIconPaddingRight = 2; 129 static const int kOmniboxIconPaddingRight = 2;
132 #else 130 #else
133 static const int kOmniboxIconPaddingLeft = 0; 131 static const int kOmniboxIconPaddingLeft = 0;
134 static const int kOmniboxIconPaddingRight = 0; 132 static const int kOmniboxIconPaddingRight = 0;
135 #endif 133 #endif
136 134
137 const char* kNaClPluginMimeType = "application/x-nacl"; 135 const char* kNaClPluginMimeType = "application/x-nacl";
138 136
139 // The following enumeration is used in histograms matching
140 // Extensions.ManifestReload* . Values may be added, as long
141 // as existing values are not changed.
142 enum ManifestReloadReason {
143 NOT_NEEDED = 0, // Reload not needed.
144 UNPACKED_DIR, // Unpacked directory
145 NEEDS_RELOCALIZATION, // The local has changed since we read this extension.
146 NUM_MANIFEST_RELOAD_REASONS
147 };
148
149 ManifestReloadReason ShouldReloadExtensionManifest(const ExtensionInfo& info) {
150 // Always reload manifests of unpacked extensions, because they can change
151 // on disk independent of the manifest in our prefs.
152 if (info.extension_location == Extension::LOAD)
153 return UNPACKED_DIR;
154
155 // Reload the manifest if it needs to be relocalized.
156 if (extension_l10n_util::ShouldRelocalizeManifest(info))
157 return NEEDS_RELOCALIZATION;
158
159 return NOT_NEEDED;
160 }
161
162 static void ForceShutdownPlugin(const FilePath& plugin_path) { 137 static void ForceShutdownPlugin(const FilePath& plugin_path) {
163 PluginProcessHost* plugin = 138 PluginProcessHost* plugin =
164 PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path); 139 PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path);
165 if (plugin) 140 if (plugin)
166 plugin->ForceShutdown(); 141 plugin->ForceShutdown();
167 } 142 }
168 143
169 static bool IsSyncableExtension(const Extension& extension) { 144 static bool IsSyncableExtension(const Extension& extension) {
170 return extension.GetSyncType() == Extension::SYNC_TYPE_EXTENSION; 145 return extension.GetSyncType() == Extension::SYNC_TYPE_EXTENSION;
171 } 146 }
172 147
173 static bool IsSyncableApp(const Extension& extension) { 148 static bool IsSyncableApp(const Extension& extension) {
174 return extension.GetSyncType() == Extension::SYNC_TYPE_APP; 149 return extension.GetSyncType() == Extension::SYNC_TYPE_APP;
175 } 150 }
176 151
177 // Manages an ExtensionInstallUI for a particular extension.
178 class SimpleExtensionLoadPrompt : public ExtensionInstallUI::Delegate {
179 public:
180 SimpleExtensionLoadPrompt(Profile* profile,
181 base::WeakPtr<ExtensionService> extension_service,
182 const Extension* extension);
183 ~SimpleExtensionLoadPrompt();
184
185 void ShowPrompt();
186
187 // ExtensionInstallUI::Delegate
188 virtual void InstallUIProceed();
189 virtual void InstallUIAbort(bool user_initiated);
190
191 private:
192 base::WeakPtr<ExtensionService> extension_service_;
193 scoped_ptr<ExtensionInstallUI> install_ui_;
194 scoped_refptr<const Extension> extension_;
195 };
196
197 SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt(
198 Profile* profile,
199 base::WeakPtr<ExtensionService> extension_service,
200 const Extension* extension)
201 : extension_service_(extension_service),
202 install_ui_(new ExtensionInstallUI(profile)),
203 extension_(extension) {
204 }
205
206 SimpleExtensionLoadPrompt::~SimpleExtensionLoadPrompt() {
207 }
208
209 void SimpleExtensionLoadPrompt::ShowPrompt() {
210 install_ui_->ConfirmInstall(this, extension_);
211 }
212
213 void SimpleExtensionLoadPrompt::InstallUIProceed() {
214 if (extension_service_.get())
215 extension_service_->OnExtensionInstalled(
216 extension_, false, -1); // Not from web store.
217 delete this;
218 }
219
220 void SimpleExtensionLoadPrompt::InstallUIAbort(bool user_initiated) {
221 delete this;
222 }
223
224 } // namespace 152 } // namespace
225 153
226 bool ExtensionService::ComponentExtensionInfo::Equals(
227 const ComponentExtensionInfo& other) const {
228 return other.manifest == manifest && other.root_directory == root_directory;
229 }
230
231 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() 154 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
232 : background_page_ready(false), 155 : background_page_ready(false),
233 being_upgraded(false), 156 being_upgraded(false),
234 has_used_webrequest(false) { 157 has_used_webrequest(false) {
235 } 158 }
236 159
237 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { 160 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() {
238 } 161 }
239 162
240 ExtensionService::NaClModuleInfo::NaClModuleInfo() { 163 ExtensionService::NaClModuleInfo::NaClModuleInfo() {
241 } 164 }
242 165
243 ExtensionService::NaClModuleInfo::~NaClModuleInfo() { 166 ExtensionService::NaClModuleInfo::~NaClModuleInfo() {
244 } 167 }
245 168
246 // ExtensionService. 169 // ExtensionService.
247 170
248 const char* ExtensionService::kInstallDirectoryName = "Extensions"; 171 const char* ExtensionService::kInstallDirectoryName = "Extensions";
249 const char* ExtensionService::kExtensionSettingsDirectoryName = 172 const char* ExtensionService::kExtensionSettingsDirectoryName =
250 "Extension Settings"; 173 "Extension Settings";
251 const char* ExtensionService::kAppSettingsDirectoryName = "App Settings"; 174 const char* ExtensionService::kAppSettingsDirectoryName = "App Settings";
252 175
253 // Implements IO for the ExtensionService.
254
255 class ExtensionServiceBackend
256 : public base::RefCountedThreadSafe<ExtensionServiceBackend> {
257 public:
258 // |install_directory| is a path where to look for extensions to load.
259 ExtensionServiceBackend(
260 base::WeakPtr<ExtensionService> frontend,
261 const FilePath& install_directory);
262
263 // Loads a single extension from |path| where |path| is the top directory of
264 // a specific extension where its manifest file lives. If |prompt_for_plugins|
265 // is true and the extension contains plugins, we prompt the user before
266 // loading.
267 // Errors are reported through ExtensionErrorReporter. On success,
268 // AddExtension() is called.
269 // TODO(erikkay): It might be useful to be able to load a packed extension
270 // (presumably into memory) without installing it.
271 void LoadSingleExtension(const FilePath &path, bool prompt_for_plugins);
272
273 private:
274 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>;
275
276 virtual ~ExtensionServiceBackend();
277
278 // LoadSingleExtension needs to check the file access preference, which needs
279 // to happen back on the UI thread, so it posts CheckExtensionFileAccess on
280 // the UI thread. In turn, once that gets the pref, it goes back to the
281 // file thread with LoadSingleExtensionWithFileAccess.
282 void CheckExtensionFileAccess(const FilePath& extension_path,
283 bool prompt_for_plugins);
284 void LoadSingleExtensionWithFileAccess(
285 const FilePath &path, bool allow_file_access, bool prompt_for_plugins);
286
287 // Notify the frontend that there was an error loading an extension.
288 void ReportExtensionLoadError(const FilePath& extension_path,
289 const std::string& error);
290
291 // Notify the frontend that an extension was installed.
292 void OnLoadSingleExtension(const scoped_refptr<const Extension>& extension,
293 bool prompt_for_plugins);
294
295 base::WeakPtr<ExtensionService> frontend_;
296
297 // The top-level extensions directory being installed to.
298 FilePath install_directory_;
299
300 DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend);
301 };
302
303 ExtensionServiceBackend::ExtensionServiceBackend(
304 base::WeakPtr<ExtensionService> frontend,
305 const FilePath& install_directory)
306 : frontend_(frontend),
307 install_directory_(install_directory) {
308 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
309 }
310
311 ExtensionServiceBackend::~ExtensionServiceBackend() {
312 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
313 BrowserThread::CurrentlyOn(BrowserThread::FILE));
314 }
315
316 void ExtensionServiceBackend::LoadSingleExtension(const FilePath& path_in,
317 bool prompt_for_plugins) {
318 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
319
320 FilePath extension_path = path_in;
321 file_util::AbsolutePath(&extension_path);
322
323 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
324 base::Bind(&ExtensionServiceBackend::CheckExtensionFileAccess,
325 this, extension_path, prompt_for_plugins));
326 }
327
328 void ExtensionServiceBackend::CheckExtensionFileAccess(
329 const FilePath& extension_path, bool prompt_for_plugins) {
330 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331 std::string id = Extension::GenerateIdForPath(extension_path);
332 // Unpacked extensions default to allowing file access, but if that has been
333 // overridden, don't reset the value.
334 bool allow_file_access =
335 Extension::ShouldAlwaysAllowFileAccess(Extension::LOAD);
336 if (frontend_->extension_prefs()->HasAllowFileAccessSetting(id))
337 allow_file_access = frontend_->extension_prefs()->AllowFileAccess(id);
338
339 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
340 base::Bind(
341 &ExtensionServiceBackend::LoadSingleExtensionWithFileAccess,
342 this, extension_path, allow_file_access, prompt_for_plugins));
343 }
344
345 void ExtensionServiceBackend::LoadSingleExtensionWithFileAccess(
346 const FilePath& extension_path,
347 bool allow_file_access,
348 bool prompt_for_plugins) {
349 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
350 int flags = allow_file_access ?
351 Extension::ALLOW_FILE_ACCESS : Extension::NO_FLAGS;
352 if (Extension::ShouldDoStrictErrorChecking(Extension::LOAD))
353 flags |= Extension::STRICT_ERROR_CHECKS;
354 std::string error;
355 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension(
356 extension_path,
357 Extension::LOAD,
358 flags,
359 &error));
360
361 if (!extension) {
362 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
363 base::Bind(
364 &ExtensionServiceBackend::ReportExtensionLoadError,
365 this,
366 extension_path, error));
367 return;
368 }
369
370 // Report this as an installed extension so that it gets remembered in the
371 // prefs.
372 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
373 base::Bind(
374 &ExtensionServiceBackend::OnLoadSingleExtension,
375 this, extension, prompt_for_plugins));
376 }
377
378 void ExtensionServiceBackend::ReportExtensionLoadError(
379 const FilePath& extension_path, const std::string &error) {
380 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
381 if (frontend_.get())
382 frontend_->ReportExtensionLoadError(
383 extension_path, error, true /* alert_on_error */);
384 }
385
386 void ExtensionServiceBackend::OnLoadSingleExtension(
387 const scoped_refptr<const Extension>& extension, bool prompt_for_plugins) {
388 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
389 if (frontend_.get())
390 frontend_->OnLoadSingleExtension(extension, prompt_for_plugins);
391 }
392
393 void ExtensionService::CheckExternalUninstall(const std::string& id) { 176 void ExtensionService::CheckExternalUninstall(const std::string& id) {
394 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 177 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 178
396 // Check if the providers know about this extension. 179 // Check if the providers know about this extension.
397 ProviderCollection::const_iterator i; 180 ProviderCollection::const_iterator i;
398 for (i = external_extension_providers_.begin(); 181 for (i = external_extension_providers_.begin();
399 i != external_extension_providers_.end(); ++i) { 182 i != external_extension_providers_.end(); ++i) {
400 DCHECK(i->get()->IsReady()); 183 DCHECK(i->get()->IsReady());
401 if (i->get()->HasExtension(id)) 184 if (i->get()->HasExtension(id))
402 return; // Yup, known extension, don't uninstall. 185 return; // Yup, known extension, don't uninstall.
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 354
572 return true; 355 return true;
573 } 356 }
574 357
575 ExtensionService::ExtensionService(Profile* profile, 358 ExtensionService::ExtensionService(Profile* profile,
576 const CommandLine* command_line, 359 const CommandLine* command_line,
577 const FilePath& install_directory, 360 const FilePath& install_directory,
578 ExtensionPrefs* extension_prefs, 361 ExtensionPrefs* extension_prefs,
579 bool autoupdate_enabled, 362 bool autoupdate_enabled,
580 bool extensions_enabled) 363 bool extensions_enabled)
581 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 364 : profile_(profile),
582 profile_(profile),
583 extension_prefs_(extension_prefs), 365 extension_prefs_(extension_prefs),
584 extension_settings_frontend_(profile), 366 extension_settings_frontend_(profile),
585 pending_extension_manager_(*ALLOW_THIS_IN_INITIALIZER_LIST(this)), 367 pending_extension_manager_(*ALLOW_THIS_IN_INITIALIZER_LIST(this)),
586 install_directory_(install_directory), 368 install_directory_(install_directory),
587 extensions_enabled_(extensions_enabled), 369 extensions_enabled_(extensions_enabled),
588 show_extensions_prompts_(true), 370 show_extensions_prompts_(true),
589 ready_(false), 371 ready_(false),
590 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 372 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
591 menu_manager_(profile), 373 menu_manager_(profile),
592 app_notification_manager_(new AppNotificationManager(profile)), 374 app_notification_manager_(new AppNotificationManager(profile)),
(...skipping 28 matching lines...) Expand all
621 switches::kExtensionsUpdateFrequency), 403 switches::kExtensionsUpdateFrequency),
622 &update_frequency); 404 &update_frequency);
623 } 405 }
624 updater_.reset(new ExtensionUpdater(this, 406 updater_.reset(new ExtensionUpdater(this,
625 extension_prefs, 407 extension_prefs,
626 profile->GetPrefs(), 408 profile->GetPrefs(),
627 profile, 409 profile,
628 update_frequency)); 410 update_frequency));
629 } 411 }
630 412
631 backend_ = 413 component_loader_.reset(new extensions::ComponentLoader(this));
632 new ExtensionServiceBackend(weak_ptr_factory_.GetWeakPtr(),
633 install_directory_);
634 414
635 app_notification_manager_->Init(); 415 app_notification_manager_->Init();
636 416
637 if (extensions_enabled_) { 417 if (extensions_enabled_) {
638 ExternalExtensionProviderImpl::CreateExternalProviders( 418 ExternalExtensionProviderImpl::CreateExternalProviders(
639 this, profile_, &external_extension_providers_); 419 this, profile_, &external_extension_providers_);
640 } 420 }
641 421
642 // Use monochrome icons for Omnibox icons. 422 // Use monochrome icons for Omnibox icons.
643 omnibox_popup_icon_manager_.set_monochrome(true); 423 omnibox_popup_icon_manager_.set_monochrome(true);
(...skipping 15 matching lines...) Expand all
659 } 439 }
660 440
661 const ExtensionList* ExtensionService::terminated_extensions() const { 441 const ExtensionList* ExtensionService::terminated_extensions() const {
662 return &terminated_extensions_; 442 return &terminated_extensions_;
663 } 443 }
664 444
665 PendingExtensionManager* ExtensionService::pending_extension_manager() { 445 PendingExtensionManager* ExtensionService::pending_extension_manager() {
666 return &pending_extension_manager_; 446 return &pending_extension_manager_;
667 } 447 }
668 448
669 void ExtensionService::UnregisterComponentExtension(
670 const ComponentExtensionInfo& info) {
671 RegisteredComponentExtensions new_component_extension_manifests;
672 for (RegisteredComponentExtensions::iterator it =
673 component_extension_manifests_.begin();
674 it != component_extension_manifests_.end(); ++it) {
675 if (!it->Equals(info))
676 new_component_extension_manifests.push_back(*it);
677 }
678 component_extension_manifests_.swap(new_component_extension_manifests);
679 }
680
681 ExtensionService::~ExtensionService() { 449 ExtensionService::~ExtensionService() {
682 // No need to unload extensions here because they are profile-scoped, and the 450 // No need to unload extensions here because they are profile-scoped, and the
683 // profile is in the process of being deleted. 451 // profile is in the process of being deleted.
684 452
685 ProviderCollection::const_iterator i; 453 ProviderCollection::const_iterator i;
686 for (i = external_extension_providers_.begin(); 454 for (i = external_extension_providers_.begin();
687 i != external_extension_providers_.end(); ++i) { 455 i != external_extension_providers_.end(); ++i) {
688 ExternalExtensionProviderInterface* provider = i->get(); 456 ExternalExtensionProviderInterface* provider = i->get();
689 provider->ServiceShutdown(); 457 provider->ServiceShutdown();
690 } 458 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 void ExtensionService::Init() { 512 void ExtensionService::Init() {
745 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 513 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
746 514
747 DCHECK(!ready_); // Can't redo init. 515 DCHECK(!ready_); // Can't redo init.
748 DCHECK_EQ(extensions_.size(), 0u); 516 DCHECK_EQ(extensions_.size(), 0u);
749 517
750 // Hack: we need to ensure the ResourceDispatcherHost is ready before we load 518 // Hack: we need to ensure the ResourceDispatcherHost is ready before we load
751 // the first extension, because its members listen for loaded notifications. 519 // the first extension, because its members listen for loaded notifications.
752 g_browser_process->resource_dispatcher_host(); 520 g_browser_process->resource_dispatcher_host();
753 521
754 LoadAllExtensions(); 522 component_loader_->LoadAll();
523 extensions::InstalledLoader(this).LoadAllExtensions();
755 524
756 // TODO(erikkay) this should probably be deferred to a future point 525 // TODO(erikkay) this should probably be deferred to a future point
757 // rather than running immediately at startup. 526 // rather than running immediately at startup.
758 CheckForExternalUpdates(); 527 CheckForExternalUpdates();
759 528
760 // TODO(erikkay) this should probably be deferred as well. 529 // TODO(erikkay) this should probably be deferred as well.
761 GarbageCollectExtensions(); 530 GarbageCollectExtensions();
762 } 531 }
763 532
764 bool ExtensionService::UpdateExtension( 533 bool ExtensionService::UpdateExtension(
(...skipping 22 matching lines...) Expand all
787 556
788 return false; 557 return false;
789 } 558 }
790 559
791 // We want a silent install only for non-pending extensions and 560 // We want a silent install only for non-pending extensions and
792 // pending extensions that have install_silently set. 561 // pending extensions that have install_silently set.
793 ExtensionInstallUI* client = 562 ExtensionInstallUI* client =
794 (!is_pending_extension || pending_extension_info.install_silently()) ? 563 (!is_pending_extension || pending_extension_info.install_silently()) ?
795 NULL : new ExtensionInstallUI(profile_); 564 NULL : new ExtensionInstallUI(profile_);
796 565
797 scoped_refptr<CrxInstaller> installer(MakeCrxInstaller(client)); 566 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, client));
798 installer->set_expected_id(id); 567 installer->set_expected_id(id);
799 if (is_pending_extension) 568 if (is_pending_extension)
800 installer->set_install_source(pending_extension_info.install_source()); 569 installer->set_install_source(pending_extension_info.install_source());
801 else if (extension) 570 else if (extension)
802 installer->set_install_source(extension->location()); 571 installer->set_install_source(extension->location());
803 if (pending_extension_info.install_silently()) 572 if (pending_extension_info.install_silently())
804 installer->set_allow_silent_install(true); 573 installer->set_allow_silent_install(true);
805 if (extension && extension->from_webstore()) 574 if (extension && extension->from_webstore())
806 installer->set_is_gallery_install(true); 575 installer->set_is_gallery_install(true);
807 installer->set_delete_source(true); 576 installer->set_delete_source(true);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 } else { 610 } else {
842 path = unloaded_extension_paths_[extension_id]; 611 path = unloaded_extension_paths_[extension_id];
843 } 612 }
844 613
845 // Check the installed extensions to see if what we're reloading was already 614 // Check the installed extensions to see if what we're reloading was already
846 // installed. 615 // installed.
847 scoped_ptr<ExtensionInfo> installed_extension( 616 scoped_ptr<ExtensionInfo> installed_extension(
848 extension_prefs_->GetInstalledExtensionInfo(extension_id)); 617 extension_prefs_->GetInstalledExtensionInfo(extension_id));
849 if (installed_extension.get() && 618 if (installed_extension.get() &&
850 installed_extension->extension_manifest.get()) { 619 installed_extension->extension_manifest.get()) {
851 LoadInstalledExtension(*installed_extension, false); 620 extensions::InstalledLoader(this).Load(*installed_extension, false);
852 } else { 621 } else {
622 // Otherwise, the extension is unpacked (location LOAD).
853 // We should always be able to remember the extension's path. If it's not in 623 // We should always be able to remember the extension's path. If it's not in
854 // the map, someone failed to update |unloaded_extension_paths_|. 624 // the map, someone failed to update |unloaded_extension_paths_|.
855 CHECK(!path.empty()); 625 CHECK(!path.empty());
856 LoadExtension(path); 626 extensions::UnpackedInstaller::Create(this)->Load(path);
857 } 627 }
858 } 628 }
859 629
860 bool ExtensionService::UninstallExtension( 630 bool ExtensionService::UninstallExtension(
861 const std::string& extension_id_unsafe, 631 const std::string& extension_id_unsafe,
862 bool external_uninstall, 632 bool external_uninstall,
863 std::string* error) { 633 std::string* error) {
864 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 634 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
865 635
866 // Copy the extension identifier since the reference might have been 636 // Copy the extension identifier since the reference might have been
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 EnableExtension(extension->id()); 870 EnableExtension(extension->id());
1101 } 871 }
1102 872
1103 void ExtensionService::UpdateActivePermissions( 873 void ExtensionService::UpdateActivePermissions(
1104 const Extension* extension, 874 const Extension* extension,
1105 const ExtensionPermissionSet* permissions) { 875 const ExtensionPermissionSet* permissions) {
1106 extension_prefs()->SetActivePermissions(extension->id(), permissions); 876 extension_prefs()->SetActivePermissions(extension->id(), permissions);
1107 extension->SetActivePermissions(permissions); 877 extension->SetActivePermissions(permissions);
1108 } 878 }
1109 879
1110 void ExtensionService::LoadExtension(const FilePath& extension_path) {
1111 LoadExtension(extension_path, true);
1112 }
1113
1114 void ExtensionService::LoadExtension(const FilePath& extension_path,
1115 bool prompt_for_plugins) {
1116 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
1117 base::Bind(&ExtensionServiceBackend::LoadSingleExtension, backend_.get(),
1118 extension_path, prompt_for_plugins));
1119 }
1120
1121 void ExtensionService::LoadExtensionFromCommandLine(
1122 const FilePath& path_in) {
1123
1124 // Load extensions from the command line synchronously to avoid a race
1125 // between extension loading and loading an URL from the command line.
1126 base::ThreadRestrictions::ScopedAllowIO allow_io;
1127
1128 FilePath extension_path = path_in;
1129 file_util::AbsolutePath(&extension_path);
1130
1131 std::string id = Extension::GenerateIdForPath(extension_path);
1132 bool allow_file_access =
1133 Extension::ShouldAlwaysAllowFileAccess(Extension::LOAD);
1134 if (extension_prefs()->HasAllowFileAccessSetting(id))
1135 allow_file_access = extension_prefs()->AllowFileAccess(id);
1136
1137 int flags = Extension::NO_FLAGS;
1138 if (allow_file_access)
1139 flags |= Extension::ALLOW_FILE_ACCESS;
1140 if (Extension::ShouldDoStrictErrorChecking(Extension::LOAD))
1141 flags |= Extension::STRICT_ERROR_CHECKS;
1142
1143 std::string error;
1144 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension(
1145 extension_path,
1146 Extension::LOAD,
1147 flags,
1148 &error));
1149
1150 if (!extension) {
1151 ReportExtensionLoadError(extension_path, error, true);
1152 return;
1153 }
1154
1155 OnLoadSingleExtension(extension, false);
1156 }
1157
1158 void ExtensionService::LoadComponentExtensions() {
1159 for (RegisteredComponentExtensions::iterator it =
1160 component_extension_manifests_.begin();
1161 it != component_extension_manifests_.end(); ++it) {
1162 LoadComponentExtension(*it);
1163 }
1164 }
1165
1166 const Extension* ExtensionService::LoadComponentExtension(
1167 const ComponentExtensionInfo &info) {
1168 JSONStringValueSerializer serializer(info.manifest);
1169 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
1170 if (!manifest.get()) {
1171 LOG(ERROR) << "Failed to parse manifest for extension";
1172 return NULL;
1173 }
1174
1175 int flags = Extension::REQUIRE_KEY;
1176 if (Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT))
1177 flags |= Extension::STRICT_ERROR_CHECKS;
1178 std::string error;
1179 scoped_refptr<const Extension> extension(Extension::Create(
1180 info.root_directory,
1181 Extension::COMPONENT,
1182 *static_cast<DictionaryValue*>(manifest.get()),
1183 flags,
1184 &error));
1185 if (!extension.get()) {
1186 LOG(ERROR) << error;
1187 return NULL;
1188 }
1189 AddExtension(extension);
1190 return extension;
1191 }
1192
1193 void ExtensionService::UnloadComponentExtension(
1194 const ComponentExtensionInfo& info) {
1195 JSONStringValueSerializer serializer(info.manifest);
1196 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
1197 if (!manifest.get()) {
1198 LOG(ERROR) << "Failed to parse manifest for extension";
1199 return;
1200 }
1201 std::string public_key;
1202 std::string public_key_bytes;
1203 std::string id;
1204 if (!static_cast<DictionaryValue*>(manifest.get())->
1205 GetString(extension_manifest_keys::kPublicKey, &public_key) ||
1206 !Extension::ParsePEMKeyBytes(public_key, &public_key_bytes) ||
1207 !Extension::GenerateId(public_key_bytes, &id)) {
1208 LOG(ERROR) << "Failed to get extension id";
1209 return;
1210 }
1211 UnloadExtension(id, extension_misc::UNLOAD_REASON_DISABLE);
1212 }
1213
1214 void ExtensionService::LoadAllExtensions() {
1215 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1216
1217 base::TimeTicks start_time = base::TimeTicks::Now();
1218
1219 // Load any component extensions.
1220 LoadComponentExtensions();
1221
1222 // Load the previously installed extensions.
1223 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
1224 extension_prefs_->GetInstalledExtensionsInfo());
1225
1226 std::vector<int> reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS, 0);
1227 bool should_write_prefs = false;
1228
1229 for (size_t i = 0; i < extensions_info->size(); ++i) {
1230 ExtensionInfo* info = extensions_info->at(i).get();
1231
1232 ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info);
1233 ++reload_reason_counts[reload_reason];
1234 UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestReloadEnumValue",
1235 reload_reason, 100);
1236
1237 if (reload_reason != NOT_NEEDED) {
1238 // Reloading and extension reads files from disk. We do this on the
1239 // UI thread because reloads should be very rare, and the complexity
1240 // added by delaying the time when the extensions service knows about
1241 // all extensions is significant. See crbug.com/37548 for details.
1242 // |allow_io| disables tests that file operations run on the file
1243 // thread.
1244 base::ThreadRestrictions::ScopedAllowIO allow_io;
1245
1246 std::string error;
1247 scoped_refptr<const Extension> extension(
1248 extension_file_util::LoadExtension(
1249 info->extension_path,
1250 info->extension_location,
1251 GetExtensionCreateFlagsForInstalledExtension(info),
1252 &error));
1253
1254 if (extension.get()) {
1255 extensions_info->at(i)->extension_manifest.reset(
1256 static_cast<DictionaryValue*>(
1257 extension->manifest_value()->DeepCopy()));
1258 should_write_prefs = true;
1259 }
1260 }
1261 }
1262
1263 for (size_t i = 0; i < extensions_info->size(); ++i) {
1264 LoadInstalledExtension(*extensions_info->at(i), should_write_prefs);
1265 }
1266
1267 OnLoadedInstalledExtensions();
1268
1269 // The histograms Extensions.ManifestReload* allow us to validate
1270 // the assumption that reloading manifest is a rare event.
1271 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNotNeeded",
1272 reload_reason_counts[NOT_NEEDED]);
1273 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadUnpackedDir",
1274 reload_reason_counts[UNPACKED_DIR]);
1275 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNeedsRelocalization",
1276 reload_reason_counts[NEEDS_RELOCALIZATION]);
1277
1278 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAll", extensions_.size());
1279 UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled", disabled_extensions_.size());
1280
1281 UMA_HISTOGRAM_TIMES("Extensions.LoadAllTime",
1282 base::TimeTicks::Now() - start_time);
1283
1284 int app_user_count = 0;
1285 int app_external_count = 0;
1286 int hosted_app_count = 0;
1287 int packaged_app_count = 0;
1288 int user_script_count = 0;
1289 int extension_user_count = 0;
1290 int extension_external_count = 0;
1291 int theme_count = 0;
1292 int page_action_count = 0;
1293 int browser_action_count = 0;
1294 ExtensionList::iterator ex;
1295 for (ex = extensions_.begin(); ex != extensions_.end(); ++ex) {
1296 Extension::Location location = (*ex)->location();
1297 Extension::Type type = (*ex)->GetType();
1298 if ((*ex)->is_app()) {
1299 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLocation",
1300 location, 100);
1301 } else if (type == Extension::TYPE_EXTENSION) {
1302 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionLocation",
1303 location, 100);
1304 }
1305
1306 // Don't count component extensions, since they are only extensions as an
1307 // implementation detail.
1308 if (location == Extension::COMPONENT)
1309 continue;
1310
1311 // Don't count unpacked extensions, since they're a developer-specific
1312 // feature.
1313 if (location == Extension::LOAD)
1314 continue;
1315
1316 // Using an enumeration shows us the total installed ratio across all users.
1317 // Using the totals per user at each startup tells us the distribution of
1318 // usage for each user (e.g. 40% of users have at least one app installed).
1319 UMA_HISTOGRAM_ENUMERATION("Extensions.LoadType", type, 100);
1320 switch (type) {
1321 case Extension::TYPE_THEME:
1322 ++theme_count;
1323 break;
1324 case Extension::TYPE_USER_SCRIPT:
1325 ++user_script_count;
1326 break;
1327 case Extension::TYPE_HOSTED_APP:
1328 ++hosted_app_count;
1329 if (Extension::IsExternalLocation(location)) {
1330 ++app_external_count;
1331 } else {
1332 ++app_user_count;
1333 }
1334 break;
1335 case Extension::TYPE_PACKAGED_APP:
1336 ++packaged_app_count;
1337 if (Extension::IsExternalLocation(location)) {
1338 ++app_external_count;
1339 } else {
1340 ++app_user_count;
1341 }
1342 break;
1343 case Extension::TYPE_EXTENSION:
1344 default:
1345 if (Extension::IsExternalLocation(location)) {
1346 ++extension_external_count;
1347 } else {
1348 ++extension_user_count;
1349 }
1350 break;
1351 }
1352 if ((*ex)->page_action() != NULL)
1353 ++page_action_count;
1354 if ((*ex)->browser_action() != NULL)
1355 ++browser_action_count;
1356
1357 RecordPermissionMessagesHistogram(
1358 ex->get(), "Extensions.Permissions_Load");
1359 }
1360 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp",
1361 app_user_count + app_external_count);
1362 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppUser", app_user_count);
1363 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppExternal", app_external_count);
1364 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count);
1365 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count);
1366 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension",
1367 extension_user_count + extension_external_count);
1368 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionUser",
1369 extension_user_count);
1370 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionExternal",
1371 extension_external_count);
1372 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count);
1373 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count);
1374 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count);
1375 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction",
1376 browser_action_count);
1377 }
1378
1379 // static 880 // static
1380 void ExtensionService::RecordPermissionMessagesHistogram( 881 void ExtensionService::RecordPermissionMessagesHistogram(
1381 const Extension* e, const char* histogram) { 882 const Extension* e, const char* histogram) {
1382 // Since this is called from multiple sources, and since the Histogram macros 883 // Since this is called from multiple sources, and since the Histogram macros
1383 // use statics, we need to manually lookup the Histogram ourselves. 884 // use statics, we need to manually lookup the Histogram ourselves.
1384 base::Histogram* counter = base::LinearHistogram::FactoryGet( 885 base::Histogram* counter = base::LinearHistogram::FactoryGet(
1385 histogram, 886 histogram,
1386 1, 887 1,
1387 ExtensionPermissionMessage::kEnumBoundary, 888 ExtensionPermissionMessage::kEnumBoundary,
1388 ExtensionPermissionMessage::kEnumBoundary + 1, 889 ExtensionPermissionMessage::kEnumBoundary + 1,
1389 base::Histogram::kUmaTargetedHistogramFlag); 890 base::Histogram::kUmaTargetedHistogramFlag);
1390 891
1391 ExtensionPermissionMessages permissions = e->GetPermissionMessages(); 892 ExtensionPermissionMessages permissions = e->GetPermissionMessages();
1392 if (permissions.empty()) { 893 if (permissions.empty()) {
1393 counter->Add(ExtensionPermissionMessage::kNone); 894 counter->Add(ExtensionPermissionMessage::kNone);
1394 } else { 895 } else {
1395 for (ExtensionPermissionMessages::iterator it = permissions.begin(); 896 for (ExtensionPermissionMessages::iterator it = permissions.begin();
1396 it != permissions.end(); ++it) 897 it != permissions.end(); ++it)
1397 counter->Add(it->id()); 898 counter->Add(it->id());
1398 } 899 }
1399 } 900 }
1400 901
1401 void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
1402 bool write_to_prefs) {
1403 std::string error;
1404 scoped_refptr<const Extension> extension(NULL);
1405
1406 // An explicit check against policy is required to behave correctly during
1407 // startup. This is because extensions that were previously OK might have
1408 // been blacklisted in policy while Chrome was not running.
1409 if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id,
1410 info.extension_location)) {
1411 error = errors::kDisabledByPolicy;
1412 } else if (info.extension_manifest.get()) {
1413 extension = Extension::Create(
1414 info.extension_path,
1415 info.extension_location,
1416 *info.extension_manifest,
1417 GetExtensionCreateFlagsForInstalledExtension(&info),
1418 &error);
1419 } else {
1420 error = errors::kManifestUnreadable;
1421 }
1422
1423 // Once installed, non-unpacked extensions cannot change their IDs (e.g., by
1424 // updating the 'key' field in their manifest).
1425 if (extension &&
1426 extension->location() != Extension::LOAD &&
1427 info.extension_id != extension->id()) {
1428 error = errors::kCannotChangeExtensionID;
1429 extension = NULL;
1430 UserMetrics::RecordAction(UserMetricsAction("Extensions.IDChangedError"));
1431 }
1432
1433 if (!extension) {
1434 ReportExtensionLoadError(info.extension_path, error, false);
1435 return;
1436 }
1437
1438 if (write_to_prefs)
1439 extension_prefs_->UpdateManifest(extension);
1440
1441 AddExtension(extension);
1442 }
1443
1444 int ExtensionService::GetExtensionCreateFlagsForInstalledExtension(
1445 const ExtensionInfo* info) {
1446 int flags = Extension::NO_FLAGS;
1447 if (info->extension_location != Extension::LOAD)
1448 flags |= Extension::REQUIRE_KEY;
1449 if (Extension::ShouldDoStrictErrorChecking(info->extension_location))
1450 flags |= Extension::STRICT_ERROR_CHECKS;
1451 if (extension_prefs_->AllowFileAccess(info->extension_id))
1452 flags |= Extension::ALLOW_FILE_ACCESS;
1453 if (extension_prefs_->IsFromWebStore(info->extension_id))
1454 flags |= Extension::FROM_WEBSTORE;
1455 if (extension_prefs_->IsFromBookmark(info->extension_id))
1456 flags |= Extension::FROM_BOOKMARK;
1457 return flags;
1458 }
1459
1460 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { 902 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
1461 // The ChromeURLRequestContexts need to be first to know that the extension 903 // The ChromeURLRequestContexts need to be first to know that the extension
1462 // was loaded, otherwise a race can arise where a renderer that is created 904 // was loaded, otherwise a race can arise where a renderer that is created
1463 // for the extension may try to load an extension URL with an extension id 905 // for the extension may try to load an extension URL with an extension id
1464 // that the request context doesn't yet know about. The profile is responsible 906 // that the request context doesn't yet know about. The profile is responsible
1465 // for ensuring its URLRequestContexts appropriately discover the loaded 907 // for ensuring its URLRequestContexts appropriately discover the loaded
1466 // extension. 908 // extension.
1467 profile_->RegisterExtensionWithRequestContexts(extension); 909 profile_->RegisterExtensionWithRequestContexts(extension);
1468 910
1469 // Tell subsystems that use the EXTENSION_LOADED notification about the new 911 // Tell subsystems that use the EXTENSION_LOADED notification about the new
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
2198 1640
2199 if (!CommandLine::ForCurrentProcess()->HasSwitch( 1641 if (!CommandLine::ForCurrentProcess()->HasSwitch(
2200 switches::kEnableExtensionAlerts)) { 1642 switches::kEnableExtensionAlerts)) {
2201 return; // TODO(miket): enable unconditionally when done. 1643 return; // TODO(miket): enable unconditionally when done.
2202 } 1644 }
2203 1645
2204 // Build up the lists of extensions that require acknowledgment. 1646 // Build up the lists of extensions that require acknowledgment.
2205 // If this is the first time, grandfather extensions that would have 1647 // If this is the first time, grandfather extensions that would have
2206 // caused notification. 1648 // caused notification.
2207 scoped_ptr<ExtensionGlobalError> global_error( 1649 scoped_ptr<ExtensionGlobalError> global_error(
2208 new ExtensionGlobalError(weak_ptr_factory_.GetWeakPtr())); 1650 new ExtensionGlobalError(AsWeakPtr()));
2209 bool needs_alert = false; 1651 bool needs_alert = false;
2210 for (ExtensionList::const_iterator iter = extensions_.begin(); 1652 for (ExtensionList::const_iterator iter = extensions_.begin();
2211 iter != extensions_.end(); ++iter) { 1653 iter != extensions_.end(); ++iter) {
2212 const Extension* e = *iter; 1654 const Extension* e = *iter;
2213 if (!IsExtensionEnabled(e->id())) { 1655 if (!IsExtensionEnabled(e->id())) {
2214 continue; 1656 continue;
2215 } 1657 }
2216 if (Extension::IsExternalLocation(e->location())) { 1658 if (Extension::IsExternalLocation(e->location())) {
2217 if (!extension_prefs_->IsExternalExtensionAcknowledged(e->id())) { 1659 if (!extension_prefs_->IsExternalExtensionAcknowledged(e->id())) {
2218 global_error->AddExternalExtension(e->id()); 1660 global_error->AddExternalExtension(e->id());
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 terminated_extensions_.clear(); 1790 terminated_extensions_.clear();
2349 extension_runtime_data_.clear(); 1791 extension_runtime_data_.clear();
2350 1792
2351 // TODO(erikkay) should there be a notification for this? We can't use 1793 // TODO(erikkay) should there be a notification for this? We can't use
2352 // EXTENSION_UNLOADED since that implies that the extension has been disabled 1794 // EXTENSION_UNLOADED since that implies that the extension has been disabled
2353 // or uninstalled, and UnloadAll is just part of shutdown. 1795 // or uninstalled, and UnloadAll is just part of shutdown.
2354 } 1796 }
2355 1797
2356 void ExtensionService::ReloadExtensions() { 1798 void ExtensionService::ReloadExtensions() {
2357 UnloadAllExtensions(); 1799 UnloadAllExtensions();
2358 LoadAllExtensions(); 1800 component_loader_->LoadAll();
1801 extensions::InstalledLoader(this).LoadAllExtensions();
2359 } 1802 }
2360 1803
2361 void ExtensionService::GarbageCollectExtensions() { 1804 void ExtensionService::GarbageCollectExtensions() {
2362 if (extension_prefs_->pref_service()->ReadOnly()) 1805 if (extension_prefs_->pref_service()->ReadOnly())
2363 return; 1806 return;
2364 1807
2365 scoped_ptr<ExtensionPrefs::ExtensionsInfo> info( 1808 scoped_ptr<ExtensionPrefs::ExtensionsInfo> info(
2366 extension_prefs_->GetInstalledExtensionsInfo()); 1809 extension_prefs_->GetInstalledExtensionsInfo());
2367 1810
2368 std::map<std::string, FilePath> extension_paths; 1811 std::map<std::string, FilePath> extension_paths;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
2554 std::set<std::string> extension_ids; 1997 std::set<std::string> extension_ids;
2555 for (size_t i = 0; i < extensions_.size(); ++i) { 1998 for (size_t i = 0; i < extensions_.size(); ++i) {
2556 if (!extensions_[i]->is_theme() && 1999 if (!extensions_[i]->is_theme() &&
2557 extensions_[i]->location() != Extension::COMPONENT) 2000 extensions_[i]->location() != Extension::COMPONENT)
2558 extension_ids.insert(extensions_[i]->id()); 2001 extension_ids.insert(extensions_[i]->id());
2559 } 2002 }
2560 2003
2561 child_process_logging::SetActiveExtensions(extension_ids); 2004 child_process_logging::SetActiveExtensions(extension_ids);
2562 } 2005 }
2563 2006
2564 void ExtensionService::OnLoadSingleExtension(const Extension* extension,
2565 bool prompt_for_plugins) {
2566 // If this is a new install of an extension with plugins, prompt the user
2567 // first.
2568 if (show_extensions_prompts_ && prompt_for_plugins &&
2569 !extension->plugins().empty() &&
2570 disabled_extension_paths_.find(extension->id()) ==
2571 disabled_extension_paths_.end()) {
2572 SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt(
2573 profile_, weak_ptr_factory_.GetWeakPtr(), extension);
2574 prompt->ShowPrompt();
2575 return; // continues in SimpleExtensionLoadPrompt::InstallUI*
2576 }
2577 OnExtensionInstalled(extension, false, -1); // Not from web store.
2578 }
2579
2580 void ExtensionService::OnExtensionInstalled( 2007 void ExtensionService::OnExtensionInstalled(
2581 const Extension* extension, bool from_webstore, int page_index) { 2008 const Extension* extension, bool from_webstore, int page_index) {
2582 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2009 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2583 2010
2584 // Ensure extension is deleted unless we transfer ownership. 2011 // Ensure extension is deleted unless we transfer ownership.
2585 scoped_refptr<const Extension> scoped_extension(extension); 2012 scoped_refptr<const Extension> scoped_extension(extension);
2586 const std::string& id = extension->id(); 2013 const std::string& id = extension->id();
2587 // Extensions installed by policy can't be disabled. So even if a previous 2014 // Extensions installed by policy can't be disabled. So even if a previous
2588 // installation disabled the extension, make sure it is now enabled. 2015 // installation disabled the extension, make sure it is now enabled.
2589 bool initial_enable = 2016 bool initial_enable =
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2807 << "that is older than current version. Current version " 2234 << "that is older than current version. Current version "
2808 << "is: " << existing->VersionString() << ". New version " 2235 << "is: " << existing->VersionString() << ". New version "
2809 << "is: " << version << ". Keeping current version."; 2236 << "is: " << version << ". Keeping current version.";
2810 return; 2237 return;
2811 } 2238 }
2812 } 2239 }
2813 2240
2814 pending_extension_manager()->AddFromExternalFile(id, location); 2241 pending_extension_manager()->AddFromExternalFile(id, location);
2815 2242
2816 // no client (silent install) 2243 // no client (silent install)
2817 scoped_refptr<CrxInstaller> installer(MakeCrxInstaller(NULL)); 2244 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, NULL));
2818 installer->set_install_source(location); 2245 installer->set_install_source(location);
2819 installer->set_expected_id(id); 2246 installer->set_expected_id(id);
2820 installer->set_expected_version(*version); 2247 installer->set_expected_version(*version);
2821 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); 2248 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE);
2822 installer->set_creation_flags(creation_flags); 2249 installer->set_creation_flags(creation_flags);
2823 installer->InstallCrx(path); 2250 installer->InstallCrx(path);
2824 } 2251 }
2825 2252
2826 void ExtensionService::ReportExtensionLoadError( 2253 void ExtensionService::ReportExtensionLoadError(
2827 const FilePath& extension_path, 2254 const FilePath& extension_path,
2828 const std::string &error, 2255 const std::string &error,
2829 bool be_noisy) { 2256 bool be_noisy) {
2830 content::NotificationService* service = 2257 content::NotificationService::current()->Notify(
2831 content::NotificationService::current(); 2258 chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
2832 service->Notify(chrome::NOTIFICATION_EXTENSION_LOAD_ERROR, 2259 content::Source<Profile>(profile_),
2833 content::Source<Profile>(profile_), 2260 content::Details<const std::string>(&error));
2834 content::Details<const std::string>(&error));
2835 2261
2836 std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName()); 2262 std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName());
2837 std::string message = base::StringPrintf( 2263 std::string message = base::StringPrintf(
2838 "Could not load extension from '%s'. %s", 2264 "Could not load extension from '%s'. %s",
2839 path_str.c_str(), error.c_str()); 2265 path_str.c_str(), error.c_str());
2840 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); 2266 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy);
2841 } 2267 }
2842 2268
2843 void ExtensionService::DidCreateRenderViewForBackgroundPage( 2269 void ExtensionService::DidCreateRenderViewForBackgroundPage(
2844 ExtensionHost* host) { 2270 ExtensionHost* host) {
(...skipping 21 matching lines...) Expand all
2866 2292
2867 // Mark the extension as terminated and Unload it. We want it to 2293 // Mark the extension as terminated and Unload it. We want it to
2868 // be in a consistent state: either fully working or not loaded 2294 // be in a consistent state: either fully working or not loaded
2869 // at all, but never half-crashed. We do it in a PostTask so 2295 // at all, but never half-crashed. We do it in a PostTask so
2870 // that other handlers of this notification will still have 2296 // that other handlers of this notification will still have
2871 // access to the Extension and ExtensionHost. 2297 // access to the Extension and ExtensionHost.
2872 MessageLoop::current()->PostTask( 2298 MessageLoop::current()->PostTask(
2873 FROM_HERE, 2299 FROM_HERE,
2874 base::Bind( 2300 base::Bind(
2875 &ExtensionService::TrackTerminatedExtension, 2301 &ExtensionService::TrackTerminatedExtension,
2876 weak_ptr_factory_.GetWeakPtr(), 2302 AsWeakPtr(),
2877 host->extension())); 2303 host->extension()));
2878 break; 2304 break;
2879 } 2305 }
2880 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { 2306 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
2881 RenderProcessHost* process = 2307 RenderProcessHost* process =
2882 content::Source<RenderProcessHost>(source).ptr(); 2308 content::Source<RenderProcessHost>(source).ptr();
2883 Profile* host_profile = 2309 Profile* host_profile =
2884 Profile::FromBrowserContext(process->browser_context()); 2310 Profile::FromBrowserContext(process->browser_context());
2885 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) 2311 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile()))
2886 break; 2312 break;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 ExtensionIdSet result; 2369 ExtensionIdSet result;
2944 for (ExtensionList::const_iterator it = extensions_.begin(); 2370 for (ExtensionList::const_iterator it = extensions_.begin();
2945 it != extensions_.end(); ++it) { 2371 it != extensions_.end(); ++it) {
2946 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) 2372 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT)
2947 result.insert((*it)->id()); 2373 result.insert((*it)->id());
2948 } 2374 }
2949 2375
2950 return result; 2376 return result;
2951 } 2377 }
2952 2378
2953 scoped_refptr<CrxInstaller> ExtensionService::MakeCrxInstaller(
2954 ExtensionInstallUI* client) {
2955 return new CrxInstaller(weak_ptr_factory_.GetWeakPtr(), client);
2956 }
2957
2958 bool ExtensionService::IsBackgroundPageReady(const Extension* extension) { 2379 bool ExtensionService::IsBackgroundPageReady(const Extension* extension) {
2959 return (extension->background_url().is_empty() || 2380 return (extension->background_url().is_empty() ||
2960 extension_runtime_data_[extension->id()].background_page_ready); 2381 extension_runtime_data_[extension->id()].background_page_ready);
2961 } 2382 }
2962 2383
2963 void ExtensionService::SetBackgroundPageReady(const Extension* extension) { 2384 void ExtensionService::SetBackgroundPageReady(const Extension* extension) {
2964 DCHECK(!extension->background_url().is_empty()); 2385 DCHECK(!extension->background_url().is_empty());
2965 extension_runtime_data_[extension->id()].background_page_ready = true; 2386 extension_runtime_data_[extension->id()].background_page_ready = true;
2966 content::NotificationService::current()->Notify( 2387 content::NotificationService::current()->Notify(
2967 chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, 2388 chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3060 2481
3061 ExtensionService::NaClModuleInfoList::iterator 2482 ExtensionService::NaClModuleInfoList::iterator
3062 ExtensionService::FindNaClModule(const GURL& url) { 2483 ExtensionService::FindNaClModule(const GURL& url) {
3063 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin(); 2484 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin();
3064 iter != nacl_module_list_.end(); ++iter) { 2485 iter != nacl_module_list_.end(); ++iter) {
3065 if (iter->url == url) 2486 if (iter->url == url)
3066 return iter; 2487 return iter;
3067 } 2488 }
3068 return nacl_module_list_.end(); 2489 return nacl_module_list_.end();
3069 } 2490 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698