OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/updater/extension_downloader.h" | 5 #include "chrome/browser/extensions/updater/extension_downloader.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 fetches_preparing_.clear(); | 180 fetches_preparing_.clear(); |
181 } | 181 } |
182 | 182 |
183 void ExtensionDownloader::StartBlacklistUpdate( | 183 void ExtensionDownloader::StartBlacklistUpdate( |
184 const std::string& version, | 184 const std::string& version, |
185 const ManifestFetchData::PingData& ping_data) { | 185 const ManifestFetchData::PingData& ping_data) { |
186 // Note: it is very important that we use the https version of the update | 186 // Note: it is very important that we use the https version of the update |
187 // url here to avoid DNS hijacking of the blacklist, which is not validated | 187 // url here to avoid DNS hijacking of the blacklist, which is not validated |
188 // by a public key signature like .crx files are. | 188 // by a public key signature like .crx files are. |
189 ManifestFetchData* blacklist_fetch = | 189 ManifestFetchData* blacklist_fetch = |
190 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl(true)); | 190 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl()); |
| 191 DCHECK(blacklist_fetch->base_url().SchemeIsSecure()); |
191 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", | 192 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", |
192 kDefaultInstallSource); | 193 kDefaultInstallSource); |
193 StartUpdateCheck(blacklist_fetch); | 194 StartUpdateCheck(blacklist_fetch); |
194 } | 195 } |
195 | 196 |
196 bool ExtensionDownloader::AddExtensionData(const std::string& id, | 197 bool ExtensionDownloader::AddExtensionData(const std::string& id, |
197 const Version& version, | 198 const Version& version, |
198 Extension::Type extension_type, | 199 Extension::Type extension_type, |
199 GURL update_url, | 200 GURL update_url, |
200 const std::string& update_url_data) { | 201 const std::string& update_url_data) { |
201 // Skip extensions with non-empty invalid update URLs. | 202 // Skip extensions with non-empty invalid update URLs. |
202 if (!update_url.is_empty() && !update_url.is_valid()) { | 203 if (!update_url.is_empty() && !update_url.is_valid()) { |
203 LOG(WARNING) << "Extension " << id << " has invalid update url " | 204 LOG(WARNING) << "Extension " << id << " has invalid update url " |
204 << update_url; | 205 << update_url; |
205 return false; | 206 return false; |
206 } | 207 } |
207 | 208 |
| 209 // Make sure we use SSL for store-hosted extensions. |
| 210 if (extension_urls::IsWebstoreUpdateUrl(update_url) && |
| 211 !update_url.SchemeIsSecure()) |
| 212 update_url = extension_urls::GetWebstoreUpdateUrl(); |
| 213 |
208 // Skip extensions with empty IDs. | 214 // Skip extensions with empty IDs. |
209 if (id.empty()) { | 215 if (id.empty()) { |
210 LOG(WARNING) << "Found extension with empty ID"; | 216 LOG(WARNING) << "Found extension with empty ID"; |
211 return false; | 217 return false; |
212 } | 218 } |
213 | 219 |
214 if (update_url.DomainIs("google.com")) { | 220 if (update_url.DomainIs("google.com")) { |
215 url_stats_.google_url_count++; | 221 url_stats_.google_url_count++; |
216 } else if (update_url.is_empty()) { | 222 } else if (update_url.is_empty()) { |
217 url_stats_.no_url_count++; | 223 url_stats_.no_url_count++; |
218 // Fill in default update URL. | 224 // Fill in default update URL. |
219 // | 225 update_url = extension_urls::GetWebstoreUpdateUrl(); |
220 // TODO(akalin): Figure out if we should use the HTTPS version. | |
221 update_url = extension_urls::GetWebstoreUpdateUrl(false); | |
222 } else { | 226 } else { |
223 url_stats_.other_url_count++; | 227 url_stats_.other_url_count++; |
224 } | 228 } |
225 | 229 |
226 switch (extension_type) { | 230 switch (extension_type) { |
227 case Extension::TYPE_THEME: | 231 case Extension::TYPE_THEME: |
228 ++url_stats_.theme_count; | 232 ++url_stats_.theme_count; |
229 break; | 233 break; |
230 case Extension::TYPE_EXTENSION: | 234 case Extension::TYPE_EXTENSION: |
231 case Extension::TYPE_USER_SCRIPT: | 235 case Extension::TYPE_USER_SCRIPT: |
232 ++url_stats_.extension_count; | 236 ++url_stats_.extension_count; |
233 break; | 237 break; |
234 case Extension::TYPE_HOSTED_APP: | 238 case Extension::TYPE_HOSTED_APP: |
235 case Extension::TYPE_PACKAGED_APP: | 239 case Extension::TYPE_PACKAGED_APP: |
236 ++url_stats_.app_count; | 240 ++url_stats_.app_count; |
237 break; | 241 break; |
238 case Extension::TYPE_UNKNOWN: | 242 case Extension::TYPE_UNKNOWN: |
239 default: | 243 default: |
240 ++url_stats_.pending_count; | 244 ++url_stats_.pending_count; |
241 break; | 245 break; |
242 } | 246 } |
243 | 247 |
244 std::vector<GURL> update_urls; | 248 std::vector<GURL> update_urls; |
245 update_urls.push_back(update_url); | 249 update_urls.push_back(update_url); |
246 // If UMA is enabled, also add to ManifestFetchData for the | 250 // If UMA is enabled, also add to ManifestFetchData for the |
247 // webstore update URL. | 251 // webstore update URL. |
248 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && | 252 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && |
249 MetricsServiceHelper::IsMetricsReportingEnabled()) { | 253 MetricsServiceHelper::IsMetricsReportingEnabled()) { |
250 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl(false)); | 254 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); |
251 } | 255 } |
252 | 256 |
253 for (size_t i = 0; i < update_urls.size(); ++i) { | 257 for (size_t i = 0; i < update_urls.size(); ++i) { |
254 DCHECK(!update_urls[i].is_empty()); | 258 DCHECK(!update_urls[i].is_empty()); |
255 DCHECK(update_urls[i].is_valid()); | 259 DCHECK(update_urls[i].is_valid()); |
256 | 260 |
257 std::string install_source = i == 0 ? | 261 std::string install_source = i == 0 ? |
258 kDefaultInstallSource : kNotFromWebstoreInstallSource; | 262 kDefaultInstallSource : kNotFromWebstoreInstallSource; |
259 | 263 |
260 ManifestFetchData::PingData ping_data; | 264 ManifestFetchData::PingData ping_data; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 return; | 429 return; |
426 } | 430 } |
427 | 431 |
428 // Examine the parsed manifest and kick off fetches of any new crx files. | 432 // Examine the parsed manifest and kick off fetches of any new crx files. |
429 std::vector<int> updates; | 433 std::vector<int> updates; |
430 DetermineUpdates(fetch_data, *results, &updates); | 434 DetermineUpdates(fetch_data, *results, &updates); |
431 for (size_t i = 0; i < updates.size(); i++) { | 435 for (size_t i = 0; i < updates.size(); i++) { |
432 const UpdateManifest::Result* update = &(results->list.at(updates[i])); | 436 const UpdateManifest::Result* update = &(results->list.at(updates[i])); |
433 const std::string& id = update->extension_id; | 437 const std::string& id = update->extension_id; |
434 not_updated.erase(id); | 438 not_updated.erase(id); |
| 439 |
| 440 GURL crx_url = update->crx_url; |
435 if (id != kBlacklistAppID) { | 441 if (id != kBlacklistAppID) { |
436 NotifyUpdateFound(update->extension_id); | 442 NotifyUpdateFound(update->extension_id); |
437 } else { | 443 } else { |
438 // The URL of the blacklist file is returned by the server and we need to | 444 // The URL of the blacklist file is returned by the server and we need to |
439 // be sure that we continue to be able to reliably detect whether a URL | 445 // be sure that we continue to be able to reliably detect whether a URL |
440 // references a blacklist file. | 446 // references a blacklist file. |
441 DCHECK(extension_urls::IsBlacklistUpdateUrl(update->crx_url)) | 447 DCHECK(extension_urls::IsBlacklistUpdateUrl(crx_url)) << crx_url; |
442 << update->crx_url; | 448 |
| 449 // Force https (crbug.com/129587). |
| 450 if (!crx_url.SchemeIsSecure()) { |
| 451 url_canon::Replacements<char> replacements; |
| 452 std::string scheme("https"); |
| 453 replacements.SetScheme(scheme.c_str(), |
| 454 url_parse::Component(0, scheme.size())); |
| 455 crx_url = crx_url.ReplaceComponents(replacements); |
| 456 } |
443 } | 457 } |
444 FetchUpdatedExtension(update->extension_id, update->crx_url, | 458 FetchUpdatedExtension(update->extension_id, crx_url, update->package_hash, |
445 update->package_hash, update->version); | 459 update->version); |
446 } | 460 } |
447 | 461 |
448 // If the manifest response included a <daystart> element, we want to save | 462 // If the manifest response included a <daystart> element, we want to save |
449 // that value for any extensions which had sent a ping in the request. | 463 // that value for any extensions which had sent a ping in the request. |
450 if (fetch_data.base_url().DomainIs("google.com") && | 464 if (fetch_data.base_url().DomainIs("google.com") && |
451 results->daystart_elapsed_seconds >= 0) { | 465 results->daystart_elapsed_seconds >= 0) { |
452 Time day_start = | 466 Time day_start = |
453 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); | 467 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); |
454 | 468 |
455 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); | 469 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 } | 663 } |
650 | 664 |
651 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { | 665 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { |
652 content::NotificationService::current()->Notify( | 666 content::NotificationService::current()->Notify( |
653 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | 667 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, |
654 content::NotificationService::AllBrowserContextsAndSources(), | 668 content::NotificationService::AllBrowserContextsAndSources(), |
655 content::Details<const std::string>(&id)); | 669 content::Details<const std::string>(&id)); |
656 } | 670 } |
657 | 671 |
658 } // namespace extensions | 672 } // namespace extensions |
OLD | NEW |