OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "components/safe_browsing/password_protection/password_protection_servi
ce.h" | 5 #include "components/safe_browsing/password_protection/password_protection_servi
ce.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 // e.g., "https://www.foo.com:80/bar/test.cgi" -> "http://www.foo.com". | 56 // e.g., "https://www.foo.com:80/bar/test.cgi" -> "http://www.foo.com". |
57 GURL GetHostNameWithHTTPScheme(const GURL& url) { | 57 GURL GetHostNameWithHTTPScheme(const GURL& url) { |
58 DCHECK(url.SchemeIsHTTPOrHTTPS()); | 58 DCHECK(url.SchemeIsHTTPOrHTTPS()); |
59 std::string result(url::kHttpScheme); | 59 std::string result(url::kHttpScheme); |
60 result.append(url::kStandardSchemeSeparator).append(url.HostNoBrackets()); | 60 result.append(url::kStandardSchemeSeparator).append(url.HostNoBrackets()); |
61 return GURL(result); | 61 return GURL(result); |
62 } | 62 } |
63 | 63 |
64 } // namespace | 64 } // namespace |
65 | 65 |
| 66 PasswordProtectionFrame::~PasswordProtectionFrame() = default; |
| 67 |
66 PasswordProtectionService::PasswordProtectionService( | 68 PasswordProtectionService::PasswordProtectionService( |
67 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, | 69 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, |
68 scoped_refptr<net::URLRequestContextGetter> request_context_getter, | 70 scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
69 HistoryService* history_service, | 71 HistoryService* history_service, |
70 HostContentSettingsMap* host_content_settings_map) | 72 HostContentSettingsMap* host_content_settings_map) |
71 : stored_verdict_count_(-1), | 73 : stored_verdict_count_(-1), |
72 database_manager_(database_manager), | 74 database_manager_(database_manager), |
73 request_context_getter_(request_context_getter), | 75 request_context_getter_(request_context_getter), |
74 history_service_observer_(this), | 76 history_service_observer_(this), |
75 content_settings_(host_content_settings_map), | 77 content_settings_(host_content_settings_map), |
76 weak_factory_(this) { | 78 weak_factory_(this) { |
77 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 79 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
78 if (history_service) | 80 if (history_service) |
79 history_service_observer_.Add(history_service); | 81 history_service_observer_.Add(history_service); |
80 } | 82 } |
81 | 83 |
82 PasswordProtectionService::~PasswordProtectionService() { | 84 PasswordProtectionService::~PasswordProtectionService() { |
| 85 tracker_.TryCancelAll(); |
83 CancelPendingRequests(); | 86 CancelPendingRequests(); |
84 history_service_observer_.RemoveAll(); | 87 history_service_observer_.RemoveAll(); |
85 weak_factory_.InvalidateWeakPtrs(); | 88 weak_factory_.InvalidateWeakPtrs(); |
86 } | 89 } |
87 | 90 |
88 void PasswordProtectionService::RecordPasswordReuse(const GURL& url) { | 91 void PasswordProtectionService::RecordPasswordReuse(const GURL& url) { |
89 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 92 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
90 DCHECK(database_manager_); | 93 DCHECK(database_manager_); |
91 if (!url.is_valid()) | 94 bool* match_whitelist = new bool(false); |
92 return; | 95 tracker_.PostTaskAndReply( |
93 | 96 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(), FROM_HERE, |
94 BrowserThread::PostTask( | 97 base::Bind(&PasswordProtectionService::CheckCsdWhitelistOnIOThread, |
95 BrowserThread::IO, FROM_HERE, | 98 base::Unretained(this), url, match_whitelist), |
96 base::Bind( | 99 base::Bind(&PasswordProtectionService::OnMatchCsdWhiteListResult, |
97 &PasswordProtectionService::CheckCsdWhitelistOnIOThread, GetWeakPtr(), | 100 base::Unretained(this), base::Owned(match_whitelist))); |
98 url, | |
99 base::Bind(&PasswordProtectionService::OnMatchCsdWhiteListResult, | |
100 base::Unretained(this)))); | |
101 } | 101 } |
102 | 102 |
103 void PasswordProtectionService::CheckCsdWhitelistOnIOThread( | 103 void PasswordProtectionService::CheckCsdWhitelistOnIOThread( |
104 const GURL& url, | 104 const GURL& url, |
105 const CheckCsdWhitelistCallback& callback) { | 105 bool* check_result) { |
106 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 106 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
107 DCHECK(database_manager_); | 107 *check_result = |
108 bool check_result = database_manager_->MatchCsdWhitelistUrl(url); | 108 url.is_valid() ? database_manager_->MatchCsdWhitelistUrl(url) : true; |
109 DCHECK(callback); | |
110 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
111 base::Bind(callback, check_result)); | |
112 } | 109 } |
113 | 110 |
114 LoginReputationClientResponse::VerdictType | 111 LoginReputationClientResponse::VerdictType |
115 PasswordProtectionService::GetCachedVerdict( | 112 PasswordProtectionService::GetCachedVerdict( |
116 const GURL& url, | 113 const GURL& url, |
117 LoginReputationClientResponse* out_response) { | 114 LoginReputationClientResponse* out_response) { |
118 if (!url.is_valid()) | 115 if (!url.is_valid()) |
119 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; | 116 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; |
120 | 117 |
121 DCHECK(content_settings_); | 118 DCHECK(content_settings_); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 // override it. | 191 // override it. |
195 verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(), | 192 verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(), |
196 std::move(verdict_entry)); | 193 std::move(verdict_entry)); |
197 content_settings_->SetWebsiteSettingDefaultScope( | 194 content_settings_->SetWebsiteSettingDefaultScope( |
198 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, | 195 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, |
199 std::string(), std::move(verdict_dictionary)); | 196 std::string(), std::move(verdict_dictionary)); |
200 } | 197 } |
201 | 198 |
202 void PasswordProtectionService::StartRequest( | 199 void PasswordProtectionService::StartRequest( |
203 const GURL& main_frame_url, | 200 const GURL& main_frame_url, |
204 LoginReputationClientRequest::TriggerType type) { | 201 LoginReputationClientRequest::TriggerType type, |
| 202 std::unique_ptr<PasswordProtectionFrameList> password_frames) { |
205 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 203 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
206 if (!IsPingingEnabled()) | 204 scoped_refptr<PasswordProtectionRequest> request( |
207 return; | 205 new PasswordProtectionRequest(main_frame_url, type, |
208 std::unique_ptr<PasswordProtectionRequest> request = | 206 std::move(password_frames), this, |
209 base::MakeUnique<PasswordProtectionRequest>( | 207 GetRequestTimeoutInMS())); |
210 main_frame_url, type, IsExtendedReporting(), IsIncognito(), | |
211 GetWeakPtr(), GetRequestTimeoutInMS()); | |
212 DCHECK(request); | 208 DCHECK(request); |
213 request->Start(); | 209 request->Start(); |
214 requests_.insert(std::move(request)); | 210 requests_.insert(std::move(request)); |
215 } | 211 } |
216 | 212 |
| 213 void PasswordProtectionService::MaybeStartLowReputationRequest( |
| 214 const GURL& main_frame_url, |
| 215 std::unique_ptr<PasswordProtectionFrameList> password_frames) { |
| 216 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 217 if (!IsPingingEnabled()) |
| 218 return; |
| 219 |
| 220 // Skip URLs that we can't get a reliable reputation for. |
| 221 if (!main_frame_url.is_valid() || !main_frame_url.SchemeIsHTTPOrHTTPS()) { |
| 222 return; |
| 223 } |
| 224 |
| 225 StartRequest(main_frame_url, |
| 226 LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, |
| 227 std::move(password_frames)); |
| 228 } |
| 229 |
217 void PasswordProtectionService::RequestFinished( | 230 void PasswordProtectionService::RequestFinished( |
218 PasswordProtectionRequest* request, | 231 PasswordProtectionRequest* request, |
219 std::unique_ptr<LoginReputationClientResponse> response) { | 232 std::unique_ptr<LoginReputationClientResponse> response) { |
220 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 233 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
221 | 234 |
222 DCHECK(request); | 235 DCHECK(request); |
223 // TODO(jialiul): We don't cache verdict for incognito mode for now. | 236 // TODO(jialiul): We don't cache verdict for incognito mode for now. |
224 // Later we may consider temporarily caching verdict. | 237 // Later we may consider temporarily caching verdict. |
225 if (!request->is_incognito() && response) | 238 if (response && !IsIncognito()) |
226 CacheVerdict(request->main_frame_url(), response.get(), base::Time::Now()); | 239 CacheVerdict(request->main_frame_url(), response.get(), base::Time::Now()); |
227 | 240 |
228 // Finished processing this request. Remove it from pending list. | 241 // Finished processing this request. Remove it from pending list. |
229 for (auto it = requests_.begin(); it != requests_.end(); it++) { | 242 for (auto it = requests_.begin(); it != requests_.end(); it++) { |
230 if (it->get() == request) { | 243 if (it->get() == request) { |
231 requests_.erase(it); | 244 requests_.erase(it); |
232 break; | 245 break; |
233 } | 246 } |
234 } | 247 } |
235 } | 248 } |
236 | 249 |
237 void PasswordProtectionService::CancelPendingRequests() { | 250 void PasswordProtectionService::CancelPendingRequests() { |
238 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 251 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
239 for (auto it = requests_.begin(); it != requests_.end();) { | 252 for (auto it = requests_.begin(); it != requests_.end();) { |
240 // We need to advance the iterator before we cancel because canceling | 253 // We need to advance the iterator before we cancel because canceling |
241 // the request will invalidate it when RequestFinished is called. | 254 // the request will invalidate it when RequestFinished is called. |
242 PasswordProtectionRequest* request = it->get(); | 255 PasswordProtectionRequest* request = it->get(); |
243 it++; | 256 it++; |
244 request->Cancel(false); | 257 request->Cancel(false); |
245 } | 258 } |
246 DCHECK(requests_.empty()); | 259 DCHECK(requests_.empty()); |
247 } | 260 } |
248 | 261 |
| 262 scoped_refptr<SafeBrowsingDatabaseManager> |
| 263 PasswordProtectionService::database_manager() { |
| 264 return database_manager_; |
| 265 } |
| 266 |
249 GURL PasswordProtectionService::GetPasswordProtectionRequestUrl() { | 267 GURL PasswordProtectionService::GetPasswordProtectionRequestUrl() { |
250 GURL url(kPasswordProtectionRequestUrl); | 268 GURL url(kPasswordProtectionRequestUrl); |
251 std::string api_key = google_apis::GetAPIKey(); | 269 std::string api_key = google_apis::GetAPIKey(); |
252 DCHECK(!api_key.empty()); | 270 DCHECK(!api_key.empty()); |
253 return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); | 271 return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); |
254 } | 272 } |
255 | 273 |
256 int PasswordProtectionService::GetStoredVerdictCount() { | 274 int PasswordProtectionService::GetStoredVerdictCount() { |
257 DCHECK(content_settings_); | 275 DCHECK(content_settings_); |
258 // If we have already computed this, return its value. | 276 // If we have already computed this, return its value. |
(...skipping 18 matching lines...) Expand all Loading... |
277 stored_verdict_count_ += static_cast<int>(verdict_dictionary->size()); | 295 stored_verdict_count_ += static_cast<int>(verdict_dictionary->size()); |
278 } | 296 } |
279 return stored_verdict_count_; | 297 return stored_verdict_count_; |
280 } | 298 } |
281 | 299 |
282 int PasswordProtectionService::GetRequestTimeoutInMS() { | 300 int PasswordProtectionService::GetRequestTimeoutInMS() { |
283 return kRequestTimeoutMs; | 301 return kRequestTimeoutMs; |
284 } | 302 } |
285 | 303 |
286 void PasswordProtectionService::OnMatchCsdWhiteListResult( | 304 void PasswordProtectionService::OnMatchCsdWhiteListResult( |
287 bool match_whitelist) { | 305 const bool* match_whitelist) { |
288 UMA_HISTOGRAM_BOOLEAN( | 306 UMA_HISTOGRAM_BOOLEAN( |
289 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist", | 307 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist", |
290 match_whitelist); | 308 *match_whitelist); |
291 } | 309 } |
292 | 310 |
293 void PasswordProtectionService::OnURLsDeleted( | 311 void PasswordProtectionService::OnURLsDeleted( |
294 history::HistoryService* history_service, | 312 history::HistoryService* history_service, |
295 bool all_history, | 313 bool all_history, |
296 bool expired, | 314 bool expired, |
297 const history::URLRows& deleted_rows, | 315 const history::URLRows& deleted_rows, |
298 const std::set<GURL>& favicon_urls) { | 316 const std::set<GURL>& favicon_urls) { |
299 BrowserThread::PostTask( | 317 BrowserThread::PostTask( |
300 BrowserThread::UI, FROM_HERE, | 318 BrowserThread::UI, FROM_HERE, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 V4ProtocolManagerUtil::GeneratePathVariantsToCheck(canonical_path, | 411 V4ProtocolManagerUtil::GeneratePathVariantsToCheck(canonical_path, |
394 std::string(), paths); | 412 std::string(), paths); |
395 } | 413 } |
396 | 414 |
397 // Return the path of the cache expression. e.g.: | 415 // Return the path of the cache expression. e.g.: |
398 // "www.google.com" -> "/" | 416 // "www.google.com" -> "/" |
399 // "www.google.com/abc" -> "/abc/" | 417 // "www.google.com/abc" -> "/abc/" |
400 // "foo.com/foo/bar/" -> "/foo/bar/" | 418 // "foo.com/foo/bar/" -> "/foo/bar/" |
401 std::string PasswordProtectionService::GetCacheExpressionPath( | 419 std::string PasswordProtectionService::GetCacheExpressionPath( |
402 const std::string& cache_expression) { | 420 const std::string& cache_expression) { |
403 DCHECK(!cache_expression.empty()); | 421 // TODO(jialiul): Change this to a DCHECk when SB server is ready. |
| 422 if (cache_expression.empty()) |
| 423 return std::string("/"); |
| 424 |
404 std::string out_put(cache_expression); | 425 std::string out_put(cache_expression); |
405 // Append a trailing slash if needed. | 426 // Append a trailing slash if needed. |
406 if (out_put[out_put.length() - 1] != '/') | 427 if (out_put[out_put.length() - 1] != '/') |
407 out_put.append("/"); | 428 out_put.append("/"); |
408 | 429 |
409 size_t first_slash_pos = out_put.find_first_of("/"); | 430 size_t first_slash_pos = out_put.find_first_of("/"); |
410 DCHECK_NE(std::string::npos, first_slash_pos); | 431 DCHECK_NE(std::string::npos, first_slash_pos); |
411 return out_put.substr(first_slash_pos); | 432 return out_put.substr(first_slash_pos); |
412 } | 433 } |
413 | 434 |
(...skipping 12 matching lines...) Expand all Loading... |
426 const std::vector<char> verdict_blob(serialized_proto.begin(), | 447 const std::vector<char> verdict_blob(serialized_proto.begin(), |
427 serialized_proto.end()); | 448 serialized_proto.end()); |
428 std::unique_ptr<base::Value> binary_value = | 449 std::unique_ptr<base::Value> binary_value = |
429 base::MakeUnique<base::Value>(verdict_blob); | 450 base::MakeUnique<base::Value>(verdict_blob); |
430 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); | 451 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); |
431 result->Set(kVerdictProto, std::move(binary_value)); | 452 result->Set(kVerdictProto, std::move(binary_value)); |
432 return result; | 453 return result; |
433 } | 454 } |
434 | 455 |
435 } // namespace safe_browsing | 456 } // namespace safe_browsing |
OLD | NEW |