| OLD | NEW |
| 1 // Copyright (c) 2010 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 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
| 14 #include "base/string16.h" | 14 #include "base/string16.h" |
| 15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
| 18 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
| 19 #include "base/time.h" | 19 #include "base/time.h" |
| 20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 #include "base/values_util.h" | |
| 23 #include "base/version.h" | 22 #include "base/version.h" |
| 24 #include "chrome/browser/browser_process.h" | 23 #include "chrome/browser/browser_process.h" |
| 25 #include "chrome/browser/themes/browser_theme_provider.h" | 24 #include "chrome/browser/themes/browser_theme_provider.h" |
| 26 #include "chrome/browser/browser_thread.h" | 25 #include "chrome/browser/browser_thread.h" |
| 27 #include "chrome/browser/debugger/devtools_manager.h" | 26 #include "chrome/browser/debugger/devtools_manager.h" |
| 28 #include "chrome/browser/dom_ui/shown_sections_handler.h" | 27 #include "chrome/browser/dom_ui/shown_sections_handler.h" |
| 29 #include "chrome/browser/extensions/crx_installer.h" | 28 #include "chrome/browser/extensions/crx_installer.h" |
| 30 #include "chrome/browser/extensions/default_apps.h" | 29 #include "chrome/browser/extensions/default_apps.h" |
| 31 #include "chrome/browser/extensions/extension_accessibility_api.h" | 30 #include "chrome/browser/extensions/extension_accessibility_api.h" |
| 32 #include "chrome/browser/extensions/extension_bookmarks_module.h" | 31 #include "chrome/browser/extensions/extension_bookmarks_module.h" |
| 33 #include "chrome/browser/extensions/extension_browser_event_router.h" | 32 #include "chrome/browser/extensions/extension_browser_event_router.h" |
| 34 #include "chrome/browser/extensions/extension_cookies_api.h" | 33 #include "chrome/browser/extensions/extension_cookies_api.h" |
| 35 #include "chrome/browser/extensions/extension_data_deleter.h" | 34 #include "chrome/browser/extensions/extension_data_deleter.h" |
| 36 #include "chrome/browser/extensions/extension_dom_ui.h" | 35 #include "chrome/browser/extensions/extension_dom_ui.h" |
| 37 #include "chrome/browser/extensions/extension_error_reporter.h" | 36 #include "chrome/browser/extensions/extension_error_reporter.h" |
| 38 #include "chrome/browser/extensions/extension_history_api.h" | 37 #include "chrome/browser/extensions/extension_history_api.h" |
| 39 #include "chrome/browser/extensions/extension_host.h" | 38 #include "chrome/browser/extensions/extension_host.h" |
| 40 #include "chrome/browser/extensions/extension_management_api.h" | 39 #include "chrome/browser/extensions/extension_management_api.h" |
| 41 #include "chrome/browser/extensions/extension_process_manager.h" | 40 #include "chrome/browser/extensions/extension_process_manager.h" |
| 42 #include "chrome/browser/extensions/extension_processes_api.h" | 41 #include "chrome/browser/extensions/extension_processes_api.h" |
| 43 #include "chrome/browser/extensions/extension_updater.h" | 42 #include "chrome/browser/extensions/extension_updater.h" |
| 44 #include "chrome/browser/extensions/extension_webnavigation_api.h" | 43 #include "chrome/browser/extensions/extension_webnavigation_api.h" |
| 45 #include "chrome/browser/extensions/external_extension_provider.h" | 44 #include "chrome/browser/extensions/external_extension_provider_interface.h" |
| 46 #include "chrome/browser/extensions/external_policy_extension_provider.h" | 45 #include "chrome/browser/extensions/external_extension_provider_impl.h" |
| 47 #include "chrome/browser/extensions/external_pref_extension_provider.h" | |
| 48 #include "chrome/browser/net/chrome_url_request_context.h" | 46 #include "chrome/browser/net/chrome_url_request_context.h" |
| 49 #include "chrome/browser/prefs/pref_service.h" | 47 #include "chrome/browser/prefs/pref_service.h" |
| 50 #include "chrome/browser/profiles/profile.h" | 48 #include "chrome/browser/profiles/profile.h" |
| 51 #include "chrome/browser/search_engines/template_url_model.h" | 49 #include "chrome/browser/search_engines/template_url_model.h" |
| 52 #include "chrome/common/child_process_logging.h" | 50 #include "chrome/common/child_process_logging.h" |
| 53 #include "chrome/common/chrome_switches.h" | 51 #include "chrome/common/chrome_switches.h" |
| 54 #include "chrome/common/extensions/extension.h" | 52 #include "chrome/common/extensions/extension.h" |
| 55 #include "chrome/common/extensions/extension_constants.h" | 53 #include "chrome/common/extensions/extension_constants.h" |
| 56 #include "chrome/common/extensions/extension_error_utils.h" | 54 #include "chrome/common/extensions/extension_error_utils.h" |
| 57 #include "chrome/common/extensions/extension_file_util.h" | 55 #include "chrome/common/extensions/extension_file_util.h" |
| 58 #include "chrome/common/extensions/extension_l10n_util.h" | 56 #include "chrome/common/extensions/extension_l10n_util.h" |
| 59 #include "chrome/common/extensions/extension_resource.h" | 57 #include "chrome/common/extensions/extension_resource.h" |
| 60 #include "chrome/common/notification_service.h" | 58 #include "chrome/common/notification_service.h" |
| 61 #include "chrome/common/notification_type.h" | 59 #include "chrome/common/notification_type.h" |
| 62 #include "chrome/common/json_value_serializer.h" | 60 #include "chrome/common/json_value_serializer.h" |
| 63 #include "chrome/common/pref_names.h" | 61 #include "chrome/common/pref_names.h" |
| 64 #include "chrome/common/url_constants.h" | 62 #include "chrome/common/url_constants.h" |
| 65 #include "googleurl/src/gurl.h" | 63 #include "googleurl/src/gurl.h" |
| 66 #include "net/base/registry_controlled_domain.h" | 64 #include "net/base/registry_controlled_domain.h" |
| 67 #include "webkit/database/database_tracker.h" | 65 #include "webkit/database/database_tracker.h" |
| 68 #include "webkit/database/database_util.h" | 66 #include "webkit/database/database_util.h" |
| 69 | 67 |
| 70 #if defined(OS_WIN) | |
| 71 #include "chrome/browser/extensions/external_registry_extension_provider_win.h" | |
| 72 #endif | |
| 73 | |
| 74 using base::Time; | 68 using base::Time; |
| 75 | 69 |
| 76 namespace errors = extension_manifest_errors; | 70 namespace errors = extension_manifest_errors; |
| 77 | 71 |
| 78 namespace { | 72 namespace { |
| 79 | 73 |
| 80 #if defined(OS_LINUX) | 74 #if defined(OS_LINUX) |
| 81 static const int kOmniboxIconPaddingLeft = 2; | 75 static const int kOmniboxIconPaddingLeft = 2; |
| 82 static const int kOmniboxIconPaddingRight = 2; | 76 static const int kOmniboxIconPaddingRight = 2; |
| 83 #elif defined(OS_MACOSX) | 77 #elif defined(OS_MACOSX) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 } | 171 } |
| 178 | 172 |
| 179 // ExtensionService. | 173 // ExtensionService. |
| 180 | 174 |
| 181 const char* ExtensionService::kInstallDirectoryName = "Extensions"; | 175 const char* ExtensionService::kInstallDirectoryName = "Extensions"; |
| 182 const char* ExtensionService::kCurrentVersionFileName = "Current Version"; | 176 const char* ExtensionService::kCurrentVersionFileName = "Current Version"; |
| 183 | 177 |
| 184 // Implements IO for the ExtensionService. | 178 // Implements IO for the ExtensionService. |
| 185 | 179 |
| 186 class ExtensionServiceBackend | 180 class ExtensionServiceBackend |
| 187 : public base::RefCountedThreadSafe<ExtensionServiceBackend>, | 181 : public base::RefCountedThreadSafe<ExtensionServiceBackend> { |
| 188 public ExternalExtensionProvider::Visitor { | |
| 189 public: | 182 public: |
| 190 // |install_directory| is a path where to look for extensions to load. | 183 // |install_directory| is a path where to look for extensions to load. |
| 191 ExtensionServiceBackend(PrefService* prefs, | 184 explicit ExtensionServiceBackend(const FilePath& install_directory); |
| 192 const FilePath& install_directory); | |
| 193 | 185 |
| 194 // Loads a single extension from |path| where |path| is the top directory of | 186 // Loads a single extension from |path| where |path| is the top directory of |
| 195 // a specific extension where its manifest file lives. | 187 // a specific extension where its manifest file lives. |
| 196 // Errors are reported through ExtensionErrorReporter. On success, | 188 // Errors are reported through ExtensionErrorReporter. On success, |
| 197 // OnExtensionLoaded() is called. | 189 // OnExtensionLoaded() is called. |
| 198 // TODO(erikkay): It might be useful to be able to load a packed extension | 190 // TODO(erikkay): It might be useful to be able to load a packed extension |
| 199 // (presumably into memory) without installing it. | 191 // (presumably into memory) without installing it. |
| 200 void LoadSingleExtension(const FilePath &path, | 192 void LoadSingleExtension(const FilePath &path, |
| 201 scoped_refptr<ExtensionService> frontend); | 193 scoped_refptr<ExtensionService> frontend); |
| 202 | 194 |
| 203 // Check externally updated extensions for updates and install if necessary. | |
| 204 // Errors are reported through ExtensionErrorReporter. Succcess is not | |
| 205 // reported. | |
| 206 void CheckForExternalUpdates(scoped_refptr<ExtensionService> frontend); | |
| 207 | |
| 208 // For the extension in |version_path| with |id|, check to see if it's an | |
| 209 // externally managed extension. If so, tell the frontend to uninstall it. | |
| 210 void CheckExternalUninstall(scoped_refptr<ExtensionService> frontend, | |
| 211 const std::string& id); | |
| 212 | |
| 213 // Clear all ExternalExtensionProviders. | |
| 214 void ClearProvidersForTesting(); | |
| 215 | |
| 216 // Adds an ExternalExtensionProvider for the service to use during testing. | |
| 217 // Takes ownership of |test_provider|. | |
| 218 void AddProviderForTesting(ExternalExtensionProvider* test_provider); | |
| 219 | |
| 220 // ExternalExtensionProvider::Visitor implementation. | |
| 221 virtual void OnExternalExtensionFileFound(const std::string& id, | |
| 222 const Version* version, | |
| 223 const FilePath& path, | |
| 224 Extension::Location location); | |
| 225 | |
| 226 virtual void OnExternalExtensionUpdateUrlFound(const std::string& id, | |
| 227 const GURL& update_url, | |
| 228 Extension::Location location); | |
| 229 | |
| 230 virtual void UpdateExternalPolicyExtensionProvider( | |
| 231 scoped_refptr<RefCountedList> forcelist); | |
| 232 | |
| 233 private: | 195 private: |
| 234 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>; | 196 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>; |
| 235 | 197 |
| 236 virtual ~ExtensionServiceBackend(); | 198 virtual ~ExtensionServiceBackend(); |
| 237 | 199 |
| 238 // Finish installing the extension in |crx_path| after it has been unpacked to | 200 // Finish installing the extension in |crx_path| after it has been unpacked to |
| 239 // |unpacked_path|. If |expected_id| is not empty, it's verified against the | 201 // |unpacked_path|. If |expected_id| is not empty, it's verified against the |
| 240 // extension's manifest before installation. If |silent| is true, there will | 202 // extension's manifest before installation. If |silent| is true, there will |
| 241 // be no install confirmation dialog. |from_gallery| indicates whether the | 203 // be no install confirmation dialog. |from_gallery| indicates whether the |
| 242 // crx was installed from our gallery, which results in different UI. | 204 // crx was installed from our gallery, which results in different UI. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 254 // This is a naked pointer which is set by each entry point. | 216 // This is a naked pointer which is set by each entry point. |
| 255 // The entry point is responsible for ensuring lifetime. | 217 // The entry point is responsible for ensuring lifetime. |
| 256 ExtensionService* frontend_; | 218 ExtensionService* frontend_; |
| 257 | 219 |
| 258 // The top-level extensions directory being installed to. | 220 // The top-level extensions directory being installed to. |
| 259 FilePath install_directory_; | 221 FilePath install_directory_; |
| 260 | 222 |
| 261 // Whether errors result in noisy alerts. | 223 // Whether errors result in noisy alerts. |
| 262 bool alert_on_error_; | 224 bool alert_on_error_; |
| 263 | 225 |
| 264 // A collection of external extension providers. Each provider reads | |
| 265 // a source of external extension information. Examples include the | |
| 266 // windows registry and external_extensions.json. | |
| 267 typedef std::vector<linked_ptr<ExternalExtensionProvider> > | |
| 268 ProviderCollection; | |
| 269 ProviderCollection external_extension_providers_; | |
| 270 linked_ptr<ExternalPolicyExtensionProvider> | |
| 271 external_policy_extension_provider_; | |
| 272 | |
| 273 // Set to true by OnExternalExtensionUpdateUrlFound() when an external | |
| 274 // extension URL is found. Used in CheckForExternalUpdates() to see | |
| 275 // if an update check is needed to install pending extensions. | |
| 276 bool external_extension_added_; | |
| 277 | |
| 278 DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend); | 226 DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend); |
| 279 }; | 227 }; |
| 280 | 228 |
| 281 ExtensionServiceBackend::ExtensionServiceBackend( | 229 ExtensionServiceBackend::ExtensionServiceBackend( |
| 282 PrefService* prefs, | |
| 283 const FilePath& install_directory) | 230 const FilePath& install_directory) |
| 284 : frontend_(NULL), | 231 : frontend_(NULL), |
| 285 install_directory_(install_directory), | 232 install_directory_(install_directory), |
| 286 alert_on_error_(false), | 233 alert_on_error_(false) { |
| 287 external_extension_added_(false) { | |
| 288 // TODO(aa): This ends up doing blocking IO on the UI thread because it reads | |
| 289 // pref data in the ctor and that is called on the UI thread. Would be better | |
| 290 // to re-read data each time we list external extensions, anyway. | |
| 291 external_extension_providers_.push_back( | |
| 292 linked_ptr<ExternalExtensionProvider>( | |
| 293 new ExternalPrefExtensionProvider())); | |
| 294 #if defined(OS_WIN) | |
| 295 external_extension_providers_.push_back( | |
| 296 linked_ptr<ExternalExtensionProvider>( | |
| 297 new ExternalRegistryExtensionProvider())); | |
| 298 #endif | |
| 299 // The policy-controlled extension provider is also stored in a member | |
| 300 // variable so that UpdateExternalPolicyExtensionProvider can access it and | |
| 301 // update its extension list later. | |
| 302 external_policy_extension_provider_.reset( | |
| 303 new ExternalPolicyExtensionProvider( | |
| 304 prefs->GetList(prefs::kExtensionInstallForceList))); | |
| 305 external_extension_providers_.push_back(external_policy_extension_provider_); | |
| 306 } | 234 } |
| 307 | 235 |
| 308 ExtensionServiceBackend::~ExtensionServiceBackend() { | 236 ExtensionServiceBackend::~ExtensionServiceBackend() { |
| 309 } | 237 } |
| 310 | 238 |
| 311 void ExtensionServiceBackend::LoadSingleExtension( | 239 void ExtensionServiceBackend::LoadSingleExtension( |
| 312 const FilePath& path_in, scoped_refptr<ExtensionService> frontend) { | 240 const FilePath& path_in, scoped_refptr<ExtensionService> frontend) { |
| 313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 314 | 242 |
| 315 frontend_ = frontend; | 243 frontend_ = frontend; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 345 const FilePath& extension_path, const std::string &error) { | 273 const FilePath& extension_path, const std::string &error) { |
| 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 347 BrowserThread::PostTask( | 275 BrowserThread::PostTask( |
| 348 BrowserThread::UI, FROM_HERE, | 276 BrowserThread::UI, FROM_HERE, |
| 349 NewRunnableMethod( | 277 NewRunnableMethod( |
| 350 frontend_, | 278 frontend_, |
| 351 &ExtensionService::ReportExtensionLoadError, extension_path, | 279 &ExtensionService::ReportExtensionLoadError, extension_path, |
| 352 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); | 280 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); |
| 353 } | 281 } |
| 354 | 282 |
| 355 // Some extensions will autoupdate themselves externally from Chrome. These | 283 void ExtensionService::CheckExternalUninstall(const std::string& id) { |
| 356 // are typically part of some larger client application package. To support | 284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 357 // these, the extension will register its location in the the preferences file | |
| 358 // (and also, on Windows, in the registry) and this code will periodically | |
| 359 // check that location for a .crx file, which it will then install locally if | |
| 360 // a new version is available. | |
| 361 void ExtensionServiceBackend::CheckForExternalUpdates( | |
| 362 scoped_refptr<ExtensionService> frontend) { | |
| 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 364 | |
| 365 // Note that this installation is intentionally silent (since it didn't | |
| 366 // go through the front-end). Extensions that are registered in this | |
| 367 // way are effectively considered 'pre-bundled', and so implicitly | |
| 368 // trusted. In general, if something has HKLM or filesystem access, | |
| 369 // they could install an extension manually themselves anyway. | |
| 370 alert_on_error_ = false; | |
| 371 frontend_ = frontend; | |
| 372 external_extension_added_ = false; | |
| 373 | |
| 374 // Ask each external extension provider to give us a call back for each | |
| 375 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. | |
| 376 ProviderCollection::const_iterator i; | |
| 377 for (i = external_extension_providers_.begin(); | |
| 378 i != external_extension_providers_.end(); ++i) { | |
| 379 ExternalExtensionProvider* provider = i->get(); | |
| 380 provider->VisitRegisteredExtension(this); | |
| 381 } | |
| 382 | |
| 383 if (external_extension_added_ && frontend->updater()) { | |
| 384 BrowserThread::PostTask( | |
| 385 BrowserThread::UI, FROM_HERE, | |
| 386 NewRunnableMethod( | |
| 387 frontend->updater(), &ExtensionUpdater::CheckNow)); | |
| 388 } | |
| 389 } | |
| 390 | |
| 391 void ExtensionServiceBackend::CheckExternalUninstall( | |
| 392 scoped_refptr<ExtensionService> frontend, const std::string& id) { | |
| 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 394 | 285 |
| 395 // Check if the providers know about this extension. | 286 // Check if the providers know about this extension. |
| 396 ProviderCollection::const_iterator i; | 287 ProviderCollection::const_iterator i; |
| 397 for (i = external_extension_providers_.begin(); | 288 for (i = external_extension_providers_.begin(); |
| 398 i != external_extension_providers_.end(); ++i) { | 289 i != external_extension_providers_.end(); ++i) { |
| 290 DCHECK(i->get()->IsReady()); |
| 399 if (i->get()->HasExtension(id)) | 291 if (i->get()->HasExtension(id)) |
| 400 return; // Yup, known extension, don't uninstall. | 292 return; // Yup, known extension, don't uninstall. |
| 401 } | 293 } |
| 402 | 294 |
| 403 // This is an external extension that we don't have registered. Uninstall. | 295 // This is an external extension that we don't have registered. Uninstall. |
| 404 BrowserThread::PostTask( | 296 UninstallExtension(id, true); |
| 405 BrowserThread::UI, FROM_HERE, | |
| 406 NewRunnableMethod( | |
| 407 frontend.get(), &ExtensionService::UninstallExtension, id, true)); | |
| 408 } | 297 } |
| 409 | 298 |
| 410 void ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider( | 299 void ExtensionService::ClearProvidersForTesting() { |
| 411 scoped_refptr<RefCountedList> forcelist) { | |
| 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 413 external_policy_extension_provider_->SetPreferences(forcelist->Get()); | |
| 414 } | |
| 415 | |
| 416 void ExtensionServiceBackend::ClearProvidersForTesting() { | |
| 417 external_extension_providers_.clear(); | 300 external_extension_providers_.clear(); |
| 418 } | 301 } |
| 419 | 302 |
| 420 void ExtensionServiceBackend::AddProviderForTesting( | 303 void ExtensionService::AddProviderForTesting( |
| 421 ExternalExtensionProvider* test_provider) { | 304 ExternalExtensionProviderInterface* test_provider) { |
| 422 DCHECK(test_provider); | 305 DCHECK(test_provider); |
| 423 external_extension_providers_.push_back( | 306 external_extension_providers_.push_back( |
| 424 linked_ptr<ExternalExtensionProvider>(test_provider)); | 307 linked_ptr<ExternalExtensionProviderInterface>(test_provider)); |
| 425 } | 308 } |
| 426 | 309 |
| 427 void ExtensionServiceBackend::OnExternalExtensionFileFound( | 310 void ExtensionService::OnExternalExtensionUpdateUrlFound( |
| 428 const std::string& id, const Version* version, const FilePath& path, | |
| 429 Extension::Location location) { | |
| 430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 431 | |
| 432 DCHECK(version); | |
| 433 BrowserThread::PostTask( | |
| 434 BrowserThread::UI, FROM_HERE, | |
| 435 NewRunnableMethod( | |
| 436 frontend_, &ExtensionService::OnExternalExtensionFileFound, id, | |
| 437 version->GetString(), path, location)); | |
| 438 } | |
| 439 | |
| 440 void ExtensionServiceBackend::OnExternalExtensionUpdateUrlFound( | |
| 441 const std::string& id, | 311 const std::string& id, |
| 442 const GURL& update_url, | 312 const GURL& update_url, |
| 443 Extension::Location location) { | 313 Extension::Location location) { |
| 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 445 | 315 |
| 446 if (frontend_->GetExtensionById(id, true)) { | 316 if (GetExtensionById(id, true)) { |
| 447 // Already installed. Do not change the update URL that the extension set. | 317 // Already installed. Do not change the update URL that the extension set. |
| 448 return; | 318 return; |
| 449 } | 319 } |
| 450 | 320 AddPendingExtensionFromExternalUpdateUrl(id, update_url, location); |
| 451 BrowserThread::PostTask( | |
| 452 BrowserThread::UI, FROM_HERE, | |
| 453 NewRunnableMethod( | |
| 454 frontend_, | |
| 455 &ExtensionService::AddPendingExtensionFromExternalUpdateUrl, | |
| 456 id, update_url, location)); | |
| 457 external_extension_added_ |= true; | 321 external_extension_added_ |= true; |
| 458 } | 322 } |
| 459 | 323 |
| 460 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url, | 324 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url, |
| 461 const GURL& referrer_url) { | 325 const GURL& referrer_url) { |
| 462 // Special-case the themes mini-gallery. | 326 // Special-case the themes mini-gallery. |
| 463 // TODO(erikkay) When that gallery goes away, remove this code. | 327 // TODO(erikkay) When that gallery goes away, remove this code. |
| 464 if (IsDownloadFromMiniGallery(download_url) && | 328 if (IsDownloadFromMiniGallery(download_url) && |
| 465 StartsWithASCII(referrer_url.spec(), | 329 StartsWithASCII(referrer_url.spec(), |
| 466 extension_urls::kMiniGalleryBrowsePrefix, false)) { | 330 extension_urls::kMiniGalleryBrowsePrefix, false)) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 extensions_enabled_ = false; | 427 extensions_enabled_ = false; |
| 564 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { | 428 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { |
| 565 extensions_enabled_ = false; | 429 extensions_enabled_ = false; |
| 566 } | 430 } |
| 567 | 431 |
| 568 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, | 432 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, |
| 569 NotificationService::AllSources()); | 433 NotificationService::AllSources()); |
| 570 pref_change_registrar_.Init(profile->GetPrefs()); | 434 pref_change_registrar_.Init(profile->GetPrefs()); |
| 571 pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this); | 435 pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this); |
| 572 pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this); | 436 pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this); |
| 573 pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this); | |
| 574 | 437 |
| 575 // Set up the ExtensionUpdater | 438 // Set up the ExtensionUpdater |
| 576 if (autoupdate_enabled) { | 439 if (autoupdate_enabled) { |
| 577 int update_frequency = kDefaultUpdateFrequencySeconds; | 440 int update_frequency = kDefaultUpdateFrequencySeconds; |
| 578 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { | 441 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { |
| 579 base::StringToInt(command_line->GetSwitchValueASCII( | 442 base::StringToInt(command_line->GetSwitchValueASCII( |
| 580 switches::kExtensionsUpdateFrequency), | 443 switches::kExtensionsUpdateFrequency), |
| 581 &update_frequency); | 444 &update_frequency); |
| 582 } | 445 } |
| 583 updater_ = new ExtensionUpdater(this, | 446 updater_ = new ExtensionUpdater(this, |
| 584 profile->GetPrefs(), | 447 profile->GetPrefs(), |
| 585 update_frequency); | 448 update_frequency); |
| 586 } | 449 } |
| 587 | 450 |
| 588 backend_ = new ExtensionServiceBackend(profile->GetPrefs(), | 451 backend_ = new ExtensionServiceBackend(install_directory_); |
| 589 install_directory_); | 452 |
| 453 ExternalExtensionProviderImpl::CreateExternalProviders( |
| 454 this, profile_, &external_extension_providers_); |
| 590 | 455 |
| 591 // Use monochrome icons for Omnibox icons. | 456 // Use monochrome icons for Omnibox icons. |
| 592 omnibox_popup_icon_manager_.set_monochrome(true); | 457 omnibox_popup_icon_manager_.set_monochrome(true); |
| 593 omnibox_icon_manager_.set_monochrome(true); | 458 omnibox_icon_manager_.set_monochrome(true); |
| 594 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, | 459 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, |
| 595 0, kOmniboxIconPaddingRight)); | 460 0, kOmniboxIconPaddingRight)); |
| 596 } | 461 } |
| 597 | 462 |
| 598 const ExtensionList* ExtensionService::extensions() const { | 463 const ExtensionList* ExtensionService::extensions() const { |
| 599 return &extensions_; | 464 return &extensions_; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 614 bool ExtensionService::HasInstalledExtensions() { | 479 bool ExtensionService::HasInstalledExtensions() { |
| 615 return !(extensions_.empty() && disabled_extensions_.empty()); | 480 return !(extensions_.empty() && disabled_extensions_.empty()); |
| 616 } | 481 } |
| 617 | 482 |
| 618 ExtensionService::~ExtensionService() { | 483 ExtensionService::~ExtensionService() { |
| 619 DCHECK(!profile_); // Profile should have told us it's going away. | 484 DCHECK(!profile_); // Profile should have told us it's going away. |
| 620 UnloadAllExtensions(); | 485 UnloadAllExtensions(); |
| 621 if (updater_.get()) { | 486 if (updater_.get()) { |
| 622 updater_->Stop(); | 487 updater_->Stop(); |
| 623 } | 488 } |
| 489 ProviderCollection::const_iterator i; |
| 490 for (i = external_extension_providers_.begin(); |
| 491 i != external_extension_providers_.end(); ++i) { |
| 492 ExternalExtensionProviderInterface* provider = i->get(); |
| 493 provider->ServiceShutdown(); |
| 494 } |
| 624 } | 495 } |
| 625 | 496 |
| 626 void ExtensionService::InitEventRouters() { | 497 void ExtensionService::InitEventRouters() { |
| 627 if (event_routers_initialized_) | 498 if (event_routers_initialized_) |
| 628 return; | 499 return; |
| 629 | 500 |
| 630 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); | 501 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); |
| 631 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); | 502 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); |
| 632 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); | 503 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); |
| 633 ExtensionBookmarkEventRouter::GetInstance()->Observe( | 504 ExtensionBookmarkEventRouter::GetInstance()->Observe( |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 error, | 1069 error, |
| 1199 NotificationType::EXTENSION_INSTALL_ERROR, | 1070 NotificationType::EXTENSION_INSTALL_ERROR, |
| 1200 false); | 1071 false); |
| 1201 return; | 1072 return; |
| 1202 } | 1073 } |
| 1203 | 1074 |
| 1204 if (write_to_prefs) | 1075 if (write_to_prefs) |
| 1205 extension_prefs_->UpdateManifest(extension); | 1076 extension_prefs_->UpdateManifest(extension); |
| 1206 | 1077 |
| 1207 OnExtensionLoaded(extension); | 1078 OnExtensionLoaded(extension); |
| 1208 | |
| 1209 if (Extension::IsExternalLocation(info.extension_location)) { | |
| 1210 BrowserThread::PostTask( | |
| 1211 BrowserThread::FILE, FROM_HERE, | |
| 1212 NewRunnableMethod( | |
| 1213 backend_.get(), | |
| 1214 &ExtensionServiceBackend::CheckExternalUninstall, | |
| 1215 scoped_refptr<ExtensionService>(this), | |
| 1216 info.extension_id)); | |
| 1217 } | |
| 1218 } | 1079 } |
| 1219 | 1080 |
| 1220 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { | 1081 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { |
| 1221 // The ChromeURLRequestContexts need to be first to know that the extension | 1082 // The ChromeURLRequestContexts need to be first to know that the extension |
| 1222 // was loaded, otherwise a race can arise where a renderer that is created | 1083 // was loaded, otherwise a race can arise where a renderer that is created |
| 1223 // for the extension may try to load an extension URL with an extension id | 1084 // for the extension may try to load an extension URL with an extension id |
| 1224 // that the request context doesn't yet know about. The profile is responsible | 1085 // that the request context doesn't yet know about. The profile is responsible |
| 1225 // for ensuring its URLRequestContexts appropriately discover the loaded | 1086 // for ensuring its URLRequestContexts appropriately discover the loaded |
| 1226 // extension. | 1087 // extension. |
| 1227 if (profile_) { | 1088 if (profile_) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 NotificationType::EXTENSION_USER_SCRIPTS_UPDATED, | 1314 NotificationType::EXTENSION_USER_SCRIPTS_UPDATED, |
| 1454 Source<Profile>(profile_), | 1315 Source<Profile>(profile_), |
| 1455 Details<const Extension>(extension)); | 1316 Details<const Extension>(extension)); |
| 1456 } | 1317 } |
| 1457 | 1318 |
| 1458 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { | 1319 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { |
| 1459 return extension_prefs_->GetBrowserActionVisibility(extension); | 1320 return extension_prefs_->GetBrowserActionVisibility(extension); |
| 1460 } | 1321 } |
| 1461 | 1322 |
| 1462 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, | 1323 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, |
| 1463 bool visible) { | 1324 bool visible) { |
| 1464 extension_prefs_->SetBrowserActionVisibility(extension, visible); | 1325 extension_prefs_->SetBrowserActionVisibility(extension, visible); |
| 1465 } | 1326 } |
| 1466 | 1327 |
| 1328 // Some extensions will autoupdate themselves externally from Chrome. These |
| 1329 // are typically part of some larger client application package. To support |
| 1330 // these, the extension will register its location in the the preferences file |
| 1331 // (and also, on Windows, in the registry) and this code will periodically |
| 1332 // check that location for a .crx file, which it will then install locally if |
| 1333 // a new version is available. |
| 1334 // Errors are reported through ExtensionErrorReporter. Succcess is not |
| 1335 // reported. |
| 1467 void ExtensionService::CheckForExternalUpdates() { | 1336 void ExtensionService::CheckForExternalUpdates() { |
| 1468 BrowserThread::PostTask( | 1337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1469 BrowserThread::FILE, FROM_HERE, | 1338 |
| 1470 NewRunnableMethod( | 1339 // Note that this installation is intentionally silent (since it didn't |
| 1471 backend_.get(), &ExtensionServiceBackend::CheckForExternalUpdates, | 1340 // go through the front-end). Extensions that are registered in this |
| 1472 scoped_refptr<ExtensionService>(this))); | 1341 // way are effectively considered 'pre-bundled', and so implicitly |
| 1342 // trusted. In general, if something has HKLM or filesystem access, |
| 1343 // they could install an extension manually themselves anyway. |
| 1344 external_extension_added_ = false; |
| 1345 |
| 1346 // Ask each external extension provider to give us a call back for each |
| 1347 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. |
| 1348 ProviderCollection::const_iterator i; |
| 1349 for (i = external_extension_providers_.begin(); |
| 1350 i != external_extension_providers_.end(); ++i) { |
| 1351 ExternalExtensionProviderInterface* provider = i->get(); |
| 1352 provider->VisitRegisteredExtension(); |
| 1353 } |
| 1354 |
| 1355 // Uninstall of unclaimed extensions will happen after all the providers |
| 1356 // had reported ready. Trigger uninstall even if there are no providers |
| 1357 // installed: |
| 1358 OnExternalProviderReady(); |
| 1473 } | 1359 } |
| 1474 | 1360 |
| 1475 void ExtensionService::UpdateExternalPolicyExtensionProvider() { | 1361 void ExtensionService::OnExternalProviderReady() { |
| 1476 const ListValue* list_pref = | 1362 // An external provider has finished loading. We only take action |
| 1477 profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList); | 1363 // if all of them are finished. So we check them first. |
| 1478 ListValue* list_copy = NULL; | 1364 ProviderCollection::const_iterator i; |
| 1479 if (list_pref) | 1365 for (i = external_extension_providers_.begin(); |
| 1480 list_copy = static_cast<ListValue*>(list_pref->DeepCopy()); | 1366 i != external_extension_providers_.end(); ++i) { |
| 1481 BrowserThread::PostTask( | 1367 ExternalExtensionProviderInterface* provider = i->get(); |
| 1482 BrowserThread::FILE, FROM_HERE, | 1368 if (!provider->IsReady()) { |
| 1483 NewRunnableMethod( | 1369 return; |
| 1484 backend_.get(), | 1370 } |
| 1485 &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider, | 1371 } |
| 1486 scoped_refptr<RefCountedList>( | 1372 |
| 1487 new RefCountedList(list_copy)))); | 1373 // All the providers are ready. Install any pending extensions. |
| 1374 if (external_extension_added_ && updater()) { |
| 1375 external_extension_added_ = false; |
| 1376 updater()->CheckNow(); |
| 1377 } |
| 1378 |
| 1379 // Uninstall all the unclaimed extensions. |
| 1380 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
| 1381 extension_prefs_->GetInstalledExtensionsInfo()); |
| 1382 for (size_t i = 0; i < extensions_info->size(); ++i) { |
| 1383 ExtensionInfo* info = extensions_info->at(i).get(); |
| 1384 if (Extension::IsExternalLocation(info->extension_location)) |
| 1385 CheckExternalUninstall(info->extension_id); |
| 1386 } |
| 1488 } | 1387 } |
| 1489 | 1388 |
| 1490 void ExtensionService::UnloadExtension( | 1389 void ExtensionService::UnloadExtension( |
| 1491 const std::string& extension_id, | 1390 const std::string& extension_id, |
| 1492 UnloadedExtensionInfo::Reason reason) { | 1391 UnloadedExtensionInfo::Reason reason) { |
| 1493 // Make sure the extension gets deleted after we return from this function. | 1392 // Make sure the extension gets deleted after we return from this function. |
| 1494 scoped_refptr<const Extension> extension( | 1393 scoped_refptr<const Extension> extension( |
| 1495 GetExtensionByIdInternal(extension_id, true, true)); | 1394 GetExtensionByIdInternal(extension_id, true, true)); |
| 1496 | 1395 |
| 1497 // This method can be called via PostTask, so the extension may have been | 1396 // This method can be called via PostTask, so the extension may have been |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1912 const SkBitmap& ExtensionService::GetOmniboxIcon( | 1811 const SkBitmap& ExtensionService::GetOmniboxIcon( |
| 1913 const std::string& extension_id) { | 1812 const std::string& extension_id) { |
| 1914 return omnibox_icon_manager_.GetIcon(extension_id); | 1813 return omnibox_icon_manager_.GetIcon(extension_id); |
| 1915 } | 1814 } |
| 1916 | 1815 |
| 1917 const SkBitmap& ExtensionService::GetOmniboxPopupIcon( | 1816 const SkBitmap& ExtensionService::GetOmniboxPopupIcon( |
| 1918 const std::string& extension_id) { | 1817 const std::string& extension_id) { |
| 1919 return omnibox_popup_icon_manager_.GetIcon(extension_id); | 1818 return omnibox_popup_icon_manager_.GetIcon(extension_id); |
| 1920 } | 1819 } |
| 1921 | 1820 |
| 1922 void ExtensionService::ClearProvidersForTesting() { | |
| 1923 BrowserThread::PostTask( | |
| 1924 BrowserThread::FILE, FROM_HERE, | |
| 1925 NewRunnableMethod( | |
| 1926 backend_.get(), &ExtensionServiceBackend::ClearProvidersForTesting)); | |
| 1927 } | |
| 1928 | |
| 1929 void ExtensionService::AddProviderForTesting( | |
| 1930 ExternalExtensionProvider* test_provider) { | |
| 1931 BrowserThread::PostTask( | |
| 1932 BrowserThread::FILE, FROM_HERE, | |
| 1933 NewRunnableMethod( | |
| 1934 backend_.get(), &ExtensionServiceBackend::AddProviderForTesting, | |
| 1935 test_provider)); | |
| 1936 } | |
| 1937 | |
| 1938 void ExtensionService::OnExternalExtensionFileFound( | 1821 void ExtensionService::OnExternalExtensionFileFound( |
| 1939 const std::string& id, | 1822 const std::string& id, |
| 1940 const std::string& version, | 1823 const Version* version, |
| 1941 const FilePath& path, | 1824 const FilePath& path, |
| 1942 Extension::Location location) { | 1825 Extension::Location location) { |
| 1943 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1826 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1944 if (extension_prefs_->IsExtensionKilled(id)) | 1827 if (extension_prefs_->IsExtensionKilled(id)) |
| 1945 return; | 1828 return; |
| 1946 | 1829 |
| 1830 DCHECK(version); |
| 1831 |
| 1947 // Before even bothering to unpack, check and see if we already have this | 1832 // Before even bothering to unpack, check and see if we already have this |
| 1948 // version. This is important because these extensions are going to get | 1833 // version. This is important because these extensions are going to get |
| 1949 // installed on every startup. | 1834 // installed on every startup. |
| 1950 const Extension* existing = GetExtensionById(id, true); | 1835 const Extension* existing = GetExtensionById(id, true); |
| 1951 scoped_ptr<Version> other(Version::GetVersionFromString(version)); | |
| 1952 if (existing) { | 1836 if (existing) { |
| 1953 switch (existing->version()->CompareTo(*other)) { | 1837 switch (existing->version()->CompareTo(*version)) { |
| 1954 case -1: // existing version is older, we should upgrade | 1838 case -1: // existing version is older, we should upgrade |
| 1955 break; | 1839 break; |
| 1956 case 0: // existing version is same, do nothing | 1840 case 0: // existing version is same, do nothing |
| 1957 return; | 1841 return; |
| 1958 case 1: // existing version is newer, uh-oh | 1842 case 1: // existing version is newer, uh-oh |
| 1959 LOG(WARNING) << "Found external version of extension " << id | 1843 LOG(WARNING) << "Found external version of extension " << id |
| 1960 << "that is older than current version. Current version " | 1844 << "that is older than current version. Current version " |
| 1961 << "is: " << existing->VersionString() << ". New version " | 1845 << "is: " << existing->VersionString() << ". New version " |
| 1962 << "is: " << version << ". Keeping current version."; | 1846 << "is: " << version << ". Keeping current version."; |
| 1963 return; | 1847 return; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 host->extension()->id(), | 1921 host->extension()->id(), |
| 2038 UnloadedExtensionInfo::DISABLE)); | 1922 UnloadedExtensionInfo::DISABLE)); |
| 2039 break; | 1923 break; |
| 2040 } | 1924 } |
| 2041 | 1925 |
| 2042 case NotificationType::PREF_CHANGED: { | 1926 case NotificationType::PREF_CHANGED: { |
| 2043 std::string* pref_name = Details<std::string>(details).ptr(); | 1927 std::string* pref_name = Details<std::string>(details).ptr(); |
| 2044 if (*pref_name == prefs::kExtensionInstallAllowList || | 1928 if (*pref_name == prefs::kExtensionInstallAllowList || |
| 2045 *pref_name == prefs::kExtensionInstallDenyList) { | 1929 *pref_name == prefs::kExtensionInstallDenyList) { |
| 2046 CheckAdminBlacklist(); | 1930 CheckAdminBlacklist(); |
| 2047 } else if (*pref_name == prefs::kExtensionInstallForceList) { | |
| 2048 UpdateExternalPolicyExtensionProvider(); | |
| 2049 CheckForExternalUpdates(); | |
| 2050 // TODO(gfeher): Also check for external extensions that can be | |
| 2051 // uninstalled because they were removed from the pref. | |
| 2052 // (crbug.com/63667) | |
| 2053 } else { | 1931 } else { |
| 2054 NOTREACHED() << "Unexpected preference name."; | 1932 NOTREACHED() << "Unexpected preference name."; |
| 2055 } | 1933 } |
| 2056 break; | 1934 break; |
| 2057 } | 1935 } |
| 2058 | 1936 |
| 2059 default: | 1937 default: |
| 2060 NOTREACHED() << "Unexpected notification type."; | 1938 NOTREACHED() << "Unexpected notification type."; |
| 2061 } | 1939 } |
| 2062 } | 1940 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2095 } | 1973 } |
| 2096 | 1974 |
| 2097 void ExtensionService::SetBeingUpgraded(const Extension* extension, | 1975 void ExtensionService::SetBeingUpgraded(const Extension* extension, |
| 2098 bool value) { | 1976 bool value) { |
| 2099 extension_runtime_data_[extension->id()].being_upgraded = value; | 1977 extension_runtime_data_[extension->id()].being_upgraded = value; |
| 2100 } | 1978 } |
| 2101 | 1979 |
| 2102 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { | 1980 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { |
| 2103 return &extension_runtime_data_[extension->id()].property_bag; | 1981 return &extension_runtime_data_[extension->id()].property_bag; |
| 2104 } | 1982 } |
| OLD | NEW |