url_checker.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/safe_search_api/url_checker.h"
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/feature_list.h"
  11. #include "base/json/json_reader.h"
  12. #include "base/logging.h"
  13. #include "base/metrics/histogram_macros.h"
  14. #include "base/strings/string_piece.h"
  15. #include "base/strings/string_util.h"
  16. #include "base/time/time.h"
  17. #include "base/values.h"
  18. namespace safe_search_api {
  19. namespace {
  20. const size_t kDefaultCacheSize = 1000;
  21. const size_t kDefaultCacheTimeoutSeconds = 3600;
  22. } // namespace
  23. struct URLChecker::Check {
  24. Check(const GURL& url, CheckCallback callback);
  25. ~Check();
  26. GURL url;
  27. std::vector<CheckCallback> callbacks;
  28. };
  29. URLChecker::Check::Check(const GURL& url, CheckCallback callback) : url(url) {
  30. callbacks.push_back(std::move(callback));
  31. }
  32. URLChecker::Check::~Check() = default;
  33. URLChecker::CheckResult::CheckResult(Classification classification,
  34. bool uncertain)
  35. : classification(classification),
  36. uncertain(uncertain),
  37. timestamp(base::TimeTicks::Now()) {}
  38. URLChecker::URLChecker(std::unique_ptr<URLCheckerClient> async_checker)
  39. : URLChecker(std::move(async_checker), kDefaultCacheSize) {}
  40. URLChecker::URLChecker(std::unique_ptr<URLCheckerClient> async_checker,
  41. size_t cache_size)
  42. : async_checker_(std::move(async_checker)),
  43. cache_(cache_size),
  44. cache_timeout_(base::Seconds(kDefaultCacheTimeoutSeconds)) {}
  45. URLChecker::~URLChecker() = default;
  46. bool URLChecker::CheckURL(const GURL& url, CheckCallback callback) {
  47. auto cache_it = cache_.Get(url);
  48. if (cache_it != cache_.end()) {
  49. const CheckResult& result = cache_it->second;
  50. base::TimeDelta age = base::TimeTicks::Now() - result.timestamp;
  51. if (age < cache_timeout_) {
  52. DVLOG(1) << "Cache hit! " << url.spec() << " is "
  53. << (result.classification == Classification::UNSAFE ? "NOT" : "")
  54. << " safe; certain: " << !result.uncertain;
  55. std::move(callback).Run(url, result.classification, result.uncertain);
  56. return true;
  57. }
  58. DVLOG(1) << "Outdated cache entry for " << url.spec() << ", purging";
  59. cache_.Erase(cache_it);
  60. }
  61. // See if we already have a check in progress for this URL.
  62. for (const auto& check : checks_in_progress_) {
  63. if (check->url == url) {
  64. DVLOG(1) << "Adding to pending check for " << url.spec();
  65. check->callbacks.push_back(std::move(callback));
  66. return false;
  67. }
  68. }
  69. auto it = checks_in_progress_.insert(
  70. checks_in_progress_.begin(),
  71. std::make_unique<Check>(url, std::move(callback)));
  72. async_checker_->CheckURL(url,
  73. base::BindOnce(&URLChecker::OnAsyncCheckComplete,
  74. weak_factory_.GetWeakPtr(), it));
  75. return false;
  76. }
  77. void URLChecker::OnAsyncCheckComplete(CheckList::iterator it,
  78. const GURL& url,
  79. ClientClassification api_classification) {
  80. bool uncertain = api_classification == ClientClassification::kUnknown;
  81. // Fallback to a |SAFE| classification when the result is not explicitly
  82. // marked as restricted.
  83. Classification classification = Classification::SAFE;
  84. if (api_classification == ClientClassification::kRestricted) {
  85. classification = Classification::UNSAFE;
  86. }
  87. std::vector<CheckCallback> callbacks = std::move(it->get()->callbacks);
  88. checks_in_progress_.erase(it);
  89. cache_.Put(url, CheckResult(classification, uncertain));
  90. for (size_t i = 0; i < callbacks.size(); i++)
  91. std::move(callbacks[i]).Run(url, classification, uncertain);
  92. }
  93. } // namespace safe_search_api