| 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/safe_browsing/download_protection_service.h" | 5 #include "chrome/browser/safe_browsing/download_protection_service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 static const int64_t kDownloadRequestTimeoutMs = 7000; | 75 static const int64_t kDownloadRequestTimeoutMs = 7000; |
| 76 // We sample 1% of whitelisted downloads to still send out download pings. | 76 // We sample 1% of whitelisted downloads to still send out download pings. |
| 77 static const double kWhitelistDownloadSampleRate = 0.01; | 77 static const double kWhitelistDownloadSampleRate = 0.01; |
| 78 } // namespace | 78 } // namespace |
| 79 | 79 |
| 80 namespace safe_browsing { | 80 namespace safe_browsing { |
| 81 | 81 |
| 82 const char DownloadProtectionService::kDownloadRequestUrl[] = | 82 const char DownloadProtectionService::kDownloadRequestUrl[] = |
| 83 "https://sb-ssl.google.com/safebrowsing/clientreport/download"; | 83 "https://sb-ssl.google.com/safebrowsing/clientreport/download"; |
| 84 | 84 |
| 85 const void* const DownloadProtectionService::kDownloadPingTokenKey |
| 86 = &kDownloadPingTokenKey; |
| 87 |
| 85 namespace { | 88 namespace { |
| 86 void RecordFileExtensionType(const base::FilePath& file) { | 89 void RecordFileExtensionType(const base::FilePath& file) { |
| 87 UMA_HISTOGRAM_SPARSE_SLOWLY( | 90 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 88 "SBClientDownload.DownloadExtensions", | 91 "SBClientDownload.DownloadExtensions", |
| 89 FileTypePolicies::GetInstance()->UmaValueForFile(file)); | 92 FileTypePolicies::GetInstance()->UmaValueForFile(file)); |
| 90 } | 93 } |
| 91 | 94 |
| 92 void RecordArchivedArchiveFileExtensionType(const base::FilePath& file) { | 95 void RecordArchivedArchiveFileExtensionType(const base::FilePath& file) { |
| 93 UMA_HISTOGRAM_SPARSE_SLOWLY( | 96 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 94 "SBClientDownload.ArchivedArchiveExtensions", | 97 "SBClientDownload.ArchivedArchiveExtensions", |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 if (source->GetStatus().is_success()) { | 447 if (source->GetStatus().is_success()) { |
| 445 UMA_HISTOGRAM_SPARSE_SLOWLY( | 448 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 446 "SBClientDownload.DownloadRequestResponseCode", | 449 "SBClientDownload.DownloadRequestResponseCode", |
| 447 source->GetResponseCode()); | 450 source->GetResponseCode()); |
| 448 } | 451 } |
| 449 UMA_HISTOGRAM_SPARSE_SLOWLY( | 452 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 450 "SBClientDownload.DownloadRequestNetError", | 453 "SBClientDownload.DownloadRequestNetError", |
| 451 -source->GetStatus().error()); | 454 -source->GetStatus().error()); |
| 452 DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED; | 455 DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED; |
| 453 DownloadCheckResult result = UNKNOWN; | 456 DownloadCheckResult result = UNKNOWN; |
| 457 std::string token; |
| 454 if (source->GetStatus().is_success() && | 458 if (source->GetStatus().is_success() && |
| 455 net::HTTP_OK == source->GetResponseCode()) { | 459 net::HTTP_OK == source->GetResponseCode()) { |
| 456 ClientDownloadResponse response; | 460 ClientDownloadResponse response; |
| 457 std::string data; | 461 std::string data; |
| 458 bool got_data = source->GetResponseAsString(&data); | 462 bool got_data = source->GetResponseAsString(&data); |
| 459 DCHECK(got_data); | 463 DCHECK(got_data); |
| 460 if (!response.ParseFromString(data)) { | 464 if (!response.ParseFromString(data)) { |
| 461 reason = REASON_INVALID_RESPONSE_PROTO; | 465 reason = REASON_INVALID_RESPONSE_PROTO; |
| 462 result = UNKNOWN; | 466 result = UNKNOWN; |
| 463 } else if (response.verdict() == ClientDownloadResponse::SAFE) { | 467 } else if (response.verdict() == ClientDownloadResponse::SAFE) { |
| 464 reason = REASON_DOWNLOAD_SAFE; | 468 reason = REASON_DOWNLOAD_SAFE; |
| 465 result = SAFE; | 469 result = SAFE; |
| 466 } else if (service_ && !service_->IsSupportedDownload( | 470 } else if (service_ && !service_->IsSupportedDownload( |
| 467 *item_, item_->GetTargetFilePath())) { | 471 *item_, item_->GetTargetFilePath())) { |
| 468 // The client of the download protection service assumes that we don't | 472 // The client of the download protection service assumes that we don't |
| 469 // support this download so we cannot return any other verdict than | 473 // support this download so we cannot return any other verdict than |
| 470 // UNKNOWN even if the server says it's dangerous to download this file. | 474 // UNKNOWN even if the server says it's dangerous to download this file. |
| 471 // Note: if service_ is NULL we already cancelled the request and | 475 // Note: if service_ is NULL we already cancelled the request and |
| 472 // returned UNKNOWN. | 476 // returned UNKNOWN. |
| 473 reason = REASON_DOWNLOAD_NOT_SUPPORTED; | 477 reason = REASON_DOWNLOAD_NOT_SUPPORTED; |
| 474 result = UNKNOWN; | 478 result = UNKNOWN; |
| 475 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS) { | 479 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS) { |
| 476 reason = REASON_DOWNLOAD_DANGEROUS; | 480 reason = REASON_DOWNLOAD_DANGEROUS; |
| 477 result = DANGEROUS; | 481 result = DANGEROUS; |
| 482 token = response.token(); |
| 478 } else if (response.verdict() == ClientDownloadResponse::UNCOMMON) { | 483 } else if (response.verdict() == ClientDownloadResponse::UNCOMMON) { |
| 479 reason = REASON_DOWNLOAD_UNCOMMON; | 484 reason = REASON_DOWNLOAD_UNCOMMON; |
| 480 result = UNCOMMON; | 485 result = UNCOMMON; |
| 486 token = response.token(); |
| 481 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) { | 487 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) { |
| 482 reason = REASON_DOWNLOAD_DANGEROUS_HOST; | 488 reason = REASON_DOWNLOAD_DANGEROUS_HOST; |
| 483 result = DANGEROUS_HOST; | 489 result = DANGEROUS_HOST; |
| 490 token = response.token(); |
| 484 } else if ( | 491 } else if ( |
| 485 response.verdict() == ClientDownloadResponse::POTENTIALLY_UNWANTED) { | 492 response.verdict() == ClientDownloadResponse::POTENTIALLY_UNWANTED) { |
| 486 reason = REASON_DOWNLOAD_POTENTIALLY_UNWANTED; | 493 reason = REASON_DOWNLOAD_POTENTIALLY_UNWANTED; |
| 487 result = POTENTIALLY_UNWANTED; | 494 result = POTENTIALLY_UNWANTED; |
| 495 token = response.token(); |
| 488 } else { | 496 } else { |
| 489 LOG(DFATAL) << "Unknown download response verdict: " | 497 LOG(DFATAL) << "Unknown download response verdict: " |
| 490 << response.verdict(); | 498 << response.verdict(); |
| 491 reason = REASON_INVALID_RESPONSE_VERDICT; | 499 reason = REASON_INVALID_RESPONSE_VERDICT; |
| 492 result = UNKNOWN; | 500 result = UNKNOWN; |
| 493 } | 501 } |
| 502 if (!token.empty()) |
| 503 SetDownloadPingToken(item_, token); |
| 504 |
| 494 DownloadFeedbackService::MaybeStorePingsForDownload( | 505 DownloadFeedbackService::MaybeStorePingsForDownload( |
| 495 result, item_, client_download_request_data_, data); | 506 result, item_, client_download_request_data_, data); |
| 496 } | 507 } |
| 497 // We don't need the fetcher anymore. | 508 // We don't need the fetcher anymore. |
| 498 fetcher_.reset(); | 509 fetcher_.reset(); |
| 499 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestDuration", | 510 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestDuration", |
| 500 base::TimeTicks::Now() - start_time_); | 511 base::TimeTicks::Now() - start_time_); |
| 501 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestNetworkDuration", | 512 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestNetworkDuration", |
| 502 base::TimeTicks::Now() - request_start_time_); | 513 base::TimeTicks::Now() - request_start_time_); |
| 503 | 514 |
| (...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 learn_more_url, "ctx", | 1574 learn_more_url, "ctx", |
| 1564 base::IntToString(static_cast<int>(item.GetDangerType()))); | 1575 base::IntToString(static_cast<int>(item.GetDangerType()))); |
| 1565 navigator->OpenURL( | 1576 navigator->OpenURL( |
| 1566 content::OpenURLParams(learn_more_url, | 1577 content::OpenURLParams(learn_more_url, |
| 1567 content::Referrer(), | 1578 content::Referrer(), |
| 1568 NEW_FOREGROUND_TAB, | 1579 NEW_FOREGROUND_TAB, |
| 1569 ui::PAGE_TRANSITION_LINK, | 1580 ui::PAGE_TRANSITION_LINK, |
| 1570 false)); | 1581 false)); |
| 1571 } | 1582 } |
| 1572 | 1583 |
| 1584 void DownloadProtectionService::SetDownloadPingToken( |
| 1585 content::DownloadItem* item, const std::string& token) { |
| 1586 if (item) |
| 1587 item->SetUserData(kDownloadPingTokenKey, new DownloadPingToken(token)); |
| 1588 } |
| 1589 |
| 1590 std::string DownloadProtectionService::GetDownloadPingToken( |
| 1591 const content::DownloadItem* item) { |
| 1592 base::SupportsUserData::Data* token_data = |
| 1593 item->GetUserData(kDownloadPingTokenKey); |
| 1594 if (token_data) |
| 1595 return static_cast<DownloadPingToken*>(token_data)->token_string(); |
| 1596 else |
| 1597 return std::string(); |
| 1598 } |
| 1599 |
| 1573 namespace { | 1600 namespace { |
| 1574 // Escapes a certificate attribute so that it can be used in a whitelist | 1601 // Escapes a certificate attribute so that it can be used in a whitelist |
| 1575 // entry. Currently, we only escape slashes, since they are used as a | 1602 // entry. Currently, we only escape slashes, since they are used as a |
| 1576 // separator between attributes. | 1603 // separator between attributes. |
| 1577 std::string EscapeCertAttribute(const std::string& attribute) { | 1604 std::string EscapeCertAttribute(const std::string& attribute) { |
| 1578 std::string escaped; | 1605 std::string escaped; |
| 1579 for (size_t i = 0; i < attribute.size(); ++i) { | 1606 for (size_t i = 0; i < attribute.size(); ++i) { |
| 1580 if (attribute[i] == '%') { | 1607 if (attribute[i] == '%') { |
| 1581 escaped.append("%25"); | 1608 escaped.append("%25"); |
| 1582 } else if (attribute[i] == '/') { | 1609 } else if (attribute[i] == '/') { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 GURL DownloadProtectionService::GetDownloadRequestUrl() { | 1676 GURL DownloadProtectionService::GetDownloadRequestUrl() { |
| 1650 GURL url(kDownloadRequestUrl); | 1677 GURL url(kDownloadRequestUrl); |
| 1651 std::string api_key = google_apis::GetAPIKey(); | 1678 std::string api_key = google_apis::GetAPIKey(); |
| 1652 if (!api_key.empty()) | 1679 if (!api_key.empty()) |
| 1653 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); | 1680 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); |
| 1654 | 1681 |
| 1655 return url; | 1682 return url; |
| 1656 } | 1683 } |
| 1657 | 1684 |
| 1658 } // namespace safe_browsing | 1685 } // namespace safe_browsing |
| OLD | NEW |