Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: components/safe_browsing/password_protection/password_protection_service.cc

Issue 2892093003: Don't trigger Phishguard pings if we cannot compute URL reputation. (Closed)
Patch Set: update comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/field_trial.h" 10 #include "base/metrics/field_trial.h"
11 #include "base/metrics/histogram_macros.h" 11 #include "base/metrics/histogram_macros.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h" 13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "components/content_settings/core/browser/host_content_settings_map.h" 15 #include "components/content_settings/core/browser/host_content_settings_map.h"
16 #include "components/history/core/browser/history_service.h" 16 #include "components/history/core/browser/history_service.h"
17 #include "components/safe_browsing/password_protection/password_protection_reque st.h" 17 #include "components/safe_browsing/password_protection/password_protection_reque st.h"
18 #include "components/safe_browsing_db/database_manager.h" 18 #include "components/safe_browsing_db/database_manager.h"
19 #include "components/safe_browsing_db/v4_protocol_manager_util.h" 19 #include "components/safe_browsing_db/v4_protocol_manager_util.h"
20 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/web_contents.h"
21 #include "google_apis/google_api_keys.h" 22 #include "google_apis/google_api_keys.h"
22 #include "net/base/escape.h" 23 #include "net/base/escape.h"
24 #include "net/base/url_util.h"
23 25
24 using content::BrowserThread; 26 using content::BrowserThread;
27 using content::WebContents;
25 using history::HistoryService; 28 using history::HistoryService;
26 29
27 namespace safe_browsing { 30 namespace safe_browsing {
28 31
29 namespace { 32 namespace {
30 33
31 // Keys for storing password protection verdict into a DictionaryValue. 34 // Keys for storing password protection verdict into a DictionaryValue.
32 const char kCacheCreationTime[] = "cache_creation_time"; 35 const char kCacheCreationTime[] = "cache_creation_time";
33 const char kVerdictProto[] = "verdict_proto"; 36 const char kVerdictProto[] = "verdict_proto";
34 const int kRequestTimeoutMs = 10000; 37 const int kRequestTimeoutMs = 10000;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 } 102 }
100 103
101 void PasswordProtectionService::CheckCsdWhitelistOnIOThread( 104 void PasswordProtectionService::CheckCsdWhitelistOnIOThread(
102 const GURL& url, 105 const GURL& url,
103 bool* check_result) { 106 bool* check_result) {
104 DCHECK_CURRENTLY_ON(BrowserThread::IO); 107 DCHECK_CURRENTLY_ON(BrowserThread::IO);
105 *check_result = 108 *check_result =
106 url.is_valid() ? database_manager_->MatchCsdWhitelistUrl(url) : true; 109 url.is_valid() ? database_manager_->MatchCsdWhitelistUrl(url) : true;
107 } 110 }
108 111
112 bool PasswordProtectionService::CanGetReputationOfURL(const GURL& url) {
113 if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS())
114 return false;
115
116 const std::string& hostname = url.HostNoBrackets();
117 return !net::IsLocalhost(hostname) && !net::IsHostnameNonUnique(hostname) &&
118 hostname.find('.') != std::string::npos;
119 }
120
109 LoginReputationClientResponse::VerdictType 121 LoginReputationClientResponse::VerdictType
110 PasswordProtectionService::GetCachedVerdict( 122 PasswordProtectionService::GetCachedVerdict(
111 const GURL& url, 123 const GURL& url,
112 LoginReputationClientResponse* out_response) { 124 LoginReputationClientResponse* out_response) {
113 if (!url.is_valid()) 125 if (!url.is_valid())
114 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; 126 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
115 127
116 DCHECK(content_settings_); 128 DCHECK(content_settings_);
117 129
118 GURL hostname = GetHostNameWithHTTPScheme(url); 130 GURL hostname = GetHostNameWithHTTPScheme(url);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 // |verdict_diectionary|. 256 // |verdict_diectionary|.
245 content_settings_->SetWebsiteSettingDefaultScope( 257 content_settings_->SetWebsiteSettingDefaultScope(
246 primary_pattern_url, GURL(), 258 primary_pattern_url, GURL(),
247 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), 259 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
248 std::move(verdict_dictionary)); 260 std::move(verdict_dictionary));
249 } 261 }
250 } 262 }
251 } 263 }
252 264
253 void PasswordProtectionService::StartRequest( 265 void PasswordProtectionService::StartRequest(
266 WebContents* web_contents,
254 const GURL& main_frame_url, 267 const GURL& main_frame_url,
255 const GURL& password_form_action, 268 const GURL& password_form_action,
256 const GURL& password_form_frame_url, 269 const GURL& password_form_frame_url,
257 const std::string& saved_domain, 270 const std::string& saved_domain,
258 LoginReputationClientRequest::TriggerType type) { 271 LoginReputationClientRequest::TriggerType type) {
259 DCHECK_CURRENTLY_ON(BrowserThread::UI); 272 DCHECK_CURRENTLY_ON(BrowserThread::UI);
260 scoped_refptr<PasswordProtectionRequest> request( 273 scoped_refptr<PasswordProtectionRequest> request(
261 new PasswordProtectionRequest(main_frame_url, password_form_action, 274 new PasswordProtectionRequest(web_contents, main_frame_url,
275 password_form_action,
262 password_form_frame_url, saved_domain, type, 276 password_form_frame_url, saved_domain, type,
263 this, GetRequestTimeoutInMS())); 277 this, GetRequestTimeoutInMS()));
264 DCHECK(request); 278 DCHECK(request);
265 request->Start(); 279 request->Start();
266 requests_.insert(std::move(request)); 280 requests_.insert(std::move(request));
267 } 281 }
268 282
269 void PasswordProtectionService::MaybeStartPasswordFieldOnFocusRequest( 283 void PasswordProtectionService::MaybeStartPasswordFieldOnFocusRequest(
284 WebContents* web_contents,
270 const GURL& main_frame_url, 285 const GURL& main_frame_url,
271 const GURL& password_form_action, 286 const GURL& password_form_action,
272 const GURL& password_form_frame_url) { 287 const GURL& password_form_frame_url) {
273 DCHECK_CURRENTLY_ON(BrowserThread::UI); 288 DCHECK_CURRENTLY_ON(BrowserThread::UI);
274 RequestOutcome request_outcome; 289 if (CanSendPing(kPasswordFieldOnFocusPinging, main_frame_url)) {
275 if (!IsPingingEnabled(kPasswordFieldOnFocusPinging, &request_outcome)) { 290 StartRequest(web_contents, main_frame_url, password_form_action,
276 RecordPingingDisabledReason(kPasswordFieldOnFocusPinging, request_outcome); 291 password_form_frame_url,
277 return; 292 std::string(), /* saved_domain: not used for this type */
293 LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE);
278 } 294 }
279
280 // Skip URLs that we can't get a reliable reputation for.
281 if (!main_frame_url.is_valid() || !main_frame_url.SchemeIsHTTPOrHTTPS()) {
282 return;
283 }
284
285 StartRequest(main_frame_url, password_form_action, password_form_frame_url,
286 std::string(), /* saved_domain: not used for this type */
287 LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE);
288 } 295 }
289 296
290 void PasswordProtectionService::MaybeStartProtectedPasswordEntryRequest( 297 void PasswordProtectionService::MaybeStartProtectedPasswordEntryRequest(
298 WebContents* web_contents,
291 const GURL& main_frame_url, 299 const GURL& main_frame_url,
292 const std::string& saved_domain) { 300 const std::string& saved_domain) {
293 DCHECK_CURRENTLY_ON(BrowserThread::UI); 301 DCHECK_CURRENTLY_ON(BrowserThread::UI);
294 RequestOutcome request_outcome; 302 if (CanSendPing(kProtectedPasswordEntryPinging, main_frame_url)) {
295 if (!IsPingingEnabled(kProtectedPasswordEntryPinging, &request_outcome)) { 303 StartRequest(web_contents, main_frame_url, GURL(), GURL(), saved_domain,
296 RecordPingingDisabledReason(kProtectedPasswordEntryPinging, 304 LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
297 request_outcome);
298 return;
299 } 305 }
306 }
300 307
301 // Skip URLs that we can't get a reliable reputation for. 308 bool PasswordProtectionService::CanSendPing(const base::Feature& feature,
302 if (!main_frame_url.is_valid() || !main_frame_url.SchemeIsHTTPOrHTTPS()) { 309 const GURL& main_frame_url) {
303 return; 310 RequestOutcome request_outcome = URL_NOT_VALID_FOR_REPUTATION_COMPUTING;
311 if (IsPingingEnabled(kPasswordFieldOnFocusPinging, &request_outcome) &&
312 CanGetReputationOfURL(main_frame_url)) {
313 return true;
304 } 314 }
305 315 RecordNoPingingReason(feature, request_outcome);
306 StartRequest(main_frame_url, GURL(), GURL(), saved_domain, 316 return false;
307 LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
308 } 317 }
309 318
310 void PasswordProtectionService::RequestFinished( 319 void PasswordProtectionService::RequestFinished(
311 PasswordProtectionRequest* request, 320 PasswordProtectionRequest* request,
312 std::unique_ptr<LoginReputationClientResponse> response) { 321 std::unique_ptr<LoginReputationClientResponse> response) {
313 DCHECK_CURRENTLY_ON(BrowserThread::UI); 322 DCHECK_CURRENTLY_ON(BrowserThread::UI);
314 323
315 DCHECK(request); 324 DCHECK(request);
316 // TODO(jialiul): We don't cache verdict for incognito mode for now. 325 if (response)
317 // Later we may consider temporarily caching verdict.
318 if (response && !IsIncognito())
319 CacheVerdict(request->main_frame_url(), response.get(), base::Time::Now()); 326 CacheVerdict(request->main_frame_url(), response.get(), base::Time::Now());
320 327
321 // Finished processing this request. Remove it from pending list. 328 // Finished processing this request. Remove it from pending list.
322 for (auto it = requests_.begin(); it != requests_.end(); it++) { 329 for (auto it = requests_.begin(); it != requests_.end(); it++) {
323 if (it->get() == request) { 330 if (it->get() == request) {
324 requests_.erase(it); 331 requests_.erase(it);
325 break; 332 break;
326 } 333 }
327 } 334 }
328 } 335 }
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 const std::string serialized_proto(verdict->SerializeAsString()); 554 const std::string serialized_proto(verdict->SerializeAsString());
548 const std::vector<char> verdict_blob(serialized_proto.begin(), 555 const std::vector<char> verdict_blob(serialized_proto.begin(),
549 serialized_proto.end()); 556 serialized_proto.end());
550 std::unique_ptr<base::Value> binary_value = 557 std::unique_ptr<base::Value> binary_value =
551 base::MakeUnique<base::Value>(verdict_blob); 558 base::MakeUnique<base::Value>(verdict_blob);
552 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); 559 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type());
553 result->Set(kVerdictProto, std::move(binary_value)); 560 result->Set(kVerdictProto, std::move(binary_value));
554 return result; 561 return result;
555 } 562 }
556 563
557 void PasswordProtectionService::RecordPingingDisabledReason( 564 void PasswordProtectionService::RecordNoPingingReason(
558 const base::Feature& feature, 565 const base::Feature& feature,
559 RequestOutcome reason) { 566 RequestOutcome reason) {
560 DCHECK(feature.name == kProtectedPasswordEntryPinging.name || 567 DCHECK(feature.name == kProtectedPasswordEntryPinging.name ||
561 feature.name == kPasswordFieldOnFocusPinging.name); 568 feature.name == kPasswordFieldOnFocusPinging.name);
562 569
563 bool is_password_entry_ping = 570 bool is_password_entry_ping =
564 feature.name == kProtectedPasswordEntryPinging.name; 571 feature.name == kProtectedPasswordEntryPinging.name;
565 572
566 if (is_password_entry_ping) { 573 if (is_password_entry_ping) {
567 UMA_HISTOGRAM_ENUMERATION(kPasswordEntryRequestOutcomeHistogramName, reason, 574 UMA_HISTOGRAM_ENUMERATION(kPasswordEntryRequestOutcomeHistogramName, reason,
568 MAX_OUTCOME); 575 MAX_OUTCOME);
569 } else { 576 } else {
570 UMA_HISTOGRAM_ENUMERATION(kPasswordOnFocusRequestOutcomeHistogramName, 577 UMA_HISTOGRAM_ENUMERATION(kPasswordOnFocusRequestOutcomeHistogramName,
571 reason, MAX_OUTCOME); 578 reason, MAX_OUTCOME);
572 } 579 }
573 } 580 }
574 581
575 } // namespace safe_browsing 582 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698