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/default_apps_trial.h" | |
18 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
19 #include "chrome/browser/extensions/external_extension_provider_interface.h" | 18 #include "chrome/browser/extensions/external_extension_provider_interface.h" |
20 #include "chrome/browser/extensions/external_policy_extension_loader.h" | 19 #include "chrome/browser/extensions/external_policy_extension_loader.h" |
21 #include "chrome/browser/extensions/external_pref_extension_loader.h" | 20 #include "chrome/browser/extensions/external_pref_extension_loader.h" |
22 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/common/chrome_paths.h" | 22 #include "chrome/common/chrome_paths.h" |
24 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
26 #include "content/browser/browser_thread.h" | 25 #include "content/browser/browser_thread.h" |
27 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
28 | 27 |
| 28 #if !defined(OS_CHROMEOS) |
| 29 #include "chrome/browser/extensions/default_apps_provider.h" |
| 30 #include "chrome/browser/extensions/default_apps_trial.h" |
| 31 #endif |
| 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"; | |
35 const char ExternalExtensionProviderImpl::kState[] = "state"; | |
36 const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx"; | 38 const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx"; |
37 const char ExternalExtensionProviderImpl::kExternalVersion[] = | 39 const char ExternalExtensionProviderImpl::kExternalVersion[] = |
38 "external_version"; | 40 "external_version"; |
39 const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] = | 41 const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] = |
40 "external_update_url"; | 42 "external_update_url"; |
41 const char ExternalExtensionProviderImpl::kSupportedLocales[] = | 43 const char ExternalExtensionProviderImpl::kSupportedLocales[] = |
42 "supported_locales"; | 44 "supported_locales"; |
43 | 45 |
44 #if !defined(OS_CHROMEOS) | |
45 class DefaultAppsProvider : public ExternalExtensionProviderImpl { | |
46 public: | |
47 DefaultAppsProvider(VisitorInterface* service, Profile* profile) | |
48 : ExternalExtensionProviderImpl(service, | |
49 new ExternalPrefExtensionLoader(chrome::DIR_DEFAULT_APPS, | |
50 ExternalPrefExtensionLoader::NONE), | |
51 Extension::EXTERNAL_PREF, Extension::INVALID), | |
52 profile_(profile) { | |
53 DCHECK(profile_); | |
54 } | |
55 | |
56 // ExternalExtensionProviderImpl overrides: | |
57 virtual void ServiceShutdown() OVERRIDE; | |
58 virtual void VisitRegisteredExtension() const OVERRIDE; | |
59 | |
60 private: | |
61 Profile* profile_; | |
62 | |
63 DISALLOW_COPY_AND_ASSIGN(DefaultAppsProvider); | |
64 }; | |
65 | |
66 void DefaultAppsProvider::ServiceShutdown() { | |
67 profile_ = NULL; | |
68 ExternalExtensionProviderImpl::ServiceShutdown(); | |
69 } | |
70 | |
71 void DefaultAppsProvider::VisitRegisteredExtension() const { | |
72 // Don't install default apps if the profile already has apps installed. | |
73 if (profile_) { | |
74 ExtensionService* extension_service = profile_->GetExtensionService(); | |
75 if (extension_service && extension_service->HasApps()) { | |
76 service()->OnExternalProviderReady(); | |
77 return; | |
78 } | |
79 } | |
80 | |
81 ExternalExtensionProviderImpl::VisitRegisteredExtension(); | |
82 } | |
83 #endif | |
84 | |
85 ExternalExtensionProviderImpl::ExternalExtensionProviderImpl( | 46 ExternalExtensionProviderImpl::ExternalExtensionProviderImpl( |
86 VisitorInterface* service, | 47 VisitorInterface* service, |
87 ExternalExtensionLoader* loader, | 48 ExternalExtensionLoader* loader, |
88 Extension::Location crx_location, | 49 Extension::Location crx_location, |
89 Extension::Location download_location) | 50 Extension::Location download_location) |
90 : crx_location_(crx_location), | 51 : crx_location_(crx_location), |
91 download_location_(download_location), | 52 download_location_(download_location), |
92 service_(service), | 53 service_(service), |
93 prefs_(NULL), | 54 prefs_(NULL), |
94 ready_(false), | 55 ready_(false), |
(...skipping 11 matching lines...) Expand all Loading... |
106 loader_->StartLoading(); | 67 loader_->StartLoading(); |
107 } | 68 } |
108 | 69 |
109 void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) { | 70 void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) { |
110 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 71 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
111 | 72 |
112 // Check if the service is still alive. It is possible that it had went | 73 // Check if the service is still alive. It is possible that it had went |
113 // away while |loader_| was working on the FILE thread. | 74 // away while |loader_| was working on the FILE thread. |
114 if (!service_) return; | 75 if (!service_) return; |
115 | 76 |
| 77 invalid_extensions_.clear(); |
116 prefs_.reset(prefs); | 78 prefs_.reset(prefs); |
117 ready_ = true; // Queries for extensions are allowed from this point. | 79 ready_ = true; // Queries for extensions are allowed from this point. |
118 | 80 |
119 // Set of unsupported extensions that need to be deleted from prefs_. | 81 // Set of unsupported extensions that need to be deleted from prefs_. |
120 std::set<std::string> unsupported_extensions; | 82 std::set<std::string> unsupported_extensions; |
121 | 83 |
122 // Notify ExtensionService about all the extensions this provider has. | 84 // Notify ExtensionService about all the extensions this provider has. |
123 for (DictionaryValue::key_iterator i = prefs_->begin_keys(); | 85 for (DictionaryValue::key_iterator i = prefs_->begin_keys(); |
124 i != prefs_->end_keys(); ++i) { | 86 i != prefs_->end_keys(); ++i) { |
125 const std::string& extension_id = *i; | 87 const std::string& extension_id = *i; |
126 DictionaryValue* extension; | 88 DictionaryValue* extension; |
127 | 89 |
| 90 // Assume the extension is invalid until proven otherwise. |
| 91 invalid_extensions_.insert(extension_id); |
| 92 |
128 if (!Extension::IdIsValid(extension_id)) { | 93 if (!Extension::IdIsValid(extension_id)) { |
129 LOG(WARNING) << "Malformed extension dictionary: key " | 94 LOG(WARNING) << "Malformed extension dictionary: key " |
130 << extension_id.c_str() << " is not a valid id."; | 95 << extension_id.c_str() << " is not a valid id."; |
131 continue; | 96 continue; |
132 } | 97 } |
133 | 98 |
134 if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) { | 99 if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) { |
135 LOG(WARNING) << "Malformed extension dictionary: key " | 100 LOG(WARNING) << "Malformed extension dictionary: key " |
136 << extension_id.c_str() | 101 << extension_id.c_str() |
137 << " has a value that is not a dictionary."; | 102 << " has a value that is not a dictionary."; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 } | 189 } |
225 | 190 |
226 scoped_ptr<Version> version; | 191 scoped_ptr<Version> version; |
227 version.reset(Version::GetVersionFromString(external_version)); | 192 version.reset(Version::GetVersionFromString(external_version)); |
228 if (!version.get()) { | 193 if (!version.get()) { |
229 LOG(WARNING) << "Malformed extension dictionary for extension: " | 194 LOG(WARNING) << "Malformed extension dictionary for extension: " |
230 << extension_id.c_str() << ". Invalid version string \"" | 195 << extension_id.c_str() << ". Invalid version string \"" |
231 << external_version << "\"."; | 196 << external_version << "\"."; |
232 continue; | 197 continue; |
233 } | 198 } |
| 199 invalid_extensions_.erase(extension_id); |
234 service_->OnExternalExtensionFileFound(extension_id, version.get(), path, | 200 service_->OnExternalExtensionFileFound(extension_id, version.get(), path, |
235 crx_location_); | 201 crx_location_); |
236 } else { // if (has_external_update_url) | 202 } else { // if (has_external_update_url) |
237 CHECK(has_external_update_url); // Checking of keys above ensures this. | 203 CHECK(has_external_update_url); // Checking of keys above ensures this. |
238 if (download_location_ == Extension::INVALID) { | 204 if (download_location_ == Extension::INVALID) { |
239 LOG(WARNING) << "This provider does not support installing external " | 205 LOG(WARNING) << "This provider does not support installing external " |
240 << "extensions from update URLs."; | 206 << "extensions from update URLs."; |
241 continue; | 207 continue; |
242 } | 208 } |
243 GURL update_url(external_update_url); | 209 GURL update_url(external_update_url); |
244 if (!update_url.is_valid()) { | 210 if (!update_url.is_valid()) { |
245 LOG(WARNING) << "Malformed extension dictionary for extension: " | 211 LOG(WARNING) << "Malformed extension dictionary for extension: " |
246 << extension_id.c_str() << ". Key " << kExternalUpdateUrl | 212 << extension_id.c_str() << ". Key " << kExternalUpdateUrl |
247 << " has value \"" << external_update_url | 213 << " has value \"" << external_update_url |
248 << "\", which is not a valid URL."; | 214 << "\", which is not a valid URL."; |
249 continue; | 215 continue; |
250 } | 216 } |
| 217 invalid_extensions_.erase(extension_id); |
251 service_->OnExternalExtensionUpdateUrlFound( | 218 service_->OnExternalExtensionUpdateUrlFound( |
252 extension_id, update_url, download_location_); | 219 extension_id, update_url, download_location_); |
253 } | 220 } |
254 } | 221 } |
255 | 222 |
256 for (std::set<std::string>::iterator it = unsupported_extensions.begin(); | 223 for (std::set<std::string>::iterator it = unsupported_extensions.begin(); |
257 it != unsupported_extensions.end(); ++it) { | 224 it != unsupported_extensions.end(); ++it) { |
258 // Remove extension for the list of know external extensions. The extension | 225 // Remove extension for the list of know external extensions. The extension |
259 // will be uninstalled later because provider doesn't provide it anymore. | 226 // will be uninstalled later because provider doesn't provide it anymore. |
260 prefs_->Remove(*it, NULL); | 227 prefs_->Remove(*it, NULL); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 #endif | 342 #endif |
376 provider_list->push_back( | 343 provider_list->push_back( |
377 linked_ptr<ExternalExtensionProviderInterface>( | 344 linked_ptr<ExternalExtensionProviderInterface>( |
378 new ExternalExtensionProviderImpl( | 345 new ExternalExtensionProviderImpl( |
379 service, | 346 service, |
380 new ExternalPolicyExtensionLoader(profile), | 347 new ExternalPolicyExtensionLoader(profile), |
381 Extension::INVALID, | 348 Extension::INVALID, |
382 Extension::EXTERNAL_POLICY_DOWNLOAD))); | 349 Extension::EXTERNAL_POLICY_DOWNLOAD))); |
383 | 350 |
384 #if !defined(OS_CHROMEOS) | 351 #if !defined(OS_CHROMEOS) |
385 // We decide to install or not install default apps based on the following | 352 if (DefaultAppsProvider::ShouldRegister(profile)) { |
386 // criteria, from highest priority to lowest priority: | 353 provider_list->push_back( |
387 // | 354 linked_ptr<ExternalExtensionProviderInterface>( |
388 // - if this instance of chrome is participating in the default apps | 355 new DefaultAppsProvider( |
389 // field trial, then install apps based on the group | 356 service, |
390 // - the command line option. Tests use this option to disable installation | 357 new ExternalPrefExtensionLoader( |
391 // of default apps in some cases | 358 chrome::DIR_DEFAULT_APPS, |
392 // - the preferences value in the profile. This value is usually set in | 359 ExternalPrefExtensionLoader::NONE), |
393 // the master_preferences file | 360 profile))); |
394 bool install_apps = | |
395 profile->GetPrefs()->GetString(prefs::kDefaultApps) == "install"; | |
396 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
397 switches::kDisableDefaultApps)) { | |
398 install_apps = false; | |
399 } | |
400 if (base::FieldTrialList::TrialExists(kDefaultAppsTrial_Name)) { | |
401 install_apps = base::FieldTrialList::Find( | |
402 kDefaultAppsTrial_Name)->group_name() != kDefaultAppsTrial_NoAppsGroup; | |
403 } | |
404 | |
405 if (install_apps) { | |
406 // Don't bother installing default apps in locales where its known that | |
407 // they don't work. | |
408 // TODO(rogerta): Do this check dynamically once the webstore can expose | |
409 // an API. | |
410 const std::string& locale = g_browser_process->GetApplicationLocale(); | |
411 static const char* unsupported_locales[] = {"CN", "TR", "IR"}; | |
412 bool supported_locale = true; | |
413 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) { | |
414 if (EndsWith(locale, unsupported_locales[i], false)) { | |
415 supported_locale = false; | |
416 break; | |
417 } | |
418 } | |
419 | |
420 if (supported_locale) { | |
421 provider_list->push_back( | |
422 linked_ptr<ExternalExtensionProviderInterface>( | |
423 new DefaultAppsProvider(service, profile))); | |
424 } | |
425 } | 361 } |
426 #endif | 362 #endif |
427 } | 363 } |
OLD | NEW |