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

Side by Side Diff: chrome/browser/safe_browsing/ui_manager.cc

Issue 2451623005: Remove Dangerous indicator after going back from interstitial (Closed)
Patch Set: add another test and expand one Created 4 years, 1 month 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 (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/ui_manager.h" 5 #include "chrome/browser/safe_browsing/ui_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/debug/leak_tracker.h" 10 #include "base/debug/leak_tracker.h"
(...skipping 28 matching lines...) Expand all
39 using content::NavigationEntry; 39 using content::NavigationEntry;
40 using content::WebContents; 40 using content::WebContents;
41 using safe_browsing::HitReport; 41 using safe_browsing::HitReport;
42 42
43 namespace { 43 namespace {
44 44
45 const void* const kWhitelistKey = &kWhitelistKey; 45 const void* const kWhitelistKey = &kWhitelistKey;
46 46
47 // A WhitelistUrlSet holds the set of URLs that have been whitelisted for a 47 // A WhitelistUrlSet holds the set of URLs that have been whitelisted for a
48 // specific WebContents, along with pending entries that are still undecided. 48 // specific WebContents, along with pending entries that are still undecided.
49 // The URLs in this set should come from GetWhitelistUrl() or
50 // GetMainFrameWhitelistUrlForResource().
49 class WhitelistUrlSet : public base::SupportsUserData::Data { 51 class WhitelistUrlSet : public base::SupportsUserData::Data {
50 public: 52 public:
51 WhitelistUrlSet() {} 53 WhitelistUrlSet() {}
52 54
53 bool Contains(const GURL url) { 55 bool Contains(const GURL url) { return set_.find(url) != set_.end(); }
54 return set_.find(url.GetWithEmptyPath()) != set_.end(); 56
55 } 57 void RemovePending(const GURL& url) { pending_.erase(url); }
56 58
57 void Insert(const GURL url) { 59 void Insert(const GURL url) {
58 set_.insert(url.GetWithEmptyPath()); 60 set_.insert(url);
59 pending_.erase(url.GetWithEmptyPath()); 61 RemovePending(url);
60 } 62 }
61 63
62 bool ContainsPending(const GURL url) { 64 bool ContainsPending(const GURL url) {
63 return pending_.find(url.GetWithEmptyPath()) != pending_.end(); 65 return pending_.find(url) != pending_.end();
64 } 66 }
65 67
66 void InsertPending(const GURL url) { 68 void InsertPending(const GURL url) { pending_.insert(url); }
67 pending_.insert(url.GetWithEmptyPath());
68 }
69 69
70 private: 70 private:
71 std::set<GURL> set_; 71 std::set<GURL> set_;
72 std::set<GURL> pending_; 72 std::set<GURL> pending_;
73 73
74 DISALLOW_COPY_AND_ASSIGN(WhitelistUrlSet); 74 DISALLOW_COPY_AND_ASSIGN(WhitelistUrlSet);
75 }; 75 };
76 76
77 // Returns the URL that should be used in a WhitelistUrlSet for the given
78 // |resource|.
79 GURL GetMainFrameWhitelistUrlForResource(
80 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) {
81 if (resource.is_subresource) {
82 NavigationEntry* entry = resource.GetNavigationEntryForResource();
83 if (!entry)
84 return GURL();
85 return entry->GetURL().GetWithEmptyPath();
86 }
87 return resource.url.GetWithEmptyPath();
88 }
89
90 // Returns the URL that should be used in a WhitelistUrlSet for the
91 // resource loaded from |url| on a navigation |entry|.
92 GURL GetWhitelistUrl(const GURL& url,
93 bool is_subresource,
94 NavigationEntry* entry) {
95 if (is_subresource) {
96 if (!entry)
97 return GURL();
98 return entry->GetURL().GetWithEmptyPath();
99 }
100 return url.GetWithEmptyPath();
101 }
102
77 } // namespace 103 } // namespace
78 104
79 namespace safe_browsing { 105 namespace safe_browsing {
80 106
81 // SafeBrowsingUIManager::UnsafeResource --------------------------------------- 107 // SafeBrowsingUIManager::UnsafeResource ---------------------------------------
82 108
83 SafeBrowsingUIManager::UnsafeResource::UnsafeResource() 109 SafeBrowsingUIManager::UnsafeResource::UnsafeResource()
84 : is_subresource(false), 110 : is_subresource(false),
85 threat_type(SB_THREAT_TYPE_SAFE), 111 threat_type(SB_THREAT_TYPE_SAFE),
86 threat_source(safe_browsing::ThreatSource::UNKNOWN) {} 112 threat_source(safe_browsing::ThreatSource::UNKNOWN) {}
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 if (shutdown) 171 if (shutdown)
146 sb_service_ = NULL; 172 sb_service_ = NULL;
147 } 173 }
148 174
149 void SafeBrowsingUIManager::LogPauseDelay(base::TimeDelta time) { 175 void SafeBrowsingUIManager::LogPauseDelay(base::TimeDelta time) {
150 UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time); 176 UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time);
151 } 177 }
152 178
153 void SafeBrowsingUIManager::OnBlockingPageDone( 179 void SafeBrowsingUIManager::OnBlockingPageDone(
154 const std::vector<UnsafeResource>& resources, 180 const std::vector<UnsafeResource>& resources,
155 bool proceed) { 181 bool proceed,
182 content::WebContents* web_contents,
183 const GURL& main_frame_url) {
156 DCHECK_CURRENTLY_ON(BrowserThread::UI); 184 DCHECK_CURRENTLY_ON(BrowserThread::UI);
157 for (const auto& resource : resources) { 185 for (const auto& resource : resources) {
158 if (!resource.callback.is_null()) { 186 if (!resource.callback.is_null()) {
159 DCHECK(resource.callback_thread); 187 DCHECK(resource.callback_thread);
160 resource.callback_thread->PostTask( 188 resource.callback_thread->PostTask(
161 FROM_HERE, base::Bind(resource.callback, proceed)); 189 FROM_HERE, base::Bind(resource.callback, proceed));
162 } 190 }
163 191
164 if (proceed) 192 GURL whitelist_url = GetWhitelistUrl(
165 AddToWhitelistUrlSet(resource, false /* Pending -> permanent */); 193 main_frame_url, false /* is subresource */,
194 nullptr /* no navigation entry needed for main resource */);
195 if (proceed) {
196 AddToWhitelistUrlSet(whitelist_url, web_contents,
197 false /* Pending -> permanent */);
198 } else if (web_contents) {
199 // |web_contents| doesn't exist if the tab has been closed.
200 RemoveFromPendingWhitelistUrlSet(whitelist_url, web_contents);
201 }
166 } 202 }
167 } 203 }
168 204
169 void SafeBrowsingUIManager::DisplayBlockingPage( 205 void SafeBrowsingUIManager::DisplayBlockingPage(
170 const UnsafeResource& resource) { 206 const UnsafeResource& resource) {
171 DCHECK_CURRENTLY_ON(BrowserThread::UI); 207 DCHECK_CURRENTLY_ON(BrowserThread::UI);
172 if (resource.is_subresource && !resource.is_subframe) { 208 if (resource.is_subresource && !resource.is_subframe) {
173 // Sites tagged as serving Unwanted Software should only show a warning for 209 // Sites tagged as serving Unwanted Software should only show a warning for
174 // main-frame or sub-frame resource. Similar warning restrictions should be 210 // main-frame or sub-frame resource. Similar warning restrictions should be
175 // applied to malware sites tagged as "landing sites" (see "Types of 211 // applied to malware sites tagged as "landing sites" (see "Types of
(...skipping 13 matching lines...) Expand all
189 return; 225 return;
190 } 226 }
191 } 227 }
192 228
193 // The tab might have been closed. If it was closed, just act as if "Don't 229 // The tab might have been closed. If it was closed, just act as if "Don't
194 // Proceed" had been chosen. 230 // Proceed" had been chosen.
195 WebContents* web_contents = resource.web_contents_getter.Run(); 231 WebContents* web_contents = resource.web_contents_getter.Run();
196 if (!web_contents) { 232 if (!web_contents) {
197 std::vector<UnsafeResource> resources; 233 std::vector<UnsafeResource> resources;
198 resources.push_back(resource); 234 resources.push_back(resource);
199 OnBlockingPageDone(resources, false); 235 OnBlockingPageDone(resources, false, web_contents,
236 GetMainFrameWhitelistUrlForResource(resource));
200 return; 237 return;
201 } 238 }
202 239
203 // Check if the user has already ignored a SB warning for the same WebContents 240 // Check if the user has already ignored a SB warning for the same WebContents
204 // and top-level domain. 241 // and top-level domain.
205 if (IsWhitelisted(resource)) { 242 if (IsWhitelisted(resource)) {
206 if (!resource.callback.is_null()) { 243 if (!resource.callback.is_null()) {
207 DCHECK(resource.callback_thread); 244 DCHECK(resource.callback_thread);
208 resource.callback_thread->PostTask(FROM_HERE, 245 resource.callback_thread->PostTask(FROM_HERE,
209 base::Bind(resource.callback, true)); 246 base::Bind(resource.callback, true));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 hit_report.is_metrics_reporting_active = 282 hit_report.is_metrics_reporting_active =
246 ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled(); 283 ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
247 284
248 MaybeReportSafeBrowsingHit(hit_report); 285 MaybeReportSafeBrowsingHit(hit_report);
249 } 286 }
250 287
251 if (resource.threat_type != SB_THREAT_TYPE_SAFE) { 288 if (resource.threat_type != SB_THREAT_TYPE_SAFE) {
252 for (Observer& observer : observer_list_) 289 for (Observer& observer : observer_list_)
253 observer.OnSafeBrowsingHit(resource); 290 observer.OnSafeBrowsingHit(resource);
254 } 291 }
255 AddToWhitelistUrlSet(resource, true /* A decision is now pending */); 292 AddToWhitelistUrlSet(GetMainFrameWhitelistUrlForResource(resource),
293 resource.web_contents_getter.Run(),
294 true /* A decision is now pending */);
256 SafeBrowsingBlockingPage::ShowBlockingPage(this, resource); 295 SafeBrowsingBlockingPage::ShowBlockingPage(this, resource);
257 } 296 }
258 297
259 // A safebrowsing hit is sent after a blocking page for malware/phishing 298 // A safebrowsing hit is sent after a blocking page for malware/phishing
260 // or after the warning dialog for download urls, only for 299 // or after the warning dialog for download urls, only for
261 // UMA || extended_reporting users. 300 // UMA || extended_reporting users.
262 void SafeBrowsingUIManager::MaybeReportSafeBrowsingHit( 301 void SafeBrowsingUIManager::MaybeReportSafeBrowsingHit(
263 const HitReport& hit_report) { 302 const HitReport& hit_report) {
264 DCHECK_CURRENTLY_ON(BrowserThread::UI); 303 DCHECK_CURRENTLY_ON(BrowserThread::UI);
265 304
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 void SafeBrowsingUIManager::AddObserver(Observer* observer) { 350 void SafeBrowsingUIManager::AddObserver(Observer* observer) {
312 DCHECK_CURRENTLY_ON(BrowserThread::UI); 351 DCHECK_CURRENTLY_ON(BrowserThread::UI);
313 observer_list_.AddObserver(observer); 352 observer_list_.AddObserver(observer);
314 } 353 }
315 354
316 void SafeBrowsingUIManager::RemoveObserver(Observer* observer) { 355 void SafeBrowsingUIManager::RemoveObserver(Observer* observer) {
317 DCHECK_CURRENTLY_ON(BrowserThread::UI); 356 DCHECK_CURRENTLY_ON(BrowserThread::UI);
318 observer_list_.RemoveObserver(observer); 357 observer_list_.RemoveObserver(observer);
319 } 358 }
320 359
360 // Static.
361 void SafeBrowsingUIManager::CreateWhitelistForTesting(
362 content::WebContents* web_contents) {
Nathan Parker 2016/10/31 23:54:38 nit: How about putting this code in a "WhitelistUr
estark 2016/11/01 02:41:16 Done.
363 WhitelistUrlSet* site_list =
364 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey));
365 if (!site_list) {
366 site_list = new WhitelistUrlSet;
367 web_contents->SetUserData(kWhitelistKey, site_list);
368 }
369 }
370
321 void SafeBrowsingUIManager::ReportInvalidCertificateChainOnIOThread( 371 void SafeBrowsingUIManager::ReportInvalidCertificateChainOnIOThread(
322 const std::string& serialized_report) { 372 const std::string& serialized_report) {
323 DCHECK_CURRENTLY_ON(BrowserThread::IO); 373 DCHECK_CURRENTLY_ON(BrowserThread::IO);
324 374
325 // The service may delete the ping manager (i.e. when user disabling service, 375 // The service may delete the ping manager (i.e. when user disabling service,
326 // etc). This happens on the IO thread. 376 // etc). This happens on the IO thread.
327 if (!sb_service_ || !sb_service_->ping_manager()) 377 if (!sb_service_ || !sb_service_->ping_manager())
328 return; 378 return;
329 379
330 sb_service_->ping_manager()->ReportInvalidCertificateChain(serialized_report); 380 sb_service_->ping_manager()->ReportInvalidCertificateChain(serialized_report);
(...skipping 21 matching lines...) Expand all
352 // etc). This happens on the IO thread. 402 // etc). This happens on the IO thread.
353 if (sb_service_.get() == NULL || sb_service_->ping_manager() == NULL) 403 if (sb_service_.get() == NULL || sb_service_->ping_manager() == NULL)
354 return; 404 return;
355 405
356 if (!serialized.empty()) { 406 if (!serialized.empty()) {
357 DVLOG(1) << "Sending serialized threat details."; 407 DVLOG(1) << "Sending serialized threat details.";
358 sb_service_->ping_manager()->ReportThreatDetails(serialized); 408 sb_service_->ping_manager()->ReportThreatDetails(serialized);
359 } 409 }
360 } 410 }
361 411
362 // Record this domain in the current WebContents as either whitelisted or 412 // Record this domain in the given WebContents as either whitelisted or
363 // pending whitelisting (if an interstitial is currently displayed). If an 413 // pending whitelisting (if an interstitial is currently displayed). If an
364 // existing WhitelistUrlSet does not yet exist, create a new WhitelistUrlSet. 414 // existing WhitelistUrlSet does not yet exist, create a new WhitelistUrlSet.
365 void SafeBrowsingUIManager::AddToWhitelistUrlSet(const UnsafeResource& resource, 415 void SafeBrowsingUIManager::AddToWhitelistUrlSet(
366 bool pending) { 416 const GURL& whitelist_url,
417 content::WebContents* web_contents,
418 bool pending) {
367 DCHECK_CURRENTLY_ON(BrowserThread::UI); 419 DCHECK_CURRENTLY_ON(BrowserThread::UI);
368 420
369 WebContents* web_contents = resource.web_contents_getter.Run(); 421 // A WebContents might not exist if the tab has been closed.
422 if (!web_contents)
423 return;
424
370 WhitelistUrlSet* site_list = 425 WhitelistUrlSet* site_list =
371 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); 426 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey));
372 if (!site_list) { 427 if (!site_list) {
373 site_list = new WhitelistUrlSet; 428 site_list = new WhitelistUrlSet;
374 web_contents->SetUserData(kWhitelistKey, site_list); 429 web_contents->SetUserData(kWhitelistKey, site_list);
375 } 430 }
376 431
377 GURL whitelisted_url; 432 if (whitelist_url.is_empty())
378 if (resource.is_subresource) { 433 return;
379 NavigationEntry* entry = resource.GetNavigationEntryForResource(); 434
380 if (!entry) 435 if (pending) {
381 return; 436 site_list->InsertPending(whitelist_url);
382 whitelisted_url = entry->GetURL();
383 } else { 437 } else {
384 whitelisted_url = resource.url; 438 site_list->Insert(whitelist_url);
385 } 439 }
386 440
387 if (pending) { 441 // Notify security UI that security state has changed.
388 site_list->InsertPending(whitelisted_url); 442 web_contents->DidChangeVisibleSecurityState();
389 } else { 443 }
390 site_list->Insert(whitelisted_url); 444
391 } 445 void SafeBrowsingUIManager::RemoveFromPendingWhitelistUrlSet(
446 const GURL& whitelist_url,
447 content::WebContents* web_contents) {
448 DCHECK_CURRENTLY_ON(BrowserThread::UI);
449
450 // A WebContents might not exist if the tab has been closed.
451 if (!web_contents)
452 return;
453
454 // Use |web_contents| rather than |resource.web_contents_getter|
455 // here. By this point, a "Back" navigation could have already been
456 // committed, so the page loading |resource| might be gone and
457 // |web_contents_getter| may no longer be valid.
458 WhitelistUrlSet* site_list =
459 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey));
460
461 if (whitelist_url.is_empty())
462 return;
463
464 // Note that this function does not DCHECK that |whitelist_url|
465 // appears in the pending whitelist. In the common case, it's expected
466 // that a URL is in the pending whitelist when it is removed, but it's
467 // not always the case. For example, if there are several blocking
468 // pages queued up for different resources on the same page, and the
Nathan Parker 2016/10/31 23:54:38 I thought we didn't queue up several warnings per
estark 2016/11/01 02:41:17 Hrm. I was basing this on https://cs.chromium.org/
estark 2016/11/01 03:00:08 I lied, things do get queued to the UnsafeResource
469 // user goes back to dimiss the first one, the subsequent blocking
470 // pages get dismissed as well (as if the user had clicked "Back to
471 // safety" on each of them). In this case, the first dismissal will
472 // remove the main-frame URL from the pending whitelist, so the
473 // main-frame URL will have already been removed when the subsequent
474 // blocking pages are dismissed.
475 if (site_list->ContainsPending(whitelist_url))
476 site_list->RemovePending(whitelist_url);
392 477
393 // Notify security UI that security state has changed. 478 // Notify security UI that security state has changed.
394 web_contents->DidChangeVisibleSecurityState(); 479 web_contents->DidChangeVisibleSecurityState();
395 } 480 }
396 481
397 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { 482 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) {
398 NavigationEntry* entry = nullptr; 483 NavigationEntry* entry = nullptr;
399 if (resource.is_subresource) { 484 if (resource.is_subresource) {
400 entry = resource.GetNavigationEntryForResource(); 485 entry = resource.GetNavigationEntryForResource();
401 } 486 }
402 return IsUrlWhitelistedOrPendingForWebContents( 487 return IsUrlWhitelistedOrPendingForWebContents(
403 resource.url, resource.is_subresource, entry, 488 resource.url, resource.is_subresource, entry,
404 resource.web_contents_getter.Run(), true); 489 resource.web_contents_getter.Run(), true);
405 } 490 }
406 491
407 // Check if the user has already seen and/or ignored a SB warning for this 492 // Check if the user has already seen and/or ignored a SB warning for this
408 // WebContents and top-level domain. 493 // WebContents and top-level domain.
409 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents( 494 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents(
410 const GURL& url, 495 const GURL& url,
411 bool is_subresource, 496 bool is_subresource,
412 NavigationEntry* entry, 497 NavigationEntry* entry,
413 content::WebContents* web_contents, 498 content::WebContents* web_contents,
414 bool whitelist_only) { 499 bool whitelist_only) {
415 DCHECK_CURRENTLY_ON(BrowserThread::UI); 500 DCHECK_CURRENTLY_ON(BrowserThread::UI);
416 501
417 GURL lookup_url; 502 GURL lookup_url = GetWhitelistUrl(url, is_subresource, entry);
418 if (is_subresource) { 503 if (lookup_url.is_empty())
419 if (!entry) 504 return false;
420 return false;
421 lookup_url = entry->GetURL();
422 } else {
423 lookup_url = url;
424 }
425 505
426 WhitelistUrlSet* site_list = 506 WhitelistUrlSet* site_list =
427 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); 507 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey));
428 if (!site_list) 508 if (!site_list)
429 return false; 509 return false;
430 510
431 bool whitelisted = site_list->Contains(lookup_url); 511 bool whitelisted = site_list->Contains(lookup_url);
432 if (whitelist_only) { 512 if (whitelist_only) {
433 return whitelisted; 513 return whitelisted;
434 } else { 514 } else {
435 return whitelisted || site_list->ContainsPending(lookup_url); 515 return whitelisted || site_list->ContainsPending(lookup_url);
436 } 516 }
437 } 517 }
438 518
519 // Static.
520 GURL SafeBrowsingUIManager::GetMainFrameWhitelistUrlForResourceForTesting(
521 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) {
522 return GetMainFrameWhitelistUrlForResource(resource);
523 }
524
439 } // namespace safe_browsing 525 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698