OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/supervised_user/experimental/supervised_user_async_url_
checker.h" | 5 #include "chrome/browser/supervised_user/experimental/supervised_user_async_url_
checker.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 using net::URLRequestContextGetter; | 28 using net::URLRequestContextGetter; |
29 using net::URLRequestStatus; | 29 using net::URLRequestStatus; |
30 | 30 |
31 namespace { | 31 namespace { |
32 | 32 |
33 const char kApiUrl[] = "https://safesearch.googleapis.com/v1:classify"; | 33 const char kApiUrl[] = "https://safesearch.googleapis.com/v1:classify"; |
34 const char kDataContentType[] = "application/x-www-form-urlencoded"; | 34 const char kDataContentType[] = "application/x-www-form-urlencoded"; |
35 const char kDataFormat[] = "key=%s&urls=%s"; | 35 const char kDataFormat[] = "key=%s&urls=%s"; |
36 | 36 |
37 const size_t kDefaultCacheSize = 1000; | 37 const size_t kDefaultCacheSize = 1000; |
| 38 const size_t kDefaultCacheTimeoutSeconds = 3600; |
38 | 39 |
39 // Builds the POST data for SafeSearch API requests. | 40 // Builds the POST data for SafeSearch API requests. |
40 std::string BuildRequestData(const std::string& api_key, const GURL& url) { | 41 std::string BuildRequestData(const std::string& api_key, const GURL& url) { |
41 std::string query = net::EscapeQueryParamValue(url.spec(), true); | 42 std::string query = net::EscapeQueryParamValue(url.spec(), true); |
42 return base::StringPrintf(kDataFormat, api_key.c_str(), query.c_str()); | 43 return base::StringPrintf(kDataFormat, api_key.c_str(), query.c_str()); |
43 } | 44 } |
44 | 45 |
45 // Creates a URLFetcher to call the SafeSearch API for |url|. | 46 // Creates a URLFetcher to call the SafeSearch API for |url|. |
46 scoped_ptr<net::URLFetcher> CreateFetcher(URLFetcherDelegate* delegate, | 47 scoped_ptr<net::URLFetcher> CreateFetcher(URLFetcherDelegate* delegate, |
47 URLRequestContextGetter* context, | 48 URLRequestContextGetter* context, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 88 |
88 struct SupervisedUserAsyncURLChecker::Check { | 89 struct SupervisedUserAsyncURLChecker::Check { |
89 Check(const GURL& url, | 90 Check(const GURL& url, |
90 scoped_ptr<net::URLFetcher> fetcher, | 91 scoped_ptr<net::URLFetcher> fetcher, |
91 const CheckCallback& callback); | 92 const CheckCallback& callback); |
92 ~Check(); | 93 ~Check(); |
93 | 94 |
94 GURL url; | 95 GURL url; |
95 scoped_ptr<net::URLFetcher> fetcher; | 96 scoped_ptr<net::URLFetcher> fetcher; |
96 std::vector<CheckCallback> callbacks; | 97 std::vector<CheckCallback> callbacks; |
97 base::Time start_time; | 98 base::TimeTicks start_time; |
98 }; | 99 }; |
99 | 100 |
100 SupervisedUserAsyncURLChecker::Check::Check( | 101 SupervisedUserAsyncURLChecker::Check::Check( |
101 const GURL& url, | 102 const GURL& url, |
102 scoped_ptr<net::URLFetcher> fetcher, | 103 scoped_ptr<net::URLFetcher> fetcher, |
103 const CheckCallback& callback) | 104 const CheckCallback& callback) |
104 : url(url), | 105 : url(url), |
105 fetcher(fetcher.Pass()), | 106 fetcher(fetcher.Pass()), |
106 callbacks(1, callback), | 107 callbacks(1, callback), |
107 start_time(base::Time::Now()) { | 108 start_time(base::TimeTicks::Now()) { |
108 } | 109 } |
109 | 110 |
110 SupervisedUserAsyncURLChecker::Check::~Check() {} | 111 SupervisedUserAsyncURLChecker::Check::~Check() {} |
111 | 112 |
112 SupervisedUserAsyncURLChecker::CheckResult::CheckResult( | 113 SupervisedUserAsyncURLChecker::CheckResult::CheckResult( |
113 SupervisedUserURLFilter::FilteringBehavior behavior, bool uncertain) | 114 SupervisedUserURLFilter::FilteringBehavior behavior, |
114 : behavior(behavior), uncertain(uncertain) { | 115 bool uncertain) |
115 } | 116 : behavior(behavior), |
| 117 uncertain(uncertain), |
| 118 timestamp(base::TimeTicks::Now()) {} |
116 | 119 |
117 SupervisedUserAsyncURLChecker::SupervisedUserAsyncURLChecker( | 120 SupervisedUserAsyncURLChecker::SupervisedUserAsyncURLChecker( |
118 URLRequestContextGetter* context) | 121 URLRequestContextGetter* context) |
119 : context_(context), cache_(kDefaultCacheSize) { | 122 : SupervisedUserAsyncURLChecker(context, kDefaultCacheSize) {} |
120 } | |
121 | 123 |
122 SupervisedUserAsyncURLChecker::SupervisedUserAsyncURLChecker( | 124 SupervisedUserAsyncURLChecker::SupervisedUserAsyncURLChecker( |
123 URLRequestContextGetter* context, | 125 URLRequestContextGetter* context, |
124 size_t cache_size) | 126 size_t cache_size) |
125 : context_(context), cache_(cache_size) { | 127 : context_(context), |
126 } | 128 cache_(cache_size), |
| 129 cache_timeout_( |
| 130 base::TimeDelta::FromSeconds(kDefaultCacheTimeoutSeconds)) {} |
127 | 131 |
128 SupervisedUserAsyncURLChecker::~SupervisedUserAsyncURLChecker() {} | 132 SupervisedUserAsyncURLChecker::~SupervisedUserAsyncURLChecker() {} |
129 | 133 |
130 bool SupervisedUserAsyncURLChecker::CheckURL(const GURL& url, | 134 bool SupervisedUserAsyncURLChecker::CheckURL(const GURL& url, |
131 const CheckCallback& callback) { | 135 const CheckCallback& callback) { |
132 // TODO(treib): Hack: For now, allow all Google URLs to save search QPS. If we | 136 // TODO(treib): Hack: For now, allow all Google URLs to save QPS. If we ever |
133 // ever remove this, we should find a way to allow at least the NTP. | 137 // remove this, we should find a way to allow at least the NTP. |
134 if (google_util::IsGoogleDomainUrl(url, | 138 if (google_util::IsGoogleDomainUrl(url, |
135 google_util::ALLOW_SUBDOMAIN, | 139 google_util::ALLOW_SUBDOMAIN, |
136 google_util::ALLOW_NON_STANDARD_PORTS)) { | 140 google_util::ALLOW_NON_STANDARD_PORTS)) { |
137 callback.Run(url, SupervisedUserURLFilter::ALLOW, false); | 141 callback.Run(url, SupervisedUserURLFilter::ALLOW, false); |
138 return true; | 142 return true; |
139 } | 143 } |
140 // TODO(treib): Hack: For now, allow all YouTube URLs since YouTube has its | 144 // TODO(treib): Hack: For now, allow all YouTube URLs since YouTube has its |
141 // own Safety Mode anyway. | 145 // own Safety Mode anyway. |
142 if (google_util::IsYoutubeDomainUrl(url, | 146 if (google_util::IsYoutubeDomainUrl(url, |
143 google_util::ALLOW_SUBDOMAIN, | 147 google_util::ALLOW_SUBDOMAIN, |
144 google_util::ALLOW_NON_STANDARD_PORTS)) { | 148 google_util::ALLOW_NON_STANDARD_PORTS)) { |
145 callback.Run(url, SupervisedUserURLFilter::ALLOW, false); | 149 callback.Run(url, SupervisedUserURLFilter::ALLOW, false); |
146 return true; | 150 return true; |
147 } | 151 } |
148 | 152 |
149 auto cache_it = cache_.Get(url); | 153 auto cache_it = cache_.Get(url); |
150 if (cache_it != cache_.end()) { | 154 if (cache_it != cache_.end()) { |
151 const CheckResult& result = cache_it->second; | 155 const CheckResult& result = cache_it->second; |
152 DVLOG(1) << "Cache hit! " << url.spec() << " is " | 156 base::TimeDelta age = base::TimeTicks::Now() - result.timestamp; |
153 << (result.behavior == SupervisedUserURLFilter::BLOCK ? "NOT" : "") | 157 if (age < cache_timeout_) { |
154 << " safe; certain: " << !result.uncertain; | 158 DVLOG(1) << "Cache hit! " << url.spec() << " is " |
155 callback.Run(url, result.behavior, result.uncertain); | 159 << (result.behavior == SupervisedUserURLFilter::BLOCK ? "NOT" |
156 return true; | 160 : "") |
| 161 << " safe; certain: " << !result.uncertain; |
| 162 callback.Run(url, result.behavior, result.uncertain); |
| 163 return true; |
| 164 } |
| 165 DVLOG(1) << "Outdated cache entry for " << url.spec() << ", purging"; |
| 166 cache_.Erase(cache_it); |
157 } | 167 } |
158 | 168 |
159 // See if we already have a check in progress for this URL. | 169 // See if we already have a check in progress for this URL. |
160 for (Check* check : checks_in_progress_) { | 170 for (Check* check : checks_in_progress_) { |
161 if (check->url == url) { | 171 if (check->url == url) { |
162 DVLOG(1) << "Adding to pending check for " << url.spec(); | 172 DVLOG(1) << "Adding to pending check for " << url.spec(); |
163 check->callbacks.push_back(callback); | 173 check->callbacks.push_back(callback); |
164 return false; | 174 return false; |
165 } | 175 } |
166 } | 176 } |
(...skipping 27 matching lines...) Expand all Loading... |
194 } | 204 } |
195 | 205 |
196 std::string response_body; | 206 std::string response_body; |
197 source->GetResponseAsString(&response_body); | 207 source->GetResponseAsString(&response_body); |
198 bool is_porn = false; | 208 bool is_porn = false; |
199 bool uncertain = !ParseResponse(response_body, &is_porn); | 209 bool uncertain = !ParseResponse(response_body, &is_porn); |
200 SupervisedUserURLFilter::FilteringBehavior behavior = | 210 SupervisedUserURLFilter::FilteringBehavior behavior = |
201 is_porn ? SupervisedUserURLFilter::BLOCK : SupervisedUserURLFilter::ALLOW; | 211 is_porn ? SupervisedUserURLFilter::BLOCK : SupervisedUserURLFilter::ALLOW; |
202 | 212 |
203 UMA_HISTOGRAM_TIMES("ManagedUsers.SafeSitesDelay", | 213 UMA_HISTOGRAM_TIMES("ManagedUsers.SafeSitesDelay", |
204 base::Time::Now() - check->start_time); | 214 base::TimeTicks::Now() - check->start_time); |
205 | 215 |
206 cache_.Put(check->url, CheckResult(behavior, uncertain)); | 216 cache_.Put(check->url, CheckResult(behavior, uncertain)); |
207 | 217 |
208 for (size_t i = 0; i < check->callbacks.size(); i++) | 218 for (size_t i = 0; i < check->callbacks.size(); i++) |
209 check->callbacks[i].Run(check->url, behavior, uncertain); | 219 check->callbacks[i].Run(check->url, behavior, uncertain); |
210 checks_in_progress_.erase(it); | 220 checks_in_progress_.erase(it); |
211 } | 221 } |
OLD | NEW |