| 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()); | 190 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl(true)); |
| 191 DCHECK(blacklist_fetch->base_url().SchemeIsSecure()); | |
| 192 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", | 191 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", |
| 193 kDefaultInstallSource); | 192 kDefaultInstallSource); |
| 194 StartUpdateCheck(blacklist_fetch); | 193 StartUpdateCheck(blacklist_fetch); |
| 195 } | 194 } |
| 196 | 195 |
| 197 bool ExtensionDownloader::AddExtensionData(const std::string& id, | 196 bool ExtensionDownloader::AddExtensionData(const std::string& id, |
| 198 const Version& version, | 197 const Version& version, |
| 199 Extension::Type extension_type, | 198 Extension::Type extension_type, |
| 200 GURL update_url, | 199 GURL update_url, |
| 201 const std::string& update_url_data) { | 200 const std::string& update_url_data) { |
| 202 // Skip extensions with non-empty invalid update URLs. | 201 // Skip extensions with non-empty invalid update URLs. |
| 203 if (!update_url.is_empty() && !update_url.is_valid()) { | 202 if (!update_url.is_empty() && !update_url.is_valid()) { |
| 204 LOG(WARNING) << "Extension " << id << " has invalid update url " | 203 LOG(WARNING) << "Extension " << id << " has invalid update url " |
| 205 << update_url; | 204 << update_url; |
| 206 return false; | 205 return false; |
| 207 } | 206 } |
| 208 | 207 |
| 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 | |
| 214 // Skip extensions with empty IDs. | 208 // Skip extensions with empty IDs. |
| 215 if (id.empty()) { | 209 if (id.empty()) { |
| 216 LOG(WARNING) << "Found extension with empty ID"; | 210 LOG(WARNING) << "Found extension with empty ID"; |
| 217 return false; | 211 return false; |
| 218 } | 212 } |
| 219 | 213 |
| 220 if (update_url.DomainIs("google.com")) { | 214 if (update_url.DomainIs("google.com")) { |
| 221 url_stats_.google_url_count++; | 215 url_stats_.google_url_count++; |
| 222 } else if (update_url.is_empty()) { | 216 } else if (update_url.is_empty()) { |
| 223 url_stats_.no_url_count++; | 217 url_stats_.no_url_count++; |
| 224 // Fill in default update URL. | 218 // Fill in default update URL. |
| 225 update_url = extension_urls::GetWebstoreUpdateUrl(); | 219 // |
| 220 // TODO(akalin): Figure out if we should use the HTTPS version. |
| 221 update_url = extension_urls::GetWebstoreUpdateUrl(false); |
| 226 } else { | 222 } else { |
| 227 url_stats_.other_url_count++; | 223 url_stats_.other_url_count++; |
| 228 } | 224 } |
| 229 | 225 |
| 230 switch (extension_type) { | 226 switch (extension_type) { |
| 231 case Extension::TYPE_THEME: | 227 case Extension::TYPE_THEME: |
| 232 ++url_stats_.theme_count; | 228 ++url_stats_.theme_count; |
| 233 break; | 229 break; |
| 234 case Extension::TYPE_EXTENSION: | 230 case Extension::TYPE_EXTENSION: |
| 235 case Extension::TYPE_USER_SCRIPT: | 231 case Extension::TYPE_USER_SCRIPT: |
| 236 ++url_stats_.extension_count; | 232 ++url_stats_.extension_count; |
| 237 break; | 233 break; |
| 238 case Extension::TYPE_HOSTED_APP: | 234 case Extension::TYPE_HOSTED_APP: |
| 239 case Extension::TYPE_PACKAGED_APP: | 235 case Extension::TYPE_PACKAGED_APP: |
| 240 ++url_stats_.app_count; | 236 ++url_stats_.app_count; |
| 241 break; | 237 break; |
| 242 case Extension::TYPE_UNKNOWN: | 238 case Extension::TYPE_UNKNOWN: |
| 243 default: | 239 default: |
| 244 ++url_stats_.pending_count; | 240 ++url_stats_.pending_count; |
| 245 break; | 241 break; |
| 246 } | 242 } |
| 247 | 243 |
| 248 std::vector<GURL> update_urls; | 244 std::vector<GURL> update_urls; |
| 249 update_urls.push_back(update_url); | 245 update_urls.push_back(update_url); |
| 250 // If UMA is enabled, also add to ManifestFetchData for the | 246 // If UMA is enabled, also add to ManifestFetchData for the |
| 251 // webstore update URL. | 247 // webstore update URL. |
| 252 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && | 248 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && |
| 253 MetricsServiceHelper::IsMetricsReportingEnabled()) { | 249 MetricsServiceHelper::IsMetricsReportingEnabled()) { |
| 254 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); | 250 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl(false)); |
| 255 } | 251 } |
| 256 | 252 |
| 257 for (size_t i = 0; i < update_urls.size(); ++i) { | 253 for (size_t i = 0; i < update_urls.size(); ++i) { |
| 258 DCHECK(!update_urls[i].is_empty()); | 254 DCHECK(!update_urls[i].is_empty()); |
| 259 DCHECK(update_urls[i].is_valid()); | 255 DCHECK(update_urls[i].is_valid()); |
| 260 | 256 |
| 261 std::string install_source = i == 0 ? | 257 std::string install_source = i == 0 ? |
| 262 kDefaultInstallSource : kNotFromWebstoreInstallSource; | 258 kDefaultInstallSource : kNotFromWebstoreInstallSource; |
| 263 | 259 |
| 264 ManifestFetchData::PingData ping_data; | 260 ManifestFetchData::PingData ping_data; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 return; | 425 return; |
| 430 } | 426 } |
| 431 | 427 |
| 432 // Examine the parsed manifest and kick off fetches of any new crx files. | 428 // Examine the parsed manifest and kick off fetches of any new crx files. |
| 433 std::vector<int> updates; | 429 std::vector<int> updates; |
| 434 DetermineUpdates(fetch_data, *results, &updates); | 430 DetermineUpdates(fetch_data, *results, &updates); |
| 435 for (size_t i = 0; i < updates.size(); i++) { | 431 for (size_t i = 0; i < updates.size(); i++) { |
| 436 const UpdateManifest::Result* update = &(results->list.at(updates[i])); | 432 const UpdateManifest::Result* update = &(results->list.at(updates[i])); |
| 437 const std::string& id = update->extension_id; | 433 const std::string& id = update->extension_id; |
| 438 not_updated.erase(id); | 434 not_updated.erase(id); |
| 439 | |
| 440 GURL crx_url = update->crx_url; | |
| 441 if (id != kBlacklistAppID) { | 435 if (id != kBlacklistAppID) { |
| 442 NotifyUpdateFound(update->extension_id); | 436 NotifyUpdateFound(update->extension_id); |
| 443 } else { | 437 } else { |
| 444 // The URL of the blacklist file is returned by the server and we need to | 438 // The URL of the blacklist file is returned by the server and we need to |
| 445 // be sure that we continue to be able to reliably detect whether a URL | 439 // be sure that we continue to be able to reliably detect whether a URL |
| 446 // references a blacklist file. | 440 // references a blacklist file. |
| 447 DCHECK(extension_urls::IsBlacklistUpdateUrl(crx_url)) << crx_url; | 441 DCHECK(extension_urls::IsBlacklistUpdateUrl(update->crx_url)) |
| 448 | 442 << update->crx_url; |
| 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 } | |
| 457 } | 443 } |
| 458 FetchUpdatedExtension(update->extension_id, crx_url, update->package_hash, | 444 FetchUpdatedExtension(update->extension_id, update->crx_url, |
| 459 update->version); | 445 update->package_hash, update->version); |
| 460 } | 446 } |
| 461 | 447 |
| 462 // If the manifest response included a <daystart> element, we want to save | 448 // If the manifest response included a <daystart> element, we want to save |
| 463 // that value for any extensions which had sent a ping in the request. | 449 // that value for any extensions which had sent a ping in the request. |
| 464 if (fetch_data.base_url().DomainIs("google.com") && | 450 if (fetch_data.base_url().DomainIs("google.com") && |
| 465 results->daystart_elapsed_seconds >= 0) { | 451 results->daystart_elapsed_seconds >= 0) { |
| 466 Time day_start = | 452 Time day_start = |
| 467 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); | 453 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); |
| 468 | 454 |
| 469 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); | 455 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 } | 642 } |
| 657 | 643 |
| 658 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { | 644 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { |
| 659 content::NotificationService::current()->Notify( | 645 content::NotificationService::current()->Notify( |
| 660 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | 646 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, |
| 661 content::NotificationService::AllBrowserContextsAndSources(), | 647 content::NotificationService::AllBrowserContextsAndSources(), |
| 662 content::Details<const std::string>(&id)); | 648 content::Details<const std::string>(&id)); |
| 663 } | 649 } |
| 664 | 650 |
| 665 } // namespace extensions | 651 } // namespace extensions |
| OLD | NEW |