Roll src/third_party/WebKit 8b42d1d:744641d (svn 186770:186771)
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_blocking_page.cc
blob63921b955ba43e327f44cc39e3310455b44de285
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
3 // found in the LICENSE file.
4 //
5 // Implementation of the SafeBrowsingBlockingPage class.
7 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
9 #include <string>
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/i18n/rtl.h"
14 #include "base/lazy_instance.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/time/time.h"
23 #include "base/values.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/history/history_service_factory.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/renderer_preferences_util.h"
28 #include "chrome/browser/safe_browsing/malware_details.h"
29 #include "chrome/browser/safe_browsing/ui_manager.h"
30 #include "chrome/browser/tab_contents/tab_util.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/url_constants.h"
34 #include "chrome/grit/generated_resources.h"
35 #include "chrome/grit/locale_settings.h"
36 #include "components/google/core/browser/google_util.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/interstitial_page.h"
39 #include "content/public/browser/navigation_controller.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/common/renderer_preferences.h"
43 #include "grit/browser_resources.h"
44 #include "net/base/escape.h"
45 #include "ui/base/l10n/l10n_util.h"
47 #if defined(ENABLE_EXTENSIONS)
48 #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h"
49 #endif
51 using base::UserMetricsAction;
52 using content::BrowserThread;
53 using content::InterstitialPage;
54 using content::OpenURLParams;
55 using content::Referrer;
56 using content::WebContents;
58 #if defined(ENABLE_EXTENSIONS)
59 using extensions::ExperienceSamplingEvent;
60 #endif
62 namespace {
64 // For malware interstitial pages, we link the problematic URL to Google's
65 // diagnostic page.
66 #if defined(GOOGLE_CHROME_BUILD)
67 const char kSbDiagnosticUrl[] =
68 "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=googlechrome";
69 #else
70 const char kSbDiagnosticUrl[] =
71 "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=chromium";
72 #endif
74 // URL for malware and phishing, V2.
75 const char kLearnMoreMalwareUrlV2[] =
76 "https://www.google.com/transparencyreport/safebrowsing/";
77 const char kLearnMorePhishingUrlV2[] =
78 "https://www.google.com/transparencyreport/safebrowsing/";
80 const char kPrivacyLinkHtml[] =
81 "<a id=\"privacy-link\" href=\"\" onclick=\"sendCommand('showPrivacy'); "
82 "return false;\" onmousedown=\"return false;\">%s</a>";
84 // After a malware interstitial where the user opted-in to the report
85 // but clicked "proceed anyway", we delay the call to
86 // MalwareDetails::FinishCollection() by this much time (in
87 // milliseconds).
88 const int64 kMalwareDetailsProceedDelayMilliSeconds = 3000;
90 // The commands returned by the page when the user performs an action.
91 const char kDoReportCommand[] = "doReport";
92 const char kDontReportCommand[] = "dontReport";
93 const char kExpandedSeeMoreCommand[] = "expandedSeeMore";
94 const char kLearnMoreCommand[] = "learnMore2";
95 const char kProceedCommand[] = "proceed";
96 const char kShowDiagnosticCommand[] = "showDiagnostic";
97 const char kShowPrivacyCommand[] = "showPrivacy";
98 const char kTakeMeBackCommand[] = "takeMeBack";
100 // Other constants used to communicate with the JavaScript.
101 const char kBoxChecked[] = "boxchecked";
102 const char kDisplayCheckBox[] = "displaycheckbox";
104 // Constants for the Experience Sampling instrumentation.
105 #if defined(ENABLE_EXTENSIONS)
106 const char kEventNameMalware[] = "safebrowsing_interstitial_";
107 const char kEventNameHarmful[] = "harmful_interstitial_";
108 const char kEventNamePhishing[] = "phishing_interstitial_";
109 const char kEventNameOther[] = "safebrowsing_other_interstitial_";
110 #endif
112 base::LazyInstance<SafeBrowsingBlockingPage::UnsafeResourceMap>
113 g_unsafe_resource_map = LAZY_INSTANCE_INITIALIZER;
115 } // namespace
117 // static
118 SafeBrowsingBlockingPageFactory* SafeBrowsingBlockingPage::factory_ = NULL;
120 // The default SafeBrowsingBlockingPageFactory. Global, made a singleton so we
121 // don't leak it.
122 class SafeBrowsingBlockingPageFactoryImpl
123 : public SafeBrowsingBlockingPageFactory {
124 public:
125 SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
126 SafeBrowsingUIManager* ui_manager,
127 WebContents* web_contents,
128 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
129 override {
130 return new SafeBrowsingBlockingPage(ui_manager, web_contents,
131 unsafe_resources);
134 private:
135 friend struct base::DefaultLazyInstanceTraits<
136 SafeBrowsingBlockingPageFactoryImpl>;
138 SafeBrowsingBlockingPageFactoryImpl() { }
140 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageFactoryImpl);
143 static base::LazyInstance<SafeBrowsingBlockingPageFactoryImpl>
144 g_safe_browsing_blocking_page_factory_impl = LAZY_INSTANCE_INITIALIZER;
146 // static
147 const void* SafeBrowsingBlockingPage::kTypeForTesting =
148 &SafeBrowsingBlockingPage::kTypeForTesting;
150 SafeBrowsingBlockingPage::SafeBrowsingBlockingPage(
151 SafeBrowsingUIManager* ui_manager,
152 WebContents* web_contents,
153 const UnsafeResourceList& unsafe_resources)
154 : SecurityInterstitialPage(web_contents, unsafe_resources[0].url),
155 malware_details_proceed_delay_ms_(
156 kMalwareDetailsProceedDelayMilliSeconds),
157 ui_manager_(ui_manager),
158 report_loop_(NULL),
159 is_main_frame_load_blocked_(IsMainPageLoadBlocked(unsafe_resources)),
160 unsafe_resources_(unsafe_resources),
161 proceeded_(false),
162 num_visits_(-1) {
163 bool malware = false;
164 bool harmful = false;
165 bool phishing = false;
166 for (UnsafeResourceList::const_iterator iter = unsafe_resources_.begin();
167 iter != unsafe_resources_.end(); ++iter) {
168 const UnsafeResource& resource = *iter;
169 SBThreatType threat_type = resource.threat_type;
170 if (threat_type == SB_THREAT_TYPE_URL_MALWARE ||
171 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL) {
172 malware = true;
173 } else if (threat_type == SB_THREAT_TYPE_URL_UNWANTED) {
174 harmful = true;
175 } else {
176 DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
177 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
178 phishing = true;
181 DCHECK(phishing || malware || harmful);
182 if (malware)
183 interstitial_type_ = TYPE_MALWARE;
184 else if (harmful)
185 interstitial_type_ = TYPE_HARMFUL;
186 else
187 interstitial_type_ = TYPE_PHISHING;
189 RecordUserDecision(SHOW);
190 RecordUserInteraction(TOTAL_VISITS);
191 if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled))
192 RecordUserDecision(PROCEEDING_DISABLED);
194 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
195 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
196 Profile::EXPLICIT_ACCESS);
197 if (history_service) {
198 history_service->GetVisibleVisitCountToHost(
199 request_url(),
200 base::Bind(&SafeBrowsingBlockingPage::OnGotHistoryCount,
201 base::Unretained(this)),
202 &request_tracker_);
205 if (!is_main_frame_load_blocked_) {
206 navigation_entry_index_to_remove_ =
207 web_contents->GetController().GetLastCommittedEntryIndex();
208 } else {
209 navigation_entry_index_to_remove_ = -1;
212 // Start computing malware details. They will be sent only
213 // if the user opts-in on the blocking page later.
214 // If there's more than one malicious resources, it means the user
215 // clicked through the first warning, so we don't prepare additional
216 // reports.
217 if (unsafe_resources.size() == 1 &&
218 unsafe_resources[0].threat_type == SB_THREAT_TYPE_URL_MALWARE &&
219 malware_details_.get() == NULL && CanShowMalwareDetailsOption()) {
220 malware_details_ = MalwareDetails::NewMalwareDetails(
221 ui_manager_, web_contents, unsafe_resources[0]);
224 #if defined(ENABLE_EXTENSIONS)
225 // ExperienceSampling: Set up new sampling event for this interstitial.
226 // This needs to handle all types of warnings this interstitial can show.
227 std::string event_name;
228 switch (interstitial_type_) {
229 case TYPE_MALWARE:
230 event_name = kEventNameMalware;
231 break;
232 case TYPE_HARMFUL:
233 event_name = kEventNameHarmful;
234 break;
235 case TYPE_PHISHING:
236 event_name = kEventNamePhishing;
237 break;
238 default:
239 event_name = kEventNameOther;
240 break;
242 sampling_event_.reset(new ExperienceSamplingEvent(
243 event_name,
244 request_url(),
245 web_contents->GetLastCommittedURL(),
246 web_contents->GetBrowserContext()));
247 #endif
250 bool SafeBrowsingBlockingPage::CanShowMalwareDetailsOption() {
251 return (!web_contents()->GetBrowserContext()->IsOffTheRecord() &&
252 web_contents()->GetURL().SchemeIs(url::kHttpScheme));
255 SafeBrowsingBlockingPage::~SafeBrowsingBlockingPage() {
258 void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
259 std::string command(cmd); // Make a local copy so we can modify it.
260 // The Jasonified response has quotes, remove them.
261 if (command.length() > 1 && command[0] == '"') {
262 command = command.substr(1, command.length() - 2);
264 if (command == kDoReportCommand) {
265 SetReportingPreference(true);
266 return;
269 if (command == kDontReportCommand) {
270 SetReportingPreference(false);
271 return;
274 if (command == kLearnMoreCommand) {
275 // User pressed "Learn more".
276 RecordUserInteraction(SHOW_LEARN_MORE);
277 GURL learn_more_url(interstitial_type_ == TYPE_PHISHING ?
278 kLearnMorePhishingUrlV2 : kLearnMoreMalwareUrlV2);
279 learn_more_url = google_util::AppendGoogleLocaleParam(
280 learn_more_url, g_browser_process->GetApplicationLocale());
281 OpenURLParams params(learn_more_url,
282 Referrer(),
283 CURRENT_TAB,
284 ui::PAGE_TRANSITION_LINK,
285 false);
286 web_contents()->OpenURL(params);
287 return;
290 if (command == kShowPrivacyCommand) {
291 // User pressed "Safe Browsing privacy policy".
292 RecordUserInteraction(SHOW_PRIVACY_POLICY);
293 GURL privacy_url(
294 l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_URL));
295 privacy_url = google_util::AppendGoogleLocaleParam(
296 privacy_url, g_browser_process->GetApplicationLocale());
297 OpenURLParams params(privacy_url,
298 Referrer(),
299 CURRENT_TAB,
300 ui::PAGE_TRANSITION_LINK,
301 false);
302 web_contents()->OpenURL(params);
303 return;
306 bool proceed_blocked = false;
307 if (command == kProceedCommand) {
308 if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) {
309 proceed_blocked = true;
310 } else {
311 RecordUserDecision(PROCEED);
312 interstitial_page()->Proceed();
313 // |this| has been deleted after Proceed() returns.
314 return;
318 if (command == kTakeMeBackCommand || proceed_blocked) {
319 // Don't record the user action here because there are other ways of
320 // triggering DontProceed, like clicking the back button.
321 if (is_main_frame_load_blocked_) {
322 // If the load is blocked, we want to close the interstitial and discard
323 // the pending entry.
324 interstitial_page()->DontProceed();
325 // |this| has been deleted after DontProceed() returns.
326 return;
329 // Otherwise the offending entry has committed, and we need to go back or
330 // to a safe page. We will close the interstitial when that page commits.
331 if (web_contents()->GetController().CanGoBack()) {
332 web_contents()->GetController().GoBack();
333 } else {
334 web_contents()->GetController().LoadURL(
335 GURL(chrome::kChromeUINewTabURL),
336 content::Referrer(),
337 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
338 std::string());
340 return;
343 // The "report error" and "show diagnostic" commands can have a number
344 // appended to them, which is the index of the element they apply to.
345 size_t element_index = 0;
346 size_t colon_index = command.find(':');
347 if (colon_index != std::string::npos) {
348 DCHECK(colon_index < command.size() - 1);
349 int result_int = 0;
350 bool result = base::StringToInt(base::StringPiece(command.begin() +
351 colon_index + 1,
352 command.end()),
353 &result_int);
354 command = command.substr(0, colon_index);
355 if (result)
356 element_index = static_cast<size_t>(result_int);
359 if (element_index >= unsafe_resources_.size()) {
360 NOTREACHED();
361 return;
364 std::string bad_url_spec = unsafe_resources_[element_index].url.spec();
365 if (command == kShowDiagnosticCommand) {
366 // We're going to take the user to Google's SafeBrowsing diagnostic page.
367 RecordUserInteraction(SHOW_DIAGNOSTIC);
368 std::string diagnostic =
369 base::StringPrintf(kSbDiagnosticUrl,
370 net::EscapeQueryParamValue(bad_url_spec, true).c_str());
371 GURL diagnostic_url(diagnostic);
372 diagnostic_url = google_util::AppendGoogleLocaleParam(
373 diagnostic_url, g_browser_process->GetApplicationLocale());
374 DCHECK(unsafe_resources_[element_index].threat_type ==
375 SB_THREAT_TYPE_URL_MALWARE ||
376 unsafe_resources_[element_index].threat_type ==
377 SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL ||
378 unsafe_resources_[element_index].threat_type ==
379 SB_THREAT_TYPE_URL_UNWANTED);
380 OpenURLParams params(
381 diagnostic_url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_LINK,
382 false);
383 web_contents()->OpenURL(params);
384 return;
387 if (command == kExpandedSeeMoreCommand) {
388 RecordUserInteraction(SHOW_ADVANCED);
389 return;
392 NOTREACHED() << "Unexpected command: " << command;
395 void SafeBrowsingBlockingPage::OverrideRendererPrefs(
396 content::RendererPreferences* prefs) {
397 Profile* profile = Profile::FromBrowserContext(
398 web_contents()->GetBrowserContext());
399 renderer_preferences_util::UpdateFromSystemSettings(
400 prefs, profile, web_contents());
403 void SafeBrowsingBlockingPage::SetReportingPreference(bool report) {
404 Profile* profile = Profile::FromBrowserContext(
405 web_contents()->GetBrowserContext());
406 PrefService* pref = profile->GetPrefs();
407 pref->SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, report);
408 UMA_HISTOGRAM_BOOLEAN("SB2.SetExtendedReportingEnabled", report);
411 void SafeBrowsingBlockingPage::OnProceed() {
412 proceeded_ = true;
413 // Send the malware details, if we opted to.
414 FinishMalwareDetails(malware_details_proceed_delay_ms_);
416 NotifySafeBrowsingUIManager(ui_manager_, unsafe_resources_, true);
418 // Check to see if some new notifications of unsafe resources have been
419 // received while we were showing the interstitial.
420 UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
421 UnsafeResourceMap::iterator iter = unsafe_resource_map->find(web_contents());
422 SafeBrowsingBlockingPage* blocking_page = NULL;
423 if (iter != unsafe_resource_map->end() && !iter->second.empty()) {
424 // Build an interstitial for all the unsafe resources notifications.
425 // Don't show it now as showing an interstitial while an interstitial is
426 // already showing would cause DontProceed() to be invoked.
427 blocking_page = factory_->CreateSafeBrowsingPage(ui_manager_,
428 web_contents(),
429 iter->second);
430 unsafe_resource_map->erase(iter);
433 // Now that this interstitial is gone, we can show the new one.
434 if (blocking_page)
435 blocking_page->Show();
438 const void* SafeBrowsingBlockingPage::GetTypeForTesting() const {
439 return SafeBrowsingBlockingPage::kTypeForTesting;
442 bool SafeBrowsingBlockingPage::ShouldCreateNewNavigation() const {
443 return is_main_frame_load_blocked_;
446 void SafeBrowsingBlockingPage::OnDontProceed() {
447 // We could have already called Proceed(), in which case we must not notify
448 // the SafeBrowsingUIManager again, as the client has been deleted.
449 if (proceeded_)
450 return;
452 if (!IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled))
453 RecordUserDecision(DONT_PROCEED);
455 // Send the malware details, if we opted to.
456 FinishMalwareDetails(0); // No delay
458 NotifySafeBrowsingUIManager(ui_manager_, unsafe_resources_, false);
460 // The user does not want to proceed, clear the queued unsafe resources
461 // notifications we received while the interstitial was showing.
462 UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
463 UnsafeResourceMap::iterator iter = unsafe_resource_map->find(web_contents());
464 if (iter != unsafe_resource_map->end() && !iter->second.empty()) {
465 NotifySafeBrowsingUIManager(ui_manager_, iter->second, false);
466 unsafe_resource_map->erase(iter);
469 // We don't remove the navigation entry if the tab is being destroyed as this
470 // would trigger a navigation that would cause trouble as the render view host
471 // for the tab has by then already been destroyed. We also don't delete the
472 // current entry if it has been committed again, which is possible on a page
473 // that had a subresource warning.
474 int last_committed_index =
475 web_contents()->GetController().GetLastCommittedEntryIndex();
476 if (navigation_entry_index_to_remove_ != -1 &&
477 navigation_entry_index_to_remove_ != last_committed_index &&
478 !web_contents()->IsBeingDestroyed()) {
479 CHECK(web_contents()->GetController().RemoveEntryAtIndex(
480 navigation_entry_index_to_remove_));
481 navigation_entry_index_to_remove_ = -1;
485 void SafeBrowsingBlockingPage::OnGotHistoryCount(bool success,
486 int num_visits,
487 base::Time first_visit) {
488 if (success)
489 num_visits_ = num_visits;
492 void SafeBrowsingBlockingPage::RecordUserDecision(Decision decision) {
493 switch (interstitial_type_) {
494 case TYPE_MALWARE:
495 UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision",
496 decision,
497 MAX_DECISION);
498 break;
499 case TYPE_HARMFUL:
500 UMA_HISTOGRAM_ENUMERATION("interstitial.harmful.decision",
501 decision,
502 MAX_DECISION);
503 break;
504 case TYPE_PHISHING:
505 UMA_HISTOGRAM_ENUMERATION("interstitial.phishing.decision",
506 decision,
507 MAX_DECISION);
508 break;
511 #if defined(ENABLE_EXTENSIONS)
512 if (sampling_event_.get()) {
513 switch (decision) {
514 case PROCEED:
515 sampling_event_->CreateUserDecisionEvent(
516 ExperienceSamplingEvent::kProceed);
517 break;
518 case DONT_PROCEED:
519 sampling_event_->CreateUserDecisionEvent(
520 ExperienceSamplingEvent::kDeny);
521 break;
522 case SHOW:
523 case PROCEEDING_DISABLED:
524 case MAX_DECISION:
525 break;
528 #endif
530 // Record additional information about malware sites that users have
531 // visited before.
532 if (num_visits_ < 1 || interstitial_type_ != TYPE_MALWARE)
533 return;
534 if (decision == PROCEED || decision == DONT_PROCEED) {
535 UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision.repeat_visit",
536 SHOW,
537 MAX_DECISION);
538 UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision.repeat_visit",
539 decision,
540 MAX_DECISION);
544 void SafeBrowsingBlockingPage::RecordUserInteraction(Interaction interaction) {
545 switch (interstitial_type_) {
546 case TYPE_MALWARE:
547 UMA_HISTOGRAM_ENUMERATION("interstitial.malware.interaction",
548 interaction,
549 MAX_INTERACTION);
550 break;
551 case TYPE_HARMFUL:
552 UMA_HISTOGRAM_ENUMERATION("interstitial.harmful.interaction",
553 interaction,
554 MAX_INTERACTION);
555 break;
556 case TYPE_PHISHING:
557 UMA_HISTOGRAM_ENUMERATION("interstitial.phishing.interaction",
558 interaction,
559 MAX_INTERACTION);
560 break;
563 #if defined(ENABLE_EXTENSIONS)
564 if (!sampling_event_.get())
565 return;
566 switch (interaction) {
567 case SHOW_LEARN_MORE:
568 sampling_event_->set_has_viewed_learn_more(true);
569 break;
570 case SHOW_ADVANCED:
571 sampling_event_->set_has_viewed_details(true);
572 break;
573 case SHOW_PRIVACY_POLICY:
574 case SHOW_DIAGNOSTIC:
575 case TOTAL_VISITS:
576 case MAX_INTERACTION:
577 break;
579 #endif
582 void SafeBrowsingBlockingPage::FinishMalwareDetails(int64 delay_ms) {
583 if (malware_details_.get() == NULL)
584 return; // Not all interstitials have malware details (eg phishing).
586 const bool enabled =
587 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled);
588 UMA_HISTOGRAM_BOOLEAN("SB2.ExtendedReportingIsEnabled", enabled);
589 if (enabled) {
590 // Finish the malware details collection, send it over.
591 BrowserThread::PostDelayedTask(
592 BrowserThread::IO, FROM_HERE,
593 base::Bind(&MalwareDetails::FinishCollection, malware_details_.get()),
594 base::TimeDelta::FromMilliseconds(delay_ms));
598 bool SafeBrowsingBlockingPage::IsPrefEnabled(const char* pref) {
599 Profile* profile =
600 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
601 return profile->GetPrefs()->GetBoolean(pref);
604 // static
605 void SafeBrowsingBlockingPage::NotifySafeBrowsingUIManager(
606 SafeBrowsingUIManager* ui_manager,
607 const UnsafeResourceList& unsafe_resources,
608 bool proceed) {
609 BrowserThread::PostTask(
610 BrowserThread::IO, FROM_HERE,
611 base::Bind(&SafeBrowsingUIManager::OnBlockingPageDone,
612 ui_manager, unsafe_resources, proceed));
615 // static
616 SafeBrowsingBlockingPage::UnsafeResourceMap*
617 SafeBrowsingBlockingPage::GetUnsafeResourcesMap() {
618 return g_unsafe_resource_map.Pointer();
621 // static
622 SafeBrowsingBlockingPage* SafeBrowsingBlockingPage::CreateBlockingPage(
623 SafeBrowsingUIManager* ui_manager,
624 WebContents* web_contents,
625 const UnsafeResource& unsafe_resource) {
626 std::vector<UnsafeResource> resources;
627 resources.push_back(unsafe_resource);
628 // Set up the factory if this has not been done already (tests do that
629 // before this method is called).
630 if (!factory_)
631 factory_ = g_safe_browsing_blocking_page_factory_impl.Pointer();
632 return factory_->CreateSafeBrowsingPage(ui_manager, web_contents, resources);
635 // static
636 void SafeBrowsingBlockingPage::ShowBlockingPage(
637 SafeBrowsingUIManager* ui_manager,
638 const UnsafeResource& unsafe_resource) {
639 DVLOG(1) << __FUNCTION__ << " " << unsafe_resource.url.spec();
640 WebContents* web_contents = tab_util::GetWebContentsByID(
641 unsafe_resource.render_process_host_id, unsafe_resource.render_view_id);
643 InterstitialPage* interstitial =
644 InterstitialPage::GetInterstitialPage(web_contents);
645 if (interstitial && !unsafe_resource.is_subresource) {
646 // There is already an interstitial showing and we are about to display a
647 // new one for the main frame. Just hide the current one, it is now
648 // irrelevent
649 interstitial->DontProceed();
650 interstitial = NULL;
653 if (!interstitial) {
654 // There are no interstitial currently showing in that tab, go ahead and
655 // show this interstitial.
656 SafeBrowsingBlockingPage* blocking_page =
657 CreateBlockingPage(ui_manager, web_contents, unsafe_resource);
658 blocking_page->Show();
659 return;
662 // This is an interstitial for a page's resource, let's queue it.
663 UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
664 (*unsafe_resource_map)[web_contents].push_back(unsafe_resource);
667 // static
668 bool SafeBrowsingBlockingPage::IsMainPageLoadBlocked(
669 const UnsafeResourceList& unsafe_resources) {
670 // Client-side phishing detection interstitials never block the main frame
671 // load, since they happen after the page is finished loading.
672 if (unsafe_resources[0].threat_type ==
673 SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL) {
674 return false;
677 // Otherwise, check the threat type.
678 return unsafe_resources.size() == 1 && !unsafe_resources[0].is_subresource;
681 void SafeBrowsingBlockingPage::PopulateInterstitialStrings(
682 base::DictionaryValue* load_time_data) {
683 CHECK(load_time_data);
684 CHECK(!unsafe_resources_.empty());
686 load_time_data->SetString("type", "SAFEBROWSING");
687 load_time_data->SetString(
688 "tabTitle", l10n_util::GetStringUTF16(IDS_SAFEBROWSING_V3_TITLE));
689 load_time_data->SetString(
690 "openDetails",
691 l10n_util::GetStringUTF16(IDS_SAFEBROWSING_V3_OPEN_DETAILS_BUTTON));
692 load_time_data->SetString(
693 "closeDetails",
694 l10n_util::GetStringUTF16(IDS_SAFEBROWSING_V3_CLOSE_DETAILS_BUTTON));
695 load_time_data->SetString(
696 "primaryButtonText",
697 l10n_util::GetStringUTF16(IDS_SAFEBROWSING_OVERRIDABLE_SAFETY_BUTTON));
698 load_time_data->SetBoolean(
699 "overridable",
700 !IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled));
702 switch (interstitial_type_) {
703 case TYPE_MALWARE:
704 PopulateMalwareLoadTimeData(load_time_data);
705 break;
706 case TYPE_HARMFUL:
707 PopulateHarmfulLoadTimeData(load_time_data);
708 break;
709 case TYPE_PHISHING:
710 PopulatePhishingLoadTimeData(load_time_data);
711 break;
715 void SafeBrowsingBlockingPage::PopulateMalwareLoadTimeData(
716 base::DictionaryValue* load_time_data) {
717 load_time_data->SetBoolean("phishing", false);
718 load_time_data->SetString(
719 "heading", l10n_util::GetStringUTF16(IDS_MALWARE_V3_HEADING));
720 load_time_data->SetString(
721 "primaryParagraph",
722 l10n_util::GetStringFUTF16(
723 IDS_MALWARE_V3_PRIMARY_PARAGRAPH,
724 GetFormattedHostName()));
725 load_time_data->SetString(
726 "explanationParagraph",
727 is_main_frame_load_blocked_ ?
728 l10n_util::GetStringFUTF16(
729 IDS_MALWARE_V3_EXPLANATION_PARAGRAPH,
730 GetFormattedHostName()) :
731 l10n_util::GetStringFUTF16(
732 IDS_MALWARE_V3_EXPLANATION_PARAGRAPH_SUBRESOURCE,
733 base::UTF8ToUTF16(web_contents()->GetURL().host()),
734 GetFormattedHostName()));
735 load_time_data->SetString(
736 "finalParagraph",
737 l10n_util::GetStringUTF16(IDS_MALWARE_V3_PROCEED_PARAGRAPH));
739 load_time_data->SetBoolean(kDisplayCheckBox, CanShowMalwareDetailsOption());
740 if (CanShowMalwareDetailsOption()) {
741 std::string privacy_link = base::StringPrintf(
742 kPrivacyLinkHtml,
743 l10n_util::GetStringUTF8(
744 IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
745 load_time_data->SetString(
746 "optInLink",
747 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
748 base::UTF8ToUTF16(privacy_link)));
749 load_time_data->SetBoolean(
750 kBoxChecked,
751 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled));
755 void SafeBrowsingBlockingPage::PopulateHarmfulLoadTimeData(
756 base::DictionaryValue* load_time_data) {
757 load_time_data->SetBoolean("phishing", false);
758 load_time_data->SetString(
759 "heading", l10n_util::GetStringUTF16(IDS_HARMFUL_V3_HEADING));
760 load_time_data->SetString(
761 "primaryParagraph",
762 l10n_util::GetStringFUTF16(
763 IDS_HARMFUL_V3_PRIMARY_PARAGRAPH,
764 GetFormattedHostName()));
765 load_time_data->SetString(
766 "explanationParagraph",
767 l10n_util::GetStringFUTF16(
768 IDS_HARMFUL_V3_EXPLANATION_PARAGRAPH,
769 GetFormattedHostName()));
770 load_time_data->SetString(
771 "finalParagraph",
772 l10n_util::GetStringUTF16(IDS_HARMFUL_V3_PROCEED_PARAGRAPH));
774 load_time_data->SetBoolean(kDisplayCheckBox, CanShowMalwareDetailsOption());
775 if (CanShowMalwareDetailsOption()) {
776 std::string privacy_link = base::StringPrintf(
777 kPrivacyLinkHtml,
778 l10n_util::GetStringUTF8(
779 IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
780 load_time_data->SetString(
781 "optInLink",
782 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
783 base::UTF8ToUTF16(privacy_link)));
784 load_time_data->SetBoolean(
785 kBoxChecked,
786 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled));
790 void SafeBrowsingBlockingPage::PopulatePhishingLoadTimeData(
791 base::DictionaryValue* load_time_data) {
792 load_time_data->SetBoolean("phishing", true);
793 load_time_data->SetString(
794 "heading",
795 l10n_util::GetStringUTF16(IDS_PHISHING_V3_HEADING));
796 load_time_data->SetString(
797 "primaryParagraph",
798 l10n_util::GetStringFUTF16(
799 IDS_PHISHING_V3_PRIMARY_PARAGRAPH,
800 GetFormattedHostName()));
801 load_time_data->SetString(
802 "explanationParagraph",
803 l10n_util::GetStringFUTF16(IDS_PHISHING_V3_EXPLANATION_PARAGRAPH,
804 GetFormattedHostName()));
805 load_time_data->SetString(
806 "finalParagraph",
807 l10n_util::GetStringUTF16(IDS_PHISHING_V3_PROCEED_PARAGRAPH));