Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 #include "chrome/browser/extensions/extension_dom_ui.h" | 36 #include "chrome/browser/extensions/extension_dom_ui.h" |
| 37 #include "chrome/browser/extensions/extension_error_reporter.h" | 37 #include "chrome/browser/extensions/extension_error_reporter.h" |
| 38 #include "chrome/browser/extensions/extension_history_api.h" | 38 #include "chrome/browser/extensions/extension_history_api.h" |
| 39 #include "chrome/browser/extensions/extension_host.h" | 39 #include "chrome/browser/extensions/extension_host.h" |
| 40 #include "chrome/browser/extensions/extension_management_api.h" | 40 #include "chrome/browser/extensions/extension_management_api.h" |
| 41 #include "chrome/browser/extensions/extension_process_manager.h" | 41 #include "chrome/browser/extensions/extension_process_manager.h" |
| 42 #include "chrome/browser/extensions/extension_processes_api.h" | 42 #include "chrome/browser/extensions/extension_processes_api.h" |
| 43 #include "chrome/browser/extensions/extension_updater.h" | 43 #include "chrome/browser/extensions/extension_updater.h" |
| 44 #include "chrome/browser/extensions/extension_webnavigation_api.h" | 44 #include "chrome/browser/extensions/extension_webnavigation_api.h" |
| 45 #include "chrome/browser/extensions/external_extension_provider.h" | 45 #include "chrome/browser/extensions/external_extension_provider.h" |
| 46 #include "chrome/browser/extensions/external_policy_extension_provider.h" | 46 #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" | 47 #include "chrome/browser/net/chrome_url_request_context.h" |
| 49 #include "chrome/browser/prefs/pref_service.h" | 48 #include "chrome/browser/prefs/pref_service.h" |
| 50 #include "chrome/browser/profiles/profile.h" | 49 #include "chrome/browser/profiles/profile.h" |
| 51 #include "chrome/browser/search_engines/template_url_model.h" | 50 #include "chrome/browser/search_engines/template_url_model.h" |
| 52 #include "chrome/common/child_process_logging.h" | 51 #include "chrome/common/child_process_logging.h" |
| 53 #include "chrome/common/chrome_switches.h" | 52 #include "chrome/common/chrome_switches.h" |
| 54 #include "chrome/common/extensions/extension.h" | 53 #include "chrome/common/extensions/extension.h" |
| 55 #include "chrome/common/extensions/extension_constants.h" | 54 #include "chrome/common/extensions/extension_constants.h" |
| 56 #include "chrome/common/extensions/extension_error_utils.h" | 55 #include "chrome/common/extensions/extension_error_utils.h" |
| 57 #include "chrome/common/extensions/extension_file_util.h" | 56 #include "chrome/common/extensions/extension_file_util.h" |
| 58 #include "chrome/common/extensions/extension_l10n_util.h" | 57 #include "chrome/common/extensions/extension_l10n_util.h" |
| 59 #include "chrome/common/extensions/extension_resource.h" | 58 #include "chrome/common/extensions/extension_resource.h" |
| 60 #include "chrome/common/notification_service.h" | 59 #include "chrome/common/notification_service.h" |
| 61 #include "chrome/common/notification_type.h" | 60 #include "chrome/common/notification_type.h" |
| 62 #include "chrome/common/json_value_serializer.h" | 61 #include "chrome/common/json_value_serializer.h" |
| 63 #include "chrome/common/pref_names.h" | 62 #include "chrome/common/pref_names.h" |
| 64 #include "chrome/common/url_constants.h" | 63 #include "chrome/common/url_constants.h" |
| 65 #include "googleurl/src/gurl.h" | 64 #include "googleurl/src/gurl.h" |
| 66 #include "net/base/registry_controlled_domain.h" | 65 #include "net/base/registry_controlled_domain.h" |
| 67 #include "webkit/database/database_tracker.h" | 66 #include "webkit/database/database_tracker.h" |
| 68 #include "webkit/database/database_util.h" | 67 #include "webkit/database/database_util.h" |
| 69 | 68 |
| 70 #if defined(OS_WIN) | |
| 71 #include "chrome/browser/extensions/external_registry_extension_provider_win.h" | |
| 72 #endif | |
| 73 | |
| 74 using base::Time; | 69 using base::Time; |
| 75 | 70 |
| 76 namespace errors = extension_manifest_errors; | 71 namespace errors = extension_manifest_errors; |
| 77 | 72 |
| 78 namespace { | 73 namespace { |
| 79 | 74 |
| 80 #if defined(OS_LINUX) | 75 #if defined(OS_LINUX) |
| 81 static const int kOmniboxIconPaddingLeft = 2; | 76 static const int kOmniboxIconPaddingLeft = 2; |
| 82 static const int kOmniboxIconPaddingRight = 2; | 77 static const int kOmniboxIconPaddingRight = 2; |
| 83 #elif defined(OS_MACOSX) | 78 #elif defined(OS_MACOSX) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 } | 172 } |
| 178 | 173 |
| 179 // ExtensionService. | 174 // ExtensionService. |
| 180 | 175 |
| 181 const char* ExtensionService::kInstallDirectoryName = "Extensions"; | 176 const char* ExtensionService::kInstallDirectoryName = "Extensions"; |
| 182 const char* ExtensionService::kCurrentVersionFileName = "Current Version"; | 177 const char* ExtensionService::kCurrentVersionFileName = "Current Version"; |
| 183 | 178 |
| 184 // Implements IO for the ExtensionService. | 179 // Implements IO for the ExtensionService. |
| 185 | 180 |
| 186 class ExtensionServiceBackend | 181 class ExtensionServiceBackend |
| 187 : public base::RefCountedThreadSafe<ExtensionServiceBackend>, | 182 : public base::RefCountedThreadSafe<ExtensionServiceBackend> { |
| 188 public ExternalExtensionProvider::Visitor { | |
| 189 public: | 183 public: |
| 190 // |install_directory| is a path where to look for extensions to load. | 184 // |install_directory| is a path where to look for extensions to load. |
| 191 ExtensionServiceBackend(PrefService* prefs, | 185 explicit ExtensionServiceBackend(const FilePath& install_directory); |
| 192 const FilePath& install_directory); | |
| 193 | 186 |
| 194 // Loads a single extension from |path| where |path| is the top directory of | 187 // Loads a single extension from |path| where |path| is the top directory of |
| 195 // a specific extension where its manifest file lives. | 188 // a specific extension where its manifest file lives. |
| 196 // Errors are reported through ExtensionErrorReporter. On success, | 189 // Errors are reported through ExtensionErrorReporter. On success, |
| 197 // OnExtensionLoaded() is called. | 190 // OnExtensionLoaded() is called. |
| 198 // TODO(erikkay): It might be useful to be able to load a packed extension | 191 // TODO(erikkay): It might be useful to be able to load a packed extension |
| 199 // (presumably into memory) without installing it. | 192 // (presumably into memory) without installing it. |
| 200 void LoadSingleExtension(const FilePath &path, | 193 void LoadSingleExtension(const FilePath &path, |
| 201 scoped_refptr<ExtensionService> frontend); | 194 scoped_refptr<ExtensionService> frontend); |
| 202 | 195 |
| 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: | 196 private: |
| 234 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>; | 197 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>; |
| 235 | 198 |
| 236 virtual ~ExtensionServiceBackend(); | 199 virtual ~ExtensionServiceBackend(); |
| 237 | 200 |
| 238 // Finish installing the extension in |crx_path| after it has been unpacked to | 201 // 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 | 202 // |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 | 203 // extension's manifest before installation. If |silent| is true, there will |
| 241 // be no install confirmation dialog. |from_gallery| indicates whether the | 204 // be no install confirmation dialog. |from_gallery| indicates whether the |
| 242 // crx was installed from our gallery, which results in different UI. | 205 // 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. | 217 // This is a naked pointer which is set by each entry point. |
| 255 // The entry point is responsible for ensuring lifetime. | 218 // The entry point is responsible for ensuring lifetime. |
| 256 ExtensionService* frontend_; | 219 ExtensionService* frontend_; |
| 257 | 220 |
| 258 // The top-level extensions directory being installed to. | 221 // The top-level extensions directory being installed to. |
| 259 FilePath install_directory_; | 222 FilePath install_directory_; |
| 260 | 223 |
| 261 // Whether errors result in noisy alerts. | 224 // Whether errors result in noisy alerts. |
| 262 bool alert_on_error_; | 225 bool alert_on_error_; |
| 263 | 226 |
| 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); | 227 DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend); |
| 279 }; | 228 }; |
| 280 | 229 |
| 281 ExtensionServiceBackend::ExtensionServiceBackend( | 230 ExtensionServiceBackend::ExtensionServiceBackend( |
| 282 PrefService* prefs, | |
| 283 const FilePath& install_directory) | 231 const FilePath& install_directory) |
| 284 : frontend_(NULL), | 232 : frontend_(NULL), |
| 285 install_directory_(install_directory), | 233 install_directory_(install_directory), |
| 286 alert_on_error_(false), | 234 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 } | 235 } |
| 307 | 236 |
| 308 ExtensionServiceBackend::~ExtensionServiceBackend() { | 237 ExtensionServiceBackend::~ExtensionServiceBackend() { |
| 309 } | 238 } |
| 310 | 239 |
| 311 void ExtensionServiceBackend::LoadSingleExtension( | 240 void ExtensionServiceBackend::LoadSingleExtension( |
| 312 const FilePath& path_in, scoped_refptr<ExtensionService> frontend) { | 241 const FilePath& path_in, scoped_refptr<ExtensionService> frontend) { |
| 313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 314 | 243 |
| 315 frontend_ = frontend; | 244 frontend_ = frontend; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 345 const FilePath& extension_path, const std::string &error) { | 274 const FilePath& extension_path, const std::string &error) { |
| 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 347 BrowserThread::PostTask( | 276 BrowserThread::PostTask( |
| 348 BrowserThread::UI, FROM_HERE, | 277 BrowserThread::UI, FROM_HERE, |
| 349 NewRunnableMethod( | 278 NewRunnableMethod( |
| 350 frontend_, | 279 frontend_, |
| 351 &ExtensionService::ReportExtensionLoadError, extension_path, | 280 &ExtensionService::ReportExtensionLoadError, extension_path, |
| 352 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); | 281 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); |
| 353 } | 282 } |
| 354 | 283 |
| 355 // Some extensions will autoupdate themselves externally from Chrome. These | 284 void ExtensionService::CheckExternalUninstall(const std::string& id) { |
| 356 // are typically part of some larger client application package. To support | 285 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 | 286 |
| 395 // Check if the providers know about this extension. | 287 // Check if the providers know about this extension. |
| 396 ProviderCollection::const_iterator i; | 288 ProviderCollection::const_iterator i; |
| 397 for (i = external_extension_providers_.begin(); | 289 for (i = external_extension_providers_.begin(); |
| 398 i != external_extension_providers_.end(); ++i) { | 290 i != external_extension_providers_.end(); ++i) { |
| 291 DCHECK(i->get()->IsReady()); | |
| 399 if (i->get()->HasExtension(id)) | 292 if (i->get()->HasExtension(id)) |
| 400 return; // Yup, known extension, don't uninstall. | 293 return; // Yup, known extension, don't uninstall. |
| 401 } | 294 } |
| 402 | 295 |
| 403 // This is an external extension that we don't have registered. Uninstall. | 296 // This is an external extension that we don't have registered. Uninstall. |
| 404 BrowserThread::PostTask( | 297 UninstallExtension(id, true); |
| 405 BrowserThread::UI, FROM_HERE, | |
| 406 NewRunnableMethod( | |
| 407 frontend.get(), &ExtensionService::UninstallExtension, id, true)); | |
| 408 } | 298 } |
| 409 | 299 |
| 410 void ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider( | 300 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(); | 301 external_extension_providers_.clear(); |
| 418 } | 302 } |
| 419 | 303 |
| 420 void ExtensionServiceBackend::AddProviderForTesting( | 304 void ExtensionService::AddProviderForTesting( |
| 421 ExternalExtensionProvider* test_provider) { | 305 ExternalExtensionProvider* test_provider) { |
| 422 DCHECK(test_provider); | 306 DCHECK(test_provider); |
| 423 external_extension_providers_.push_back( | 307 external_extension_providers_.push_back( |
| 424 linked_ptr<ExternalExtensionProvider>(test_provider)); | 308 linked_ptr<ExternalExtensionProvider>(test_provider)); |
| 425 } | 309 } |
| 426 | 310 |
| 427 void ExtensionServiceBackend::OnExternalExtensionFileFound( | 311 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, | 312 const std::string& id, |
| 442 const GURL& update_url, | 313 const GURL& update_url, |
| 443 Extension::Location location) { | 314 Extension::Location location) { |
| 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 445 | 316 |
| 446 if (frontend_->GetExtensionById(id, true)) { | 317 if (GetExtensionById(id, true)) { |
| 447 // Already installed. Do not change the update URL that the extension set. | 318 // Already installed. Do not change the update URL that the extension set. |
| 448 return; | 319 return; |
| 449 } | 320 } |
| 450 | 321 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; | 322 external_extension_added_ |= true; |
| 458 } | 323 } |
| 459 | 324 |
| 460 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url, | 325 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url, |
| 461 const GURL& referrer_url) { | 326 const GURL& referrer_url) { |
| 462 // Special-case the themes mini-gallery. | 327 // Special-case the themes mini-gallery. |
| 463 // TODO(erikkay) When that gallery goes away, remove this code. | 328 // TODO(erikkay) When that gallery goes away, remove this code. |
| 464 if (IsDownloadFromMiniGallery(download_url) && | 329 if (IsDownloadFromMiniGallery(download_url) && |
| 465 StartsWithASCII(referrer_url.spec(), | 330 StartsWithASCII(referrer_url.spec(), |
| 466 extension_urls::kMiniGalleryBrowsePrefix, false)) { | 331 extension_urls::kMiniGalleryBrowsePrefix, false)) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 extensions_enabled_ = false; | 427 extensions_enabled_ = false; |
| 563 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { | 428 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { |
| 564 extensions_enabled_ = false; | 429 extensions_enabled_ = false; |
| 565 } | 430 } |
| 566 | 431 |
| 567 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, | 432 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, |
| 568 NotificationService::AllSources()); | 433 NotificationService::AllSources()); |
| 569 pref_change_registrar_.Init(profile->GetPrefs()); | 434 pref_change_registrar_.Init(profile->GetPrefs()); |
| 570 pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this); | 435 pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this); |
| 571 pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this); | 436 pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this); |
| 572 pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this); | |
| 573 | 437 |
| 574 // Set up the ExtensionUpdater | 438 // Set up the ExtensionUpdater |
| 575 if (autoupdate_enabled) { | 439 if (autoupdate_enabled) { |
| 576 int update_frequency = kDefaultUpdateFrequencySeconds; | 440 int update_frequency = kDefaultUpdateFrequencySeconds; |
| 577 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { | 441 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { |
| 578 base::StringToInt(command_line->GetSwitchValueASCII( | 442 base::StringToInt(command_line->GetSwitchValueASCII( |
| 579 switches::kExtensionsUpdateFrequency), | 443 switches::kExtensionsUpdateFrequency), |
| 580 &update_frequency); | 444 &update_frequency); |
| 581 } | 445 } |
| 582 updater_ = new ExtensionUpdater(this, | 446 updater_ = new ExtensionUpdater(this, |
| 583 profile->GetPrefs(), | 447 profile->GetPrefs(), |
| 584 update_frequency); | 448 update_frequency); |
| 585 } | 449 } |
| 586 | 450 |
| 587 backend_ = new ExtensionServiceBackend(profile->GetPrefs(), | 451 backend_ = new ExtensionServiceBackend(install_directory_); |
| 588 install_directory_); | 452 |
| 453 ExternalExtensionProviderImpl::CreateExternalProviders( | |
| 454 this, profile_, &external_extension_providers_); | |
| 589 | 455 |
| 590 // Use monochrome icons for Omnibox icons. | 456 // Use monochrome icons for Omnibox icons. |
| 591 omnibox_popup_icon_manager_.set_monochrome(true); | 457 omnibox_popup_icon_manager_.set_monochrome(true); |
| 592 omnibox_icon_manager_.set_monochrome(true); | 458 omnibox_icon_manager_.set_monochrome(true); |
| 593 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, | 459 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, |
| 594 0, kOmniboxIconPaddingRight)); | 460 0, kOmniboxIconPaddingRight)); |
| 595 } | 461 } |
| 596 | 462 |
| 597 const ExtensionList* ExtensionService::extensions() const { | 463 const ExtensionList* ExtensionService::extensions() const { |
| 598 return &extensions_; | 464 return &extensions_; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 609 bool ExtensionService::HasInstalledExtensions() { | 475 bool ExtensionService::HasInstalledExtensions() { |
| 610 return !(extensions_.empty() && disabled_extensions_.empty()); | 476 return !(extensions_.empty() && disabled_extensions_.empty()); |
| 611 } | 477 } |
| 612 | 478 |
| 613 ExtensionService::~ExtensionService() { | 479 ExtensionService::~ExtensionService() { |
| 614 DCHECK(!profile_); // Profile should have told us it's going away. | 480 DCHECK(!profile_); // Profile should have told us it's going away. |
| 615 UnloadAllExtensions(); | 481 UnloadAllExtensions(); |
| 616 if (updater_.get()) { | 482 if (updater_.get()) { |
| 617 updater_->Stop(); | 483 updater_->Stop(); |
| 618 } | 484 } |
| 485 ProviderCollection::const_iterator i; | |
| 486 for (i = external_extension_providers_.begin(); | |
| 487 i != external_extension_providers_.end(); ++i) { | |
| 488 ExternalExtensionProvider* provider = i->get(); | |
| 489 provider->ServiceShutdown(); | |
| 490 } | |
| 619 } | 491 } |
| 620 | 492 |
| 621 void ExtensionService::InitEventRouters() { | 493 void ExtensionService::InitEventRouters() { |
| 622 if (event_routers_initialized_) | 494 if (event_routers_initialized_) |
| 623 return; | 495 return; |
| 624 | 496 |
| 625 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); | 497 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); |
| 626 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); | 498 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); |
| 627 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); | 499 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); |
| 628 ExtensionBookmarkEventRouter::GetInstance()->Observe( | 500 ExtensionBookmarkEventRouter::GetInstance()->Observe( |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1193 error, | 1065 error, |
| 1194 NotificationType::EXTENSION_INSTALL_ERROR, | 1066 NotificationType::EXTENSION_INSTALL_ERROR, |
| 1195 false); | 1067 false); |
| 1196 return; | 1068 return; |
| 1197 } | 1069 } |
| 1198 | 1070 |
| 1199 if (write_to_prefs) | 1071 if (write_to_prefs) |
| 1200 extension_prefs_->UpdateManifest(extension); | 1072 extension_prefs_->UpdateManifest(extension); |
| 1201 | 1073 |
| 1202 OnExtensionLoaded(extension); | 1074 OnExtensionLoaded(extension); |
| 1203 | |
| 1204 if (Extension::IsExternalLocation(info.extension_location)) { | |
| 1205 BrowserThread::PostTask( | |
| 1206 BrowserThread::FILE, FROM_HERE, | |
| 1207 NewRunnableMethod( | |
| 1208 backend_.get(), | |
| 1209 &ExtensionServiceBackend::CheckExternalUninstall, | |
| 1210 scoped_refptr<ExtensionService>(this), | |
| 1211 info.extension_id)); | |
| 1212 } | |
| 1213 } | 1075 } |
| 1214 | 1076 |
| 1215 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { | 1077 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { |
| 1216 // The ChromeURLRequestContexts need to be first to know that the extension | 1078 // The ChromeURLRequestContexts need to be first to know that the extension |
| 1217 // was loaded, otherwise a race can arise where a renderer that is created | 1079 // was loaded, otherwise a race can arise where a renderer that is created |
| 1218 // for the extension may try to load an extension URL with an extension id | 1080 // for the extension may try to load an extension URL with an extension id |
| 1219 // that the request context doesn't yet know about. The profile is responsible | 1081 // that the request context doesn't yet know about. The profile is responsible |
| 1220 // for ensuring its URLRequestContexts appropriately discover the loaded | 1082 // for ensuring its URLRequestContexts appropriately discover the loaded |
| 1221 // extension. | 1083 // extension. |
| 1222 if (profile_) { | 1084 if (profile_) { |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1452 | 1314 |
| 1453 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { | 1315 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { |
| 1454 return extension_prefs_->GetBrowserActionVisibility(extension); | 1316 return extension_prefs_->GetBrowserActionVisibility(extension); |
| 1455 } | 1317 } |
| 1456 | 1318 |
| 1457 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, | 1319 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, |
| 1458 bool visible) { | 1320 bool visible) { |
| 1459 extension_prefs_->SetBrowserActionVisibility(extension, visible); | 1321 extension_prefs_->SetBrowserActionVisibility(extension, visible); |
| 1460 } | 1322 } |
| 1461 | 1323 |
| 1324 // Some extensions will autoupdate themselves externally from Chrome. These | |
| 1325 // are typically part of some larger client application package. To support | |
| 1326 // these, the extension will register its location in the the preferences file | |
| 1327 // (and also, on Windows, in the registry) and this code will periodically | |
| 1328 // check that location for a .crx file, which it will then install locally if | |
| 1329 // a new version is available. | |
| 1330 // Errors are reported through ExtensionErrorReporter. Succcess is not | |
| 1331 // reported. | |
| 1462 void ExtensionService::CheckForExternalUpdates() { | 1332 void ExtensionService::CheckForExternalUpdates() { |
| 1463 BrowserThread::PostTask( | 1333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1464 BrowserThread::FILE, FROM_HERE, | 1334 |
| 1465 NewRunnableMethod( | 1335 // Note that this installation is intentionally silent (since it didn't |
| 1466 backend_.get(), &ExtensionServiceBackend::CheckForExternalUpdates, | 1336 // go through the front-end). Extensions that are registered in this |
| 1467 scoped_refptr<ExtensionService>(this))); | 1337 // way are effectively considered 'pre-bundled', and so implicitly |
| 1338 // trusted. In general, if something has HKLM or filesystem access, | |
| 1339 // they could install an extension manually themselves anyway. | |
| 1340 external_extension_added_ = false; | |
| 1341 | |
| 1342 // Ask each external extension provider to give us a call back for each | |
| 1343 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. | |
| 1344 ProviderCollection::const_iterator i; | |
| 1345 for (i = external_extension_providers_.begin(); | |
| 1346 i != external_extension_providers_.end(); ++i) { | |
| 1347 ExternalExtensionProvider* provider = i->get(); | |
| 1348 provider->VisitRegisteredExtension(); | |
| 1349 } | |
| 1350 | |
| 1351 // Uninstall of unclaimed extensions will happen after all the providers | |
| 1352 // had reported ready. Trigger uninstall even if there are no providers | |
| 1353 // installed: | |
| 1354 OnExternalProviderReady(); | |
| 1468 } | 1355 } |
| 1469 | 1356 |
| 1470 void ExtensionService::UpdateExternalPolicyExtensionProvider() { | 1357 void ExtensionService::OnExternalProviderReady() { |
| 1471 const ListValue* list_pref = | 1358 // An external provider has finished loading. We only take action |
| 1472 profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList); | 1359 // if all of them are finished. So first, we all of them. |
|
Sam Kerner (Chrome)
2011/01/04 14:06:00
Comment missing a word?
gfeher
2011/01/04 23:37:09
Sorry. Done.
| |
| 1473 ListValue* list_copy = NULL; | 1360 ProviderCollection::const_iterator i; |
| 1474 if (list_pref) | 1361 for (i = external_extension_providers_.begin(); |
| 1475 list_copy = static_cast<ListValue*>(list_pref->DeepCopy()); | 1362 i != external_extension_providers_.end(); ++i) { |
| 1476 BrowserThread::PostTask( | 1363 ExternalExtensionProvider* provider = i->get(); |
| 1477 BrowserThread::FILE, FROM_HERE, | 1364 if (!provider->IsReady()) { |
| 1478 NewRunnableMethod( | 1365 return; |
| 1479 backend_.get(), | 1366 } |
| 1480 &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider, | 1367 } |
| 1481 scoped_refptr<RefCountedList>( | 1368 |
| 1482 new RefCountedList(list_copy)))); | 1369 // All the providers are ready. Install any pending extensions. |
| 1370 if (external_extension_added_ && updater()) { | |
| 1371 external_extension_added_ = false; | |
| 1372 updater()->CheckNow(); | |
| 1373 } | |
| 1374 | |
| 1375 // Uninstall all the unclaimed extensions. | |
| 1376 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | |
| 1377 extension_prefs_->GetInstalledExtensionsInfo()); | |
| 1378 for (size_t i = 0; i < extensions_info->size(); ++i) { | |
| 1379 ExtensionInfo* info = extensions_info->at(i).get(); | |
| 1380 if (Extension::IsExternalLocation(info->extension_location)) | |
| 1381 CheckExternalUninstall(info->extension_id); | |
| 1382 } | |
| 1483 } | 1383 } |
| 1484 | 1384 |
| 1485 void ExtensionService::UnloadExtension( | 1385 void ExtensionService::UnloadExtension( |
| 1486 const std::string& extension_id, | 1386 const std::string& extension_id, |
| 1487 UnloadedExtensionInfo::Reason reason) { | 1387 UnloadedExtensionInfo::Reason reason) { |
| 1488 // Make sure the extension gets deleted after we return from this function. | 1388 // Make sure the extension gets deleted after we return from this function. |
| 1489 scoped_refptr<const Extension> extension( | 1389 scoped_refptr<const Extension> extension( |
| 1490 GetExtensionByIdInternal(extension_id, true, true)); | 1390 GetExtensionByIdInternal(extension_id, true, true)); |
| 1491 | 1391 |
| 1492 // This method can be called via PostTask, so the extension may have been | 1392 // This method can be called via PostTask, so the extension may have been |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1883 const SkBitmap& ExtensionService::GetOmniboxIcon( | 1783 const SkBitmap& ExtensionService::GetOmniboxIcon( |
| 1884 const std::string& extension_id) { | 1784 const std::string& extension_id) { |
| 1885 return omnibox_icon_manager_.GetIcon(extension_id); | 1785 return omnibox_icon_manager_.GetIcon(extension_id); |
| 1886 } | 1786 } |
| 1887 | 1787 |
| 1888 const SkBitmap& ExtensionService::GetOmniboxPopupIcon( | 1788 const SkBitmap& ExtensionService::GetOmniboxPopupIcon( |
| 1889 const std::string& extension_id) { | 1789 const std::string& extension_id) { |
| 1890 return omnibox_popup_icon_manager_.GetIcon(extension_id); | 1790 return omnibox_popup_icon_manager_.GetIcon(extension_id); |
| 1891 } | 1791 } |
| 1892 | 1792 |
| 1893 void ExtensionService::ClearProvidersForTesting() { | |
| 1894 BrowserThread::PostTask( | |
| 1895 BrowserThread::FILE, FROM_HERE, | |
| 1896 NewRunnableMethod( | |
| 1897 backend_.get(), &ExtensionServiceBackend::ClearProvidersForTesting)); | |
| 1898 } | |
| 1899 | |
| 1900 void ExtensionService::AddProviderForTesting( | |
| 1901 ExternalExtensionProvider* test_provider) { | |
| 1902 BrowserThread::PostTask( | |
| 1903 BrowserThread::FILE, FROM_HERE, | |
| 1904 NewRunnableMethod( | |
| 1905 backend_.get(), &ExtensionServiceBackend::AddProviderForTesting, | |
| 1906 test_provider)); | |
| 1907 } | |
| 1908 | |
| 1909 void ExtensionService::OnExternalExtensionFileFound( | 1793 void ExtensionService::OnExternalExtensionFileFound( |
| 1910 const std::string& id, | 1794 const std::string& id, |
| 1911 const std::string& version, | 1795 const Version* version, |
| 1912 const FilePath& path, | 1796 const FilePath& path, |
| 1913 Extension::Location location) { | 1797 Extension::Location location) { |
| 1914 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1798 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1915 if (extension_prefs_->IsExtensionKilled(id)) | 1799 if (extension_prefs_->IsExtensionKilled(id)) |
| 1916 return; | 1800 return; |
| 1917 | 1801 |
| 1802 DCHECK(version); | |
| 1803 | |
| 1918 // Before even bothering to unpack, check and see if we already have this | 1804 // Before even bothering to unpack, check and see if we already have this |
| 1919 // version. This is important because these extensions are going to get | 1805 // version. This is important because these extensions are going to get |
| 1920 // installed on every startup. | 1806 // installed on every startup. |
| 1921 const Extension* existing = GetExtensionById(id, true); | 1807 const Extension* existing = GetExtensionById(id, true); |
| 1922 scoped_ptr<Version> other(Version::GetVersionFromString(version)); | |
| 1923 if (existing) { | 1808 if (existing) { |
| 1924 switch (existing->version()->CompareTo(*other)) { | 1809 switch (existing->version()->CompareTo(*version)) { |
| 1925 case -1: // existing version is older, we should upgrade | 1810 case -1: // existing version is older, we should upgrade |
| 1926 break; | 1811 break; |
| 1927 case 0: // existing version is same, do nothing | 1812 case 0: // existing version is same, do nothing |
| 1928 return; | 1813 return; |
| 1929 case 1: // existing version is newer, uh-oh | 1814 case 1: // existing version is newer, uh-oh |
| 1930 LOG(WARNING) << "Found external version of extension " << id | 1815 LOG(WARNING) << "Found external version of extension " << id |
| 1931 << "that is older than current version. Current version " | 1816 << "that is older than current version. Current version " |
| 1932 << "is: " << existing->VersionString() << ". New version " | 1817 << "is: " << existing->VersionString() << ". New version " |
| 1933 << "is: " << version << ". Keeping current version."; | 1818 << "is: " << version << ". Keeping current version."; |
| 1934 return; | 1819 return; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2007 host->extension()->id(), | 1892 host->extension()->id(), |
| 2008 UnloadedExtensionInfo::DISABLE)); | 1893 UnloadedExtensionInfo::DISABLE)); |
| 2009 break; | 1894 break; |
| 2010 } | 1895 } |
| 2011 | 1896 |
| 2012 case NotificationType::PREF_CHANGED: { | 1897 case NotificationType::PREF_CHANGED: { |
| 2013 std::string* pref_name = Details<std::string>(details).ptr(); | 1898 std::string* pref_name = Details<std::string>(details).ptr(); |
| 2014 if (*pref_name == prefs::kExtensionInstallAllowList || | 1899 if (*pref_name == prefs::kExtensionInstallAllowList || |
| 2015 *pref_name == prefs::kExtensionInstallDenyList) { | 1900 *pref_name == prefs::kExtensionInstallDenyList) { |
| 2016 CheckAdminBlacklist(); | 1901 CheckAdminBlacklist(); |
| 2017 } else if (*pref_name == prefs::kExtensionInstallForceList) { | |
| 2018 UpdateExternalPolicyExtensionProvider(); | |
| 2019 CheckForExternalUpdates(); | |
| 2020 // TODO(gfeher): Also check for external extensions that can be | |
| 2021 // uninstalled because they were removed from the pref. | |
| 2022 // (crbug.com/63667) | |
| 2023 } else { | 1902 } else { |
| 2024 NOTREACHED() << "Unexpected preference name."; | 1903 NOTREACHED() << "Unexpected preference name."; |
| 2025 } | 1904 } |
| 2026 break; | 1905 break; |
| 2027 } | 1906 } |
| 2028 | 1907 |
| 2029 default: | 1908 default: |
| 2030 NOTREACHED() << "Unexpected notification type."; | 1909 NOTREACHED() << "Unexpected notification type."; |
| 2031 } | 1910 } |
| 2032 } | 1911 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2065 } | 1944 } |
| 2066 | 1945 |
| 2067 void ExtensionService::SetBeingUpgraded(const Extension* extension, | 1946 void ExtensionService::SetBeingUpgraded(const Extension* extension, |
| 2068 bool value) { | 1947 bool value) { |
| 2069 extension_runtime_data_[extension->id()].being_upgraded = value; | 1948 extension_runtime_data_[extension->id()].being_upgraded = value; |
| 2070 } | 1949 } |
| 2071 | 1950 |
| 2072 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { | 1951 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { |
| 2073 return &extension_runtime_data_[extension->id()].property_bag; | 1952 return &extension_runtime_data_[extension->id()].property_bag; |
| 2074 } | 1953 } |
| OLD | NEW |