Chromium Code Reviews| 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/external_extension_provider_impl.h" | 5 #include "chrome/browser/extensions/external_extension_provider_impl.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/linked_ptr.h" | 10 #include "base/memory/linked_ptr.h" |
| 11 #include "base/metrics/field_trial.h" | 11 #include "base/metrics/field_trial.h" |
| 12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "base/version.h" | 15 #include "base/version.h" |
| 16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/extensions/crx_installer.h" | |
| 17 #include "chrome/browser/extensions/default_apps_trial.h" | 18 #include "chrome/browser/extensions/default_apps_trial.h" |
| 18 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
| 19 #include "chrome/browser/extensions/external_extension_provider_interface.h" | 20 #include "chrome/browser/extensions/external_extension_provider_interface.h" |
| 20 #include "chrome/browser/extensions/external_policy_extension_loader.h" | 21 #include "chrome/browser/extensions/external_policy_extension_loader.h" |
| 21 #include "chrome/browser/extensions/external_pref_extension_loader.h" | 22 #include "chrome/browser/extensions/external_pref_extension_loader.h" |
| 22 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
| 24 #include "chrome/common/chrome_notification_types.h" | |
| 23 #include "chrome/common/chrome_paths.h" | 25 #include "chrome/common/chrome_paths.h" |
| 24 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
| 26 #include "content/browser/browser_thread.h" | 28 #include "content/browser/browser_thread.h" |
| 29 #include "content/common/notification_details.h" | |
| 30 #include "content/common/notification_source.h" | |
| 27 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
| 28 | 32 |
| 29 #if defined(OS_WIN) | 33 #if defined(OS_WIN) |
| 30 #include "chrome/browser/extensions/external_registry_extension_loader_win.h" | 34 #include "chrome/browser/extensions/external_registry_extension_loader_win.h" |
| 31 #endif | 35 #endif |
| 32 | 36 |
| 33 // Constants for keeping track of extension preferences in a dictionary. | 37 // Constants for keeping track of extension preferences in a dictionary. |
| 34 const char ExternalExtensionProviderImpl::kLocation[] = "location"; | 38 const char ExternalExtensionProviderImpl::kLocation[] = "location"; |
| 35 const char ExternalExtensionProviderImpl::kState[] = "state"; | 39 const char ExternalExtensionProviderImpl::kState[] = "state"; |
| 36 const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx"; | 40 const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx"; |
| 37 const char ExternalExtensionProviderImpl::kExternalVersion[] = | 41 const char ExternalExtensionProviderImpl::kExternalVersion[] = |
| 38 "external_version"; | 42 "external_version"; |
| 39 const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] = | 43 const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] = |
| 40 "external_update_url"; | 44 "external_update_url"; |
| 41 const char ExternalExtensionProviderImpl::kSupportedLocales[] = | 45 const char ExternalExtensionProviderImpl::kSupportedLocales[] = |
| 42 "supported_locales"; | 46 "supported_locales"; |
| 43 | 47 |
| 44 #if !defined(OS_CHROMEOS) | 48 #if !defined(OS_CHROMEOS) |
| 45 class DefaultAppsProvider : public ExternalExtensionProviderImpl { | 49 DefaultAppsProvider::DefaultAppsProvider(VisitorInterface* service, |
| 46 public: | 50 ExternalExtensionLoader* loader, |
| 47 DefaultAppsProvider(VisitorInterface* service, Profile* profile) | 51 Profile* profile) |
| 48 : ExternalExtensionProviderImpl(service, | 52 : ExternalExtensionProviderImpl(service, loader, |
| 49 new ExternalPrefExtensionLoader(chrome::DIR_DEFAULT_APPS, | 53 Extension::EXTERNAL_PREF, Extension::INVALID), |
| 50 ExternalPrefExtensionLoader::NONE), | 54 profile_(profile) { |
| 51 Extension::EXTERNAL_PREF, Extension::INVALID), | 55 DCHECK(profile_); |
| 52 profile_(profile) { | 56 } |
| 53 DCHECK(profile_); | 57 |
| 58 DefaultAppsProvider::~DefaultAppsProvider() { | |
| 59 } | |
| 60 | |
| 61 void DefaultAppsProvider::SetPrefs(base::DictionaryValue* prefs) { | |
| 62 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 63 | |
| 64 if (prefs->size() > 0) { | |
| 65 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
| 66 Source<Profile>(profile_)); | |
| 67 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | |
| 68 NotificationService::AllSources()); | |
| 54 } | 69 } |
| 55 | 70 |
| 56 // ExternalExtensionProviderImpl overrides: | 71 ExternalExtensionProviderImpl::SetPrefs(prefs); |
| 57 virtual void ServiceShutdown() OVERRIDE; | |
| 58 virtual void VisitRegisteredExtension() const OVERRIDE; | |
| 59 | 72 |
| 60 private: | 73 // If the number of invalid extension is the same as the total, then we are |
| 61 Profile* profile_; | 74 // done. |
| 62 | 75 if (prefs->size() == invalid_extensions().size()) { |
|
Finnur
2011/10/19 10:01:29
Is it safe to rely on the count? Don't you want to
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
The invalid_extension set can only come from exten
| |
| 63 DISALLOW_COPY_AND_ASSIGN(DefaultAppsProvider); | 76 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, |
| 64 }; | 77 kInstallDone); |
| 78 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); | |
| 79 } | |
| 80 } | |
| 65 | 81 |
| 66 void DefaultAppsProvider::ServiceShutdown() { | 82 void DefaultAppsProvider::ServiceShutdown() { |
| 67 profile_ = NULL; | 83 profile_ = NULL; |
| 68 ExternalExtensionProviderImpl::ServiceShutdown(); | 84 ExternalExtensionProviderImpl::ServiceShutdown(); |
| 69 } | 85 } |
| 70 | 86 |
| 71 void DefaultAppsProvider::VisitRegisteredExtension() const { | 87 void DefaultAppsProvider::VisitRegisteredExtension() const { |
| 72 // Don't install default apps if the profile already has apps installed. | |
| 73 if (profile_) { | 88 if (profile_) { |
| 74 ExtensionService* extension_service = profile_->GetExtensionService(); | 89 int state = profile_->GetPrefs()->GetInteger( |
| 75 if (extension_service && extension_service->HasApps()) { | 90 prefs::kDefaultAppsInstallState); |
|
Finnur
2011/10/19 10:01:29
nit: Is there room in the line above or are my eye
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
yup, you need glasses :-)
Finnur
2011/10/20 10:10:43
Awww... :)
On 2011/10/19 20:48:25, Roger Tawa wro
| |
| 76 service()->OnExternalProviderReady(); | 91 switch (state) { |
| 77 return; | 92 case kInstallNotStarted: { |
| 93 // We never even tried to install the default apps, so try now. | |
| 94 // Don't install default apps if the profile already has apps installed. | |
| 95 ExtensionService* extension_service = profile_->GetExtensionService(); | |
| 96 if (extension_service && extension_service->HasApps()) { | |
| 97 service()->OnExternalProviderReady(); | |
|
Finnur
2011/10/19 10:01:29
nit: Probably doesn't matter, but shouldn't you se
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
Done.
| |
| 98 | |
| 99 // Keep track that we are done. | |
|
Finnur
2011/10/19 10:01:29
nit: Keep track of the fact that we are done.
Bet
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
Done.
| |
| 100 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, | |
| 101 kInstallDone); | |
| 102 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); | |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 // Remember that we are now installing the default apps. | |
| 107 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, | |
| 108 kInstalling); | |
| 109 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); | |
| 110 // No break. | |
|
Finnur
2011/10/19 10:01:29
This is a bit weird... skip the break to fall into
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
Done.
| |
| 111 } | |
| 112 case kInstalling: | |
| 113 // The profile was closed while the extensions were being installed. | |
| 114 // Continue the install process. | |
|
Finnur
2011/10/19 10:01:29
This comment is a bit confusing. I think you want
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
more verbose explanation.
| |
| 115 break; | |
| 116 case kInstallDone: | |
| 117 // Defaults are installed, so don't need to try again. | |
| 118 service()->OnExternalProviderReady(); | |
| 119 return; | |
| 78 } | 120 } |
| 79 } | 121 } |
| 80 | 122 |
| 81 ExternalExtensionProviderImpl::VisitRegisteredExtension(); | 123 ExternalExtensionProviderImpl::VisitRegisteredExtension(); |
| 82 } | 124 } |
| 125 | |
| 126 void DefaultAppsProvider::Observe(int type, | |
| 127 const NotificationSource& source, | |
| 128 const NotificationDetails& details) { | |
| 129 if (!profile_) | |
| 130 return; | |
| 131 | |
| 132 // If the notification is for a failed extension, remember its id so that | |
| 133 // we don't wait forever for it to get installed. | |
| 134 if (type == chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR) { | |
| 135 CrxInstaller* crx_installer = Source<CrxInstaller>(source).ptr(); | |
| 136 install_error_extensions_.insert(crx_installer->expected_id()); | |
| 137 } | |
| 138 | |
| 139 ExtensionService* extension_service = profile_->GetExtensionService(); | |
| 140 if (!extension_service) | |
| 141 return; | |
| 142 | |
| 143 for (DictionaryValue::key_iterator i = prefs()->begin_keys(); | |
| 144 i != prefs()->end_keys(); ++i) { | |
| 145 const std::string& extension_id = *i; | |
| 146 | |
| 147 // If the extension id is for one that is invalid or failed to install, | |
| 148 // then consider it "done". | |
| 149 if (invalid_extensions().count(extension_id) || | |
| 150 install_error_extensions_.count(extension_id)) { | |
| 151 continue; | |
| 152 } | |
| 153 | |
| 154 if (!extension_service->GetExtensionById(extension_id, true)) { | |
| 155 // We found an extension that is not yet known to the service. We | |
| 156 // need to keep going. | |
| 157 return; | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, | |
| 162 kInstallDone); | |
| 163 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); | |
| 164 registrar_.RemoveAll(); | |
| 165 } | |
| 83 #endif | 166 #endif |
| 84 | 167 |
| 85 ExternalExtensionProviderImpl::ExternalExtensionProviderImpl( | 168 ExternalExtensionProviderImpl::ExternalExtensionProviderImpl( |
| 86 VisitorInterface* service, | 169 VisitorInterface* service, |
| 87 ExternalExtensionLoader* loader, | 170 ExternalExtensionLoader* loader, |
| 88 Extension::Location crx_location, | 171 Extension::Location crx_location, |
| 89 Extension::Location download_location) | 172 Extension::Location download_location) |
| 90 : crx_location_(crx_location), | 173 : crx_location_(crx_location), |
| 91 download_location_(download_location), | 174 download_location_(download_location), |
| 92 service_(service), | 175 service_(service), |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 106 loader_->StartLoading(); | 189 loader_->StartLoading(); |
| 107 } | 190 } |
| 108 | 191 |
| 109 void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) { | 192 void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) { |
| 110 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 111 | 194 |
| 112 // Check if the service is still alive. It is possible that it had went | 195 // Check if the service is still alive. It is possible that it had went |
| 113 // away while |loader_| was working on the FILE thread. | 196 // away while |loader_| was working on the FILE thread. |
| 114 if (!service_) return; | 197 if (!service_) return; |
| 115 | 198 |
| 199 invalid_extensions_.clear(); | |
| 116 prefs_.reset(prefs); | 200 prefs_.reset(prefs); |
| 117 ready_ = true; // Queries for extensions are allowed from this point. | 201 ready_ = true; // Queries for extensions are allowed from this point. |
| 118 | 202 |
| 119 // Set of unsupported extensions that need to be deleted from prefs_. | 203 // Set of unsupported extensions that need to be deleted from prefs_. |
| 120 std::set<std::string> unsupported_extensions; | 204 std::set<std::string> unsupported_extensions; |
| 121 | 205 |
| 122 // Notify ExtensionService about all the extensions this provider has. | 206 // Notify ExtensionService about all the extensions this provider has. |
| 123 for (DictionaryValue::key_iterator i = prefs_->begin_keys(); | 207 for (DictionaryValue::key_iterator i = prefs_->begin_keys(); |
| 124 i != prefs_->end_keys(); ++i) { | 208 i != prefs_->end_keys(); ++i) { |
| 125 const std::string& extension_id = *i; | 209 const std::string& extension_id = *i; |
| 126 DictionaryValue* extension; | 210 DictionaryValue* extension; |
| 127 | 211 |
| 212 // Assume the extension is invalid until proven otherwise. | |
| 213 invalid_extensions_.insert(extension_id); | |
| 214 | |
| 128 if (!Extension::IdIsValid(extension_id)) { | 215 if (!Extension::IdIsValid(extension_id)) { |
| 129 LOG(WARNING) << "Malformed extension dictionary: key " | 216 LOG(WARNING) << "Malformed extension dictionary: key " |
| 130 << extension_id.c_str() << " is not a valid id."; | 217 << extension_id.c_str() << " is not a valid id."; |
| 131 continue; | 218 continue; |
| 132 } | 219 } |
| 133 | 220 |
| 134 if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) { | 221 if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) { |
| 135 LOG(WARNING) << "Malformed extension dictionary: key " | 222 LOG(WARNING) << "Malformed extension dictionary: key " |
| 136 << extension_id.c_str() | 223 << extension_id.c_str() |
| 137 << " has a value that is not a dictionary."; | 224 << " has a value that is not a dictionary."; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 } | 311 } |
| 225 | 312 |
| 226 scoped_ptr<Version> version; | 313 scoped_ptr<Version> version; |
| 227 version.reset(Version::GetVersionFromString(external_version)); | 314 version.reset(Version::GetVersionFromString(external_version)); |
| 228 if (!version.get()) { | 315 if (!version.get()) { |
| 229 LOG(WARNING) << "Malformed extension dictionary for extension: " | 316 LOG(WARNING) << "Malformed extension dictionary for extension: " |
| 230 << extension_id.c_str() << ". Invalid version string \"" | 317 << extension_id.c_str() << ". Invalid version string \"" |
| 231 << external_version << "\"."; | 318 << external_version << "\"."; |
| 232 continue; | 319 continue; |
| 233 } | 320 } |
| 321 invalid_extensions_.erase(extension_id); | |
| 234 service_->OnExternalExtensionFileFound(extension_id, version.get(), path, | 322 service_->OnExternalExtensionFileFound(extension_id, version.get(), path, |
| 235 crx_location_); | 323 crx_location_); |
| 236 } else { // if (has_external_update_url) | 324 } else { // if (has_external_update_url) |
| 237 CHECK(has_external_update_url); // Checking of keys above ensures this. | 325 CHECK(has_external_update_url); // Checking of keys above ensures this. |
| 238 if (download_location_ == Extension::INVALID) { | 326 if (download_location_ == Extension::INVALID) { |
| 239 LOG(WARNING) << "This provider does not support installing external " | 327 LOG(WARNING) << "This provider does not support installing external " |
| 240 << "extensions from update URLs."; | 328 << "extensions from update URLs."; |
| 241 continue; | 329 continue; |
| 242 } | 330 } |
| 243 GURL update_url(external_update_url); | 331 GURL update_url(external_update_url); |
| 244 if (!update_url.is_valid()) { | 332 if (!update_url.is_valid()) { |
| 245 LOG(WARNING) << "Malformed extension dictionary for extension: " | 333 LOG(WARNING) << "Malformed extension dictionary for extension: " |
| 246 << extension_id.c_str() << ". Key " << kExternalUpdateUrl | 334 << extension_id.c_str() << ". Key " << kExternalUpdateUrl |
| 247 << " has value \"" << external_update_url | 335 << " has value \"" << external_update_url |
| 248 << "\", which is not a valid URL."; | 336 << "\", which is not a valid URL."; |
| 249 continue; | 337 continue; |
| 250 } | 338 } |
| 339 invalid_extensions_.erase(extension_id); | |
| 251 service_->OnExternalExtensionUpdateUrlFound( | 340 service_->OnExternalExtensionUpdateUrlFound( |
| 252 extension_id, update_url, download_location_); | 341 extension_id, update_url, download_location_); |
| 253 } | 342 } |
| 254 } | 343 } |
| 255 | 344 |
| 256 for (std::set<std::string>::iterator it = unsupported_extensions.begin(); | 345 for (std::set<std::string>::iterator it = unsupported_extensions.begin(); |
| 257 it != unsupported_extensions.end(); ++it) { | 346 it != unsupported_extensions.end(); ++it) { |
| 258 // Remove extension for the list of know external extensions. The extension | 347 // Remove extension for the list of know external extensions. The extension |
| 259 // will be uninstalled later because provider doesn't provide it anymore. | 348 // will be uninstalled later because provider doesn't provide it anymore. |
| 260 prefs_->Remove(*it, NULL); | 349 prefs_->Remove(*it, NULL); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 #endif | 464 #endif |
| 376 provider_list->push_back( | 465 provider_list->push_back( |
| 377 linked_ptr<ExternalExtensionProviderInterface>( | 466 linked_ptr<ExternalExtensionProviderInterface>( |
| 378 new ExternalExtensionProviderImpl( | 467 new ExternalExtensionProviderImpl( |
| 379 service, | 468 service, |
| 380 new ExternalPolicyExtensionLoader(profile), | 469 new ExternalPolicyExtensionLoader(profile), |
| 381 Extension::INVALID, | 470 Extension::INVALID, |
| 382 Extension::EXTERNAL_POLICY_DOWNLOAD))); | 471 Extension::EXTERNAL_POLICY_DOWNLOAD))); |
| 383 | 472 |
| 384 #if !defined(OS_CHROMEOS) | 473 #if !defined(OS_CHROMEOS) |
| 385 // We decide to install or not install default apps based on the following | 474 // We decide to install or not install default apps based on the following |
|
Mihai Parparita -not on Chrome
2011/10/19 07:31:36
If you're going to be moving DefaultAppsProvider t
Roger Tawa OOO till Jul 10th
2011/10/19 20:48:25
Done.
| |
| 386 // criteria, from highest priority to lowest priority: | 475 // criteria, from highest priority to lowest priority: |
| 387 // | 476 // |
| 388 // - if this instance of chrome is participating in the default apps | 477 // - if this instance of chrome is participating in the default apps |
| 389 // field trial, then install apps based on the group | 478 // field trial, then install apps based on the group |
| 390 // - the command line option. Tests use this option to disable installation | 479 // - the command line option. Tests use this option to disable installation |
| 391 // of default apps in some cases | 480 // of default apps in some cases |
| 392 // - the preferences value in the profile. This value is usually set in | 481 // - the preferences value in the profile. This value is usually set in |
| 393 // the master_preferences file | 482 // the master_preferences file |
| 394 bool install_apps = | 483 bool install_apps = |
| 395 profile->GetPrefs()->GetString(prefs::kDefaultApps) == "install"; | 484 profile->GetPrefs()->GetString(prefs::kDefaultApps) == "install"; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 413 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) { | 502 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) { |
| 414 if (EndsWith(locale, unsupported_locales[i], false)) { | 503 if (EndsWith(locale, unsupported_locales[i], false)) { |
| 415 supported_locale = false; | 504 supported_locale = false; |
| 416 break; | 505 break; |
| 417 } | 506 } |
| 418 } | 507 } |
| 419 | 508 |
| 420 if (supported_locale) { | 509 if (supported_locale) { |
| 421 provider_list->push_back( | 510 provider_list->push_back( |
| 422 linked_ptr<ExternalExtensionProviderInterface>( | 511 linked_ptr<ExternalExtensionProviderInterface>( |
| 423 new DefaultAppsProvider(service, profile))); | 512 new DefaultAppsProvider( |
| 513 service, | |
| 514 new ExternalPrefExtensionLoader( | |
| 515 chrome::DIR_DEFAULT_APPS, | |
| 516 ExternalPrefExtensionLoader::NONE), | |
| 517 profile))); | |
| 424 } | 518 } |
| 425 } | 519 } |
| 426 #endif | 520 #endif |
| 427 } | 521 } |
| OLD | NEW |