| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |