safe_browsing_blocking_page.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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.
6
7#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
8
9#include <string>
10
11#include "base/bind.h"
12#include "base/i18n/rtl.h"
13#include "base/lazy_instance.h"
14#include "base/metrics/field_trial.h"
15#include "base/metrics/histogram.h"
16#include "base/prefs/pref_service.h"
17#include "base/stringprintf.h"
18#include "base/strings/string_number_conversions.h"
19#include "base/strings/string_piece.h"
20#include "base/time.h"
21#include "base/utf_string_conversions.h"
22#include "base/values.h"
23#include "chrome/browser/browser_process.h"
24#include "chrome/browser/google/google_util.h"
25#include "chrome/browser/profiles/profile.h"
26#include "chrome/browser/renderer_preferences_util.h"
27#include "chrome/browser/safe_browsing/malware_details.h"
28#include "chrome/browser/safe_browsing/ui_manager.h"
29#include "chrome/browser/tab_contents/tab_util.h"
30#include "chrome/common/pref_names.h"
31#include "chrome/common/url_constants.h"
32#include "content/public/browser/browser_thread.h"
33#include "content/public/browser/interstitial_page.h"
34#include "content/public/browser/navigation_controller.h"
35#include "content/public/browser/user_metrics.h"
36#include "content/public/browser/web_contents.h"
37#include "grit/browser_resources.h"
38#include "grit/chromium_strings.h"
39#include "grit/generated_resources.h"
40#include "grit/locale_settings.h"
41#include "net/base/escape.h"
42#include "ui/base/l10n/l10n_util.h"
43#include "ui/base/resource/resource_bundle.h"
44#include "ui/webui/jstemplate_builder.h"
45#include "ui/webui/web_ui_util.h"
46
47using content::BrowserThread;
48using content::InterstitialPage;
49using content::OpenURLParams;
50using content::Referrer;
51using content::UserMetricsAction;
52using content::WebContents;
53
54namespace {
55
56// For malware interstitial pages, we link the problematic URL to Google's
57// diagnostic page.
58#if defined(GOOGLE_CHROME_BUILD)
59const char* const kSbDiagnosticUrl =
60    "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=googlechrome";
61#else
62const char* const kSbDiagnosticUrl =
63    "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=chromium";
64#endif
65
66const char* const kSbReportPhishingErrorUrl =
67    "http://www.google.com/safebrowsing/report_error/";
68
69// URL for the "Learn more" link on the multi threat malware blocking page.
70const char* const kLearnMoreMalwareUrl =
71    "https://www.google.com/support/bin/answer.py?answer=45449&topic=360"
72    "&sa=X&oi=malwarewarninglink&resnum=1&ct=help";
73const char* const kLearnMoreMalwareUrlV2 =
74    "https://www.google.com/goodtoknow/online-safety/malware/";
75const char* const kLearnMorePhishingUrlV2 =
76    "https://www.google.com/goodtoknow/online-safety/phishing/";
77
78// URL for the "Learn more" link on the phishing blocking page.
79const char* const kLearnMorePhishingUrl =
80    "https://www.google.com/support/bin/answer.py?answer=106318";
81
82const char* const kSbDiagnosticHtml =
83    "<a href=\"\" onclick=\"sendCommand('showDiagnostic'); return false;\" "
84    "onmousedown=\"return false;\">%s</a>";
85
86const char* const kPLinkHtml =
87    "<a href=\"\" onclick=\"sendCommand('proceed'); return false;\" "
88    "onmousedown=\"return false;\">%s</a>";
89
90const char* const kPrivacyLinkHtml =
91    "<a id=\"privacy-link\" href=\"\" onclick=\"sendCommand('showPrivacy'); "
92    "return false;\" onmousedown=\"return false;\">%s</a>";
93
94// After a malware interstitial where the user opted-in to the report
95// but clicked "proceed anyway", we delay the call to
96// MalwareDetails::FinishCollection() by this much time (in
97// milliseconds).
98const int64 kMalwareDetailsProceedDelayMilliSeconds = 3000;
99
100// The commands returned by the page when the user performs an action.
101const char* const kShowDiagnosticCommand = "showDiagnostic";
102const char* const kReportErrorCommand = "reportError";
103const char* const kLearnMoreCommand = "learnMore";
104const char* const kLearnMoreCommandV2 = "learnMore2";
105const char* const kShowPrivacyCommand = "showPrivacy";
106const char* const kProceedCommand = "proceed";
107const char* const kTakeMeBackCommand = "takeMeBack";
108const char* const kDoReportCommand = "doReport";
109const char* const kDontReportCommand = "dontReport";
110const char* const kDisplayCheckBox = "displaycheckbox";
111const char* const kBoxChecked = "boxchecked";
112const char* const kExpandedSeeMore = "expandedSeeMore";
113// Special command that we use when the user navigated away from the
114// page.  E.g., closed the tab or the window.  This is only used by
115// RecordUserReactionTime.
116const char* const kNavigatedAwayMetaCommand = "closed";
117
118base::LazyInstance<SafeBrowsingBlockingPage::UnsafeResourceMap>
119    g_unsafe_resource_map = LAZY_INSTANCE_INITIALIZER;
120
121// These are the conditions for the summer 2013 Finch experiment.
122const char* const kMalwareStudyName = "InterstitialMalware310";
123const char* const kPhishingStudyName = "InterstitialPhishing564";
124const char* const kCond1MalwareControl = "cond1MalwareControl";
125const char* const kCond2MalwareNoBrand = "cond2MalwareNoBrand";
126const char* const kCond3PhishingControl = "cond3PhishingControl";
127const char* const kCond4PhishingNoBrand = "cond4PhishingNoBrand";
128const char* const kCond5MalwareOneStep = "cond5MalwareOneStep";
129const char* const kCond6PhishingOneStep = "cond6PhishingOneStep";
130const char* const kCond7MalwareFearMsg = "cond7MalwareFearMsg";
131const char* const kCond8PhishingFearMsg = "cond8PhishingFearMsg";
132const char* const kCond9MalwareCollabMsg = "cond9MalwareCollabMsg";
133const char* const kCond10PhishingCollabMsg = "cond10PhishingCollabMsg";
134const char* const kCond11MalwareQuestion = "cond11MalwareQuestion";
135const char* const kCond12PhishingQuestion = "cond12PhishingQuestion";
136const char* const kCond13MalwareGoBack = "cond13MalwareGoBack";
137const char* const kCond14PhishingGoBack = "cond14PhishingGoBack";
138
139}  // namespace
140
141// static
142SafeBrowsingBlockingPageFactory* SafeBrowsingBlockingPage::factory_ = NULL;
143
144// The default SafeBrowsingBlockingPageFactory.  Global, made a singleton so we
145// don't leak it.
146class SafeBrowsingBlockingPageFactoryImpl
147    : public SafeBrowsingBlockingPageFactory {
148 public:
149  virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
150      SafeBrowsingUIManager* ui_manager,
151      WebContents* web_contents,
152      const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
153      OVERRIDE {
154    // Only use the V2 page if the interstitial is for a single malware or
155    // phishing resource, the multi-threat interstitial has not been updated to
156    // V2 yet.
157    if (unsafe_resources.size() == 1 &&
158        (unsafe_resources[0].threat_type == SB_THREAT_TYPE_URL_MALWARE ||
159         unsafe_resources[0].threat_type == SB_THREAT_TYPE_URL_PHISHING)) {
160      return new SafeBrowsingBlockingPageV2(ui_manager, web_contents,
161          unsafe_resources);
162    }
163    return new SafeBrowsingBlockingPageV1(ui_manager, web_contents,
164                                          unsafe_resources);
165  }
166
167 private:
168  friend struct base::DefaultLazyInstanceTraits<
169      SafeBrowsingBlockingPageFactoryImpl>;
170
171  SafeBrowsingBlockingPageFactoryImpl() { }
172
173  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageFactoryImpl);
174};
175
176static base::LazyInstance<SafeBrowsingBlockingPageFactoryImpl>
177    g_safe_browsing_blocking_page_factory_impl = LAZY_INSTANCE_INITIALIZER;
178
179SafeBrowsingBlockingPage::SafeBrowsingBlockingPage(
180    SafeBrowsingUIManager* ui_manager,
181    WebContents* web_contents,
182    const UnsafeResourceList& unsafe_resources)
183    : malware_details_proceed_delay_ms_(
184          kMalwareDetailsProceedDelayMilliSeconds),
185      ui_manager_(ui_manager),
186      report_loop_(NULL),
187      is_main_frame_load_blocked_(IsMainPageLoadBlocked(unsafe_resources)),
188      unsafe_resources_(unsafe_resources),
189      proceeded_(false),
190      web_contents_(web_contents),
191      url_(unsafe_resources[0].url),
192      has_expanded_see_more_section_(false) {
193  bool malware = false;
194  bool phishing = false;
195  for (UnsafeResourceList::const_iterator iter = unsafe_resources_.begin();
196       iter != unsafe_resources_.end(); ++iter) {
197    const UnsafeResource& resource = *iter;
198    SBThreatType threat_type = resource.threat_type;
199    if (threat_type == SB_THREAT_TYPE_URL_MALWARE) {
200      malware = true;
201    } else {
202      DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
203             threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
204      phishing = true;
205    }
206  }
207  DCHECK(phishing || malware);
208  if (malware && phishing)
209    interstitial_type_ = TYPE_MALWARE_AND_PHISHING;
210  else if (malware)
211    interstitial_type_ = TYPE_MALWARE;
212  else
213    interstitial_type_ = TYPE_PHISHING;
214  RecordUserAction(SHOW);
215  if (!is_main_frame_load_blocked_) {
216    navigation_entry_index_to_remove_ =
217        web_contents->GetController().GetLastCommittedEntryIndex();
218  } else {
219    navigation_entry_index_to_remove_ = -1;
220  }
221
222  // Start computing malware details. They will be sent only
223  // if the user opts-in on the blocking page later.
224  // If there's more than one malicious resources, it means the user
225  // clicked through the first warning, so we don't prepare additional
226  // reports.
227  if (unsafe_resources.size() == 1 &&
228      unsafe_resources[0].threat_type == SB_THREAT_TYPE_URL_MALWARE &&
229      malware_details_ == NULL &&
230      CanShowMalwareDetailsOption()) {
231    malware_details_ = MalwareDetails::NewMalwareDetails(
232        ui_manager_, web_contents, unsafe_resources[0]);
233  }
234
235  interstitial_page_ = InterstitialPage::Create(
236      web_contents, IsMainPageLoadBlocked(unsafe_resources), url_, this);
237}
238
239bool SafeBrowsingBlockingPage::CanShowMalwareDetailsOption() {
240  return (!web_contents_->GetBrowserContext()->IsOffTheRecord() &&
241          web_contents_->GetURL().SchemeIs(chrome::kHttpScheme));
242}
243
244SafeBrowsingBlockingPage::~SafeBrowsingBlockingPage() {
245}
246
247void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
248  std::string command(cmd);  // Make a local copy so we can modify it.
249  // The Jasonified response has quotes, remove them.
250  if (command.length() > 1 && command[0] == '"') {
251    command = command.substr(1, command.length() - 2);
252  }
253  RecordUserReactionTime(command);
254  if (command == kDoReportCommand) {
255    SetReportingPreference(true);
256    return;
257  }
258
259  if (command == kDontReportCommand) {
260    SetReportingPreference(false);
261    return;
262  }
263
264  if (command == kLearnMoreCommand) {
265    // User pressed "Learn more".
266    GURL url;
267    SBThreatType threat_type = unsafe_resources_[0].threat_type;
268    if (threat_type == SB_THREAT_TYPE_URL_MALWARE) {
269      url = google_util::AppendGoogleLocaleParam(GURL(kLearnMoreMalwareUrl));
270    } else if (threat_type == SB_THREAT_TYPE_URL_PHISHING ||
271               threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL) {
272      url = google_util::AppendGoogleLocaleParam(GURL(kLearnMorePhishingUrl));
273    } else {
274      NOTREACHED();
275    }
276
277    OpenURLParams params(
278        url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
279    web_contents_->OpenURL(params);
280    return;
281  }
282
283  if (command == kLearnMoreCommandV2) {
284    // User pressed "Learn more".
285    GURL url;
286    SBThreatType threat_type = unsafe_resources_[0].threat_type;
287    if (threat_type == SB_THREAT_TYPE_URL_MALWARE) {
288      url = google_util::AppendGoogleLocaleParam(GURL(kLearnMoreMalwareUrlV2));
289    } else if (threat_type == SB_THREAT_TYPE_URL_PHISHING ||
290               threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL) {
291      url = google_util::AppendGoogleLocaleParam(GURL(kLearnMorePhishingUrlV2));
292    } else {
293      NOTREACHED();
294    }
295
296    OpenURLParams params(
297        url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
298    web_contents_->OpenURL(params);
299    return;
300  }
301
302  if (command == kShowPrivacyCommand) {
303    // User pressed "Safe Browsing privacy policy".
304    GURL url(l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_URL));
305    OpenURLParams params(
306        url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
307    web_contents_->OpenURL(params);
308    return;
309  }
310
311  bool proceed_blocked = false;
312  if (command == kProceedCommand) {
313    if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) {
314      proceed_blocked = true;
315    } else {
316      interstitial_page_->Proceed();
317      // |this| has been deleted after Proceed() returns.
318      return;
319    }
320  }
321
322  if (command == kTakeMeBackCommand || proceed_blocked) {
323    if (is_main_frame_load_blocked_) {
324      // If the load is blocked, we want to close the interstitial and discard
325      // the pending entry.
326      interstitial_page_->DontProceed();
327      // |this| has been deleted after DontProceed() returns.
328      return;
329    }
330
331    // Otherwise the offending entry has committed, and we need to go back or
332    // to a safe page.  We will close the interstitial when that page commits.
333    if (web_contents_->GetController().CanGoBack()) {
334      web_contents_->GetController().GoBack();
335    } else {
336      web_contents_->GetController().LoadURL(
337          GURL(chrome::kChromeUINewTabURL),
338          content::Referrer(),
339          content::PAGE_TRANSITION_AUTO_TOPLEVEL,
340          std::string());
341    }
342    return;
343  }
344
345  // The "report error" and "show diagnostic" commands can have a number
346  // appended to them, which is the index of the element they apply to.
347  size_t element_index = 0;
348  size_t colon_index = command.find(':');
349  if (colon_index != std::string::npos) {
350    DCHECK(colon_index < command.size() - 1);
351    int result_int = 0;
352    bool result = base::StringToInt(base::StringPiece(command.begin() +
353                                                      colon_index + 1,
354                                                      command.end()),
355                                    &result_int);
356    command = command.substr(0, colon_index);
357    if (result)
358      element_index = static_cast<size_t>(result_int);
359  }
360
361  if (element_index >= unsafe_resources_.size()) {
362    NOTREACHED();
363    return;
364  }
365
366  std::string bad_url_spec = unsafe_resources_[element_index].url.spec();
367  if (command == kReportErrorCommand) {
368    // User pressed "Report error" for a phishing site.
369    // Note that we cannot just put a link in the interstitial at this point.
370    // It is not OK to navigate in the context of an interstitial page.
371    SBThreatType threat_type = unsafe_resources_[element_index].threat_type;
372    DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
373           threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
374    GURL report_url =
375        safe_browsing_util::GeneratePhishingReportUrl(
376            kSbReportPhishingErrorUrl,
377            bad_url_spec,
378            threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
379    OpenURLParams params(
380        report_url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK,
381        false);
382    web_contents_->OpenURL(params);
383    return;
384  }
385
386  if (command == kShowDiagnosticCommand) {
387    // We're going to take the user to Google's SafeBrowsing diagnostic page.
388    std::string diagnostic =
389        base::StringPrintf(kSbDiagnosticUrl,
390            net::EscapeQueryParamValue(bad_url_spec, true).c_str());
391    GURL diagnostic_url(diagnostic);
392    diagnostic_url = google_util::AppendGoogleLocaleParam(diagnostic_url);
393    DCHECK(unsafe_resources_[element_index].threat_type ==
394           SB_THREAT_TYPE_URL_MALWARE);
395    OpenURLParams params(
396        diagnostic_url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK,
397        false);
398    web_contents_->OpenURL(params);
399    return;
400  }
401
402  if (command == kExpandedSeeMore) {
403    // User expanded the "see more info" section of the page.  We don't actually
404    // do any action based on this, it's just so that RecordUserReactionTime can
405    // track it.
406    return;
407  }
408
409  NOTREACHED() << "Unexpected command: " << command;
410}
411
412void SafeBrowsingBlockingPage::OverrideRendererPrefs(
413      content::RendererPreferences* prefs) {
414  Profile* profile = Profile::FromBrowserContext(
415      web_contents_->GetBrowserContext());
416  renderer_preferences_util::UpdateFromSystemSettings(prefs, profile);
417 }
418
419void SafeBrowsingBlockingPage::SetReportingPreference(bool report) {
420  Profile* profile = Profile::FromBrowserContext(
421      web_contents_->GetBrowserContext());
422  PrefService* pref = profile->GetPrefs();
423  pref->SetBoolean(prefs::kSafeBrowsingReportingEnabled, report);
424}
425
426void SafeBrowsingBlockingPage::OnProceed() {
427  proceeded_ = true;
428  RecordUserAction(PROCEED);
429  // Send the malware details, if we opted to.
430  FinishMalwareDetails(malware_details_proceed_delay_ms_);
431
432  NotifySafeBrowsingUIManager(ui_manager_, unsafe_resources_, true);
433
434  // Check to see if some new notifications of unsafe resources have been
435  // received while we were showing the interstitial.
436  UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
437  UnsafeResourceMap::iterator iter = unsafe_resource_map->find(web_contents_);
438  SafeBrowsingBlockingPage* blocking_page = NULL;
439  if (iter != unsafe_resource_map->end() && !iter->second.empty()) {
440    // Build an interstitial for all the unsafe resources notifications.
441    // Don't show it now as showing an interstitial while an interstitial is
442    // already showing would cause DontProceed() to be invoked.
443    blocking_page = factory_->CreateSafeBrowsingPage(ui_manager_, web_contents_,
444                                                     iter->second);
445    unsafe_resource_map->erase(iter);
446  }
447
448  // Now that this interstitial is gone, we can show the new one.
449  if (blocking_page)
450    blocking_page->interstitial_page_->Show();
451}
452
453void SafeBrowsingBlockingPage::OnDontProceed() {
454  // Calling this method twice will not double-count.
455  RecordUserReactionTime(kNavigatedAwayMetaCommand);
456  // We could have already called Proceed(), in which case we must not notify
457  // the SafeBrowsingUIManager again, as the client has been deleted.
458  if (proceeded_)
459    return;
460
461  RecordUserAction(DONT_PROCEED);
462  // Send the malware details, if we opted to.
463  FinishMalwareDetails(0);  // No delay
464
465  NotifySafeBrowsingUIManager(ui_manager_, unsafe_resources_, false);
466
467  // The user does not want to proceed, clear the queued unsafe resources
468  // notifications we received while the interstitial was showing.
469  UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
470  UnsafeResourceMap::iterator iter = unsafe_resource_map->find(web_contents_);
471  if (iter != unsafe_resource_map->end() && !iter->second.empty()) {
472    NotifySafeBrowsingUIManager(ui_manager_, iter->second, false);
473    unsafe_resource_map->erase(iter);
474  }
475
476  // We don't remove the navigation entry if the tab is being destroyed as this
477  // would trigger a navigation that would cause trouble as the render view host
478  // for the tab has by then already been destroyed.  We also don't delete the
479  // current entry if it has been committed again, which is possible on a page
480  // that had a subresource warning.
481  int last_committed_index =
482      web_contents_->GetController().GetLastCommittedEntryIndex();
483  if (navigation_entry_index_to_remove_ != -1 &&
484      navigation_entry_index_to_remove_ != last_committed_index &&
485      !web_contents_->IsBeingDestroyed()) {
486    web_contents_->GetController().RemoveEntryAtIndex(
487        navigation_entry_index_to_remove_);
488    navigation_entry_index_to_remove_ = -1;
489  }
490}
491
492void SafeBrowsingBlockingPage::RecordUserAction(BlockingPageEvent event) {
493  // This enum is used for a histogram.  Don't reorder, delete, or insert
494  // elements.  New elements should be added before MAX_ACTION only.
495  enum {
496    MALWARE_SHOW = 0,
497    MALWARE_DONT_PROCEED,
498    MALWARE_FORCED_DONT_PROCEED,
499    MALWARE_PROCEED,
500    MULTIPLE_SHOW,
501    MULTIPLE_DONT_PROCEED,
502    MULTIPLE_FORCED_DONT_PROCEED,
503    MULTIPLE_PROCEED,
504    PHISHING_SHOW,
505    PHISHING_DONT_PROCEED,
506    PHISHING_FORCED_DONT_PROCEED,
507    PHISHING_PROCEED,
508    MALWARE_SHOW_ADVANCED,
509    MULTIPLE_SHOW_ADVANCED,
510    PHISHING_SHOW_ADVANCED,
511    MAX_ACTION
512  } histogram_action = MAX_ACTION;
513
514  switch (event) {
515    case SHOW:
516      switch (interstitial_type_) {
517        case TYPE_MALWARE_AND_PHISHING:
518          histogram_action = MULTIPLE_SHOW;
519          break;
520        case TYPE_MALWARE:
521          histogram_action = MALWARE_SHOW;
522          break;
523        case TYPE_PHISHING:
524          histogram_action = PHISHING_SHOW;
525          break;
526      }
527      break;
528    case PROCEED:
529      switch (interstitial_type_) {
530        case TYPE_MALWARE_AND_PHISHING:
531          histogram_action = MULTIPLE_PROCEED;
532          break;
533        case TYPE_MALWARE:
534          histogram_action = MALWARE_PROCEED;
535          break;
536        case TYPE_PHISHING:
537          histogram_action = PHISHING_PROCEED;
538          break;
539      }
540      break;
541    case DONT_PROCEED:
542      if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) {
543        switch (interstitial_type_) {
544          case TYPE_MALWARE_AND_PHISHING:
545            histogram_action = MULTIPLE_FORCED_DONT_PROCEED;
546            break;
547          case TYPE_MALWARE:
548            histogram_action = MALWARE_FORCED_DONT_PROCEED;
549            break;
550          case TYPE_PHISHING:
551            histogram_action = PHISHING_FORCED_DONT_PROCEED;
552            break;
553        }
554      } else {
555        switch (interstitial_type_) {
556          case TYPE_MALWARE_AND_PHISHING:
557            histogram_action = MULTIPLE_DONT_PROCEED;
558            break;
559          case TYPE_MALWARE:
560            histogram_action = MALWARE_DONT_PROCEED;
561            break;
562          case TYPE_PHISHING:
563            histogram_action = PHISHING_DONT_PROCEED;
564            break;
565        }
566      }
567      break;
568    case SHOW_ADVANCED:
569      switch (interstitial_type_) {
570        case TYPE_MALWARE_AND_PHISHING:
571          histogram_action = MULTIPLE_SHOW_ADVANCED;
572          break;
573        case TYPE_MALWARE:
574          histogram_action = MALWARE_SHOW_ADVANCED;
575          break;
576        case TYPE_PHISHING:
577          histogram_action = PHISHING_SHOW_ADVANCED;
578          break;
579      }
580      break;
581    default:
582      NOTREACHED() << "Unexpected event: " << event;
583  }
584  if (histogram_action == MAX_ACTION) {
585    NOTREACHED();
586  } else {
587    UMA_HISTOGRAM_ENUMERATION("SB2.InterstitialAction", histogram_action,
588                              MAX_ACTION);
589  }
590
591  // TODO(mattm): now that we've added the histogram above, should we remove
592  // this old user metric at some future point?
593  std::string action = "SBInterstitial";
594  switch (interstitial_type_) {
595    case TYPE_MALWARE_AND_PHISHING:
596      action.append("Multiple");
597      break;
598    case TYPE_MALWARE:
599      action.append("Malware");
600      break;
601    case TYPE_PHISHING:
602      action.append("Phishing");
603      break;
604  }
605
606  switch (event) {
607    case SHOW:
608      action.append("Show");
609      break;
610    case PROCEED:
611      action.append("Proceed");
612      break;
613    case DONT_PROCEED:
614      if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled))
615        action.append("ForcedDontProceed");
616      else
617        action.append("DontProceed");
618      break;
619    case SHOW_ADVANCED:
620      break;
621    default:
622      NOTREACHED() << "Unexpected event: " << event;
623  }
624
625  content::RecordComputedAction(action);
626}
627
628void SafeBrowsingBlockingPage::RecordUserReactionTime(
629    const std::string& command) {
630  if (interstitial_show_time_.is_null())
631    return;  // We already reported the user reaction time.
632  base::TimeDelta dt = base::TimeTicks::Now() - interstitial_show_time_;
633  DVLOG(1) << "User reaction time for command:" << command
634           << " on interstitial_type_:" << interstitial_type_
635           << " warning took " << dt.InMilliseconds() << "ms";
636  bool recorded = true;
637  if (interstitial_type_ == TYPE_MALWARE ||
638      interstitial_type_ == TYPE_MALWARE_AND_PHISHING) {
639    // There are six ways in which the malware interstitial can go
640    // away.  We handle all of them here but we group two together: closing the
641    // tag / browser window and clicking on the back button in the browser (not
642    // the big green button) are considered the same action.
643    if (command == kProceedCommand) {
644      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimeProceed", dt);
645    } else if (command == kTakeMeBackCommand) {
646      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimeTakeMeBack", dt);
647    } else if (command == kShowDiagnosticCommand) {
648      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimeDiagnostic", dt);
649    } else if (command == kShowPrivacyCommand) {
650      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimePrivacyPolicy",
651                                 dt);
652    } else if (command == kLearnMoreCommand || command == kLearnMoreCommandV2) {
653      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialLearnMore",
654                                 dt);
655    } else if (command == kNavigatedAwayMetaCommand) {
656      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimeClosed", dt);
657    } else if (command == kExpandedSeeMore) {
658      // Only record the expanded histogram once per display of the
659      // interstitial.
660      if (has_expanded_see_more_section_)
661        return;
662      RecordUserAction(SHOW_ADVANCED);
663      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.MalwareInterstitialTimeExpandedSeeMore",
664                                 dt);
665      has_expanded_see_more_section_ = true;
666      // Expanding the "See More" section doesn't finish the interstitial, so
667      // don't mark the reaction time as recorded.
668      recorded = false;
669    } else {
670      recorded = false;
671    }
672  } else {
673    // Same as above but for phishing warnings.
674    if (command == kProceedCommand) {
675      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeProceed", dt);
676    } else if (command == kTakeMeBackCommand) {
677      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeTakeMeBack", dt);
678    } else if (command == kShowDiagnosticCommand) {
679      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeReportError", dt);
680    } else if (command == kLearnMoreCommand || command == kLearnMoreCommandV2) {
681      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeLearnMore", dt);
682    } else if (command == kNavigatedAwayMetaCommand) {
683      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeClosed", dt);
684    } else if (command == kExpandedSeeMore) {
685      // Only record the expanded histogram once per display of the
686      // interstitial.
687      if (has_expanded_see_more_section_)
688        return;
689      RecordUserAction(SHOW_ADVANCED);
690      UMA_HISTOGRAM_MEDIUM_TIMES("SB2.PhishingInterstitialTimeExpandedSeeMore",
691                                 dt);
692      has_expanded_see_more_section_ = true;
693      // Expanding the "See More" section doesn't finish the interstitial, so
694      // don't mark the reaction time as recorded.
695      recorded = false;
696    } else {
697      recorded = false;
698    }
699  }
700  if (recorded)  // Making sure we don't double-count reaction times.
701    interstitial_show_time_ = base::TimeTicks();  //  Resets the show time.
702}
703
704void SafeBrowsingBlockingPage::FinishMalwareDetails(int64 delay_ms) {
705  if (malware_details_ == NULL)
706    return;  // Not all interstitials have malware details (eg phishing).
707
708  if (IsPrefEnabled(prefs::kSafeBrowsingReportingEnabled)) {
709    // Finish the malware details collection, send it over.
710    BrowserThread::PostDelayedTask(
711        BrowserThread::IO, FROM_HERE,
712        base::Bind(&MalwareDetails::FinishCollection, malware_details_.get()),
713        base::TimeDelta::FromMilliseconds(delay_ms));
714  }
715}
716
717bool SafeBrowsingBlockingPage::IsPrefEnabled(const char* pref) {
718  Profile* profile =
719      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
720  return profile->GetPrefs()->GetBoolean(pref);
721}
722
723// static
724void SafeBrowsingBlockingPage::NotifySafeBrowsingUIManager(
725    SafeBrowsingUIManager* ui_manager,
726    const UnsafeResourceList& unsafe_resources,
727    bool proceed) {
728  BrowserThread::PostTask(
729      BrowserThread::IO, FROM_HERE,
730      base::Bind(&SafeBrowsingUIManager::OnBlockingPageDone,
731                 ui_manager, unsafe_resources, proceed));
732}
733
734// static
735SafeBrowsingBlockingPage::UnsafeResourceMap*
736    SafeBrowsingBlockingPage::GetUnsafeResourcesMap() {
737  return g_unsafe_resource_map.Pointer();
738}
739
740// static
741void SafeBrowsingBlockingPage::ShowBlockingPage(
742    SafeBrowsingUIManager* ui_manager,
743    const UnsafeResource& unsafe_resource) {
744  DVLOG(1) << __FUNCTION__ << " " << unsafe_resource.url.spec();
745  WebContents* web_contents = tab_util::GetWebContentsByID(
746      unsafe_resource.render_process_host_id, unsafe_resource.render_view_id);
747
748  InterstitialPage* interstitial =
749      InterstitialPage::GetInterstitialPage(web_contents);
750  if (interstitial && !unsafe_resource.is_subresource) {
751    // There is already an interstitial showing and we are about to display a
752    // new one for the main frame. Just hide the current one, it is now
753    // irrelevent
754    interstitial->DontProceed();
755    interstitial = NULL;
756  }
757
758  if (!interstitial) {
759    // There are no interstitial currently showing in that tab, go ahead and
760    // show this interstitial.
761    std::vector<UnsafeResource> resources;
762    resources.push_back(unsafe_resource);
763    // Set up the factory if this has not been done already (tests do that
764    // before this method is called).
765    if (!factory_)
766      factory_ = g_safe_browsing_blocking_page_factory_impl.Pointer();
767    SafeBrowsingBlockingPage* blocking_page =
768        factory_->CreateSafeBrowsingPage(ui_manager, web_contents, resources);
769    blocking_page->interstitial_page_->Show();
770    return;
771  }
772
773  // This is an interstitial for a page's resource, let's queue it.
774  UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
775  (*unsafe_resource_map)[web_contents].push_back(unsafe_resource);
776}
777
778// static
779bool SafeBrowsingBlockingPage::IsMainPageLoadBlocked(
780    const UnsafeResourceList& unsafe_resources) {
781  // Client-side phishing detection interstitials never block the main frame
782  // load, since they happen after the page is finished loading.
783  if (unsafe_resources[0].threat_type ==
784      SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL) {
785    return false;
786  }
787
788  // Otherwise, check the threat type.
789  return unsafe_resources.size() == 1 && !unsafe_resources[0].is_subresource;
790}
791
792SafeBrowsingBlockingPageV1::SafeBrowsingBlockingPageV1(
793    SafeBrowsingUIManager* ui_manager,
794    WebContents* web_contents,
795    const UnsafeResourceList& unsafe_resources)
796  : SafeBrowsingBlockingPage(ui_manager, web_contents, unsafe_resources) {
797}
798
799std::string SafeBrowsingBlockingPageV1::GetHTMLContents() {
800  // Load the HTML page and create the template components.
801  DictionaryValue strings;
802  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
803  std::string html;
804
805  if (unsafe_resources_.empty()) {
806    NOTREACHED();
807    return std::string();
808  }
809
810  DCHECK_GT(unsafe_resources_.size(), 1U);
811  PopulateMultipleThreatStringDictionary(&strings);
812  html = rb.GetRawDataResource(
813      IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK).as_string();
814  interstitial_show_time_ = base::TimeTicks::Now();
815  return webui::GetTemplatesHtml(html, &strings, "template_root");
816}
817
818void SafeBrowsingBlockingPageV1::PopulateStringDictionary(
819    DictionaryValue* strings,
820    const string16& title,
821    const string16& headline,
822    const string16& description1,
823    const string16& description2,
824    const string16& description3) {
825  strings->SetString("title", title);
826  strings->SetString("headLine", headline);
827  strings->SetString("description1", description1);
828  strings->SetString("description2", description2);
829  strings->SetString("description3", description3);
830  strings->SetBoolean("proceedDisabled",
831                      IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled));
832}
833
834void SafeBrowsingBlockingPageV1::PopulateMultipleThreatStringDictionary(
835    DictionaryValue* strings) {
836
837  string16 malware_label =
838      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_LABEL);
839  string16 malware_link =
840      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE);
841  string16 phishing_label =
842      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_LABEL);
843  string16 phishing_link =
844      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_REPORT_ERROR);
845
846  ListValue* error_strings = new ListValue;
847  for (UnsafeResourceList::const_iterator iter = unsafe_resources_.begin();
848       iter != unsafe_resources_.end(); ++iter) {
849    const UnsafeResource& resource = *iter;
850    SBThreatType threat_type = resource.threat_type;
851    DictionaryValue* current_error_strings = new DictionaryValue;
852    if (threat_type == SB_THREAT_TYPE_URL_MALWARE) {
853      current_error_strings->SetString("type", "malware");
854      current_error_strings->SetString("typeLabel", malware_label);
855      current_error_strings->SetString("errorLink", malware_link);
856    } else {
857      DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
858             threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
859      current_error_strings->SetString("type", "phishing");
860      current_error_strings->SetString("typeLabel", phishing_label);
861      current_error_strings->SetString("errorLink", phishing_link);
862    }
863    current_error_strings->SetString("url", resource.url.spec());
864    error_strings->Append(current_error_strings);
865  }
866  strings->Set("errors", error_strings);
867
868  switch (interstitial_type_) {
869    case TYPE_MALWARE_AND_PHISHING:
870      PopulateStringDictionary(
871          strings,
872          // Use the malware headline, it is the scariest one.
873          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MULTI_THREAT_TITLE),
874          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_HEADLINE),
875          l10n_util::GetStringFUTF16(
876              IDS_SAFE_BROWSING_MULTI_THREAT_DESCRIPTION1,
877              UTF8ToUTF16(web_contents_->GetURL().host())),
878          l10n_util::GetStringUTF16(
879              IDS_SAFE_BROWSING_MULTI_THREAT_DESCRIPTION2),
880          string16());
881      break;
882    case TYPE_MALWARE:
883      PopulateStringDictionary(
884          strings,
885          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_TITLE),
886          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_HEADLINE),
887          l10n_util::GetStringFUTF16(
888              IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION1,
889              UTF8ToUTF16(web_contents_->GetURL().host())),
890          l10n_util::GetStringUTF16(
891              IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION2),
892          l10n_util::GetStringUTF16(
893              IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION3));
894      break;
895    case TYPE_PHISHING:
896      PopulateStringDictionary(
897          strings,
898          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_TITLE),
899          l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_HEADLINE),
900          l10n_util::GetStringFUTF16(
901              IDS_SAFE_BROWSING_MULTI_PHISHING_DESCRIPTION1,
902              UTF8ToUTF16(web_contents_->GetURL().host())),
903          string16(),
904          string16());
905      break;
906  }
907
908  strings->SetString("confirm_text",
909                     l10n_util::GetStringUTF16(
910                         IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION_AGREE));
911  strings->SetString("continue_button",
912                     l10n_util::GetStringUTF16(
913                         IDS_SAFE_BROWSING_MULTI_MALWARE_PROCEED_BUTTON));
914  strings->SetString("back_button",
915      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_BACK_BUTTON));
916  strings->SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
917}
918
919void SafeBrowsingBlockingPageV1::PopulateMalwareStringDictionary(
920    DictionaryValue* strings) {
921  NOTREACHED();
922}
923
924void SafeBrowsingBlockingPageV1::PopulatePhishingStringDictionary(
925    DictionaryValue* strings) {
926  NOTREACHED();
927}
928
929SafeBrowsingBlockingPageV2::SafeBrowsingBlockingPageV2(
930    SafeBrowsingUIManager* ui_manager,
931    WebContents* web_contents,
932    const UnsafeResourceList& unsafe_resources)
933  : SafeBrowsingBlockingPage(ui_manager, web_contents, unsafe_resources) {
934    if (unsafe_resources_[0].threat_type == SB_THREAT_TYPE_URL_MALWARE) {
935      trialCondition_ =
936          base::FieldTrialList::FindFullName(kMalwareStudyName);
937    } else if (unsafe_resources_[0].threat_type ==
938                   SB_THREAT_TYPE_URL_PHISHING ||
939               unsafe_resources_[0].threat_type ==
940                   SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL) {
941      trialCondition_ =
942          base::FieldTrialList::FindFullName(kPhishingStudyName);
943    }
944}
945
946std::string SafeBrowsingBlockingPageV2::GetHTMLContents() {
947  // Load the HTML page and create the template components.
948  DictionaryValue strings;
949  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
950  std::string html;
951
952  if (unsafe_resources_.empty()) {
953    NOTREACHED();
954    return std::string();
955  }
956
957  if (unsafe_resources_.size() > 1) {
958    // TODO(mattm): Implement new multi-threat interstitial and remove
959    // SafeBrowsingBlockingPageV1 entirely.  (http://crbug.com/160336)
960    NOTREACHED();
961  } else {
962    SBThreatType threat_type = unsafe_resources_[0].threat_type;
963    if (threat_type == SB_THREAT_TYPE_URL_MALWARE) {
964      PopulateMalwareStringDictionary(&strings);
965    } else {  // Phishing.
966      DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
967             threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
968      PopulatePhishingStringDictionary(&strings);
969    }
970    html = rb.GetRawDataResource(IDR_SAFE_BROWSING_MALWARE_BLOCK_V2).
971        as_string();
972  }
973  interstitial_show_time_ = base::TimeTicks::Now();
974  return webui::GetTemplatesHtml(html, &strings, "template-root");
975}
976
977void SafeBrowsingBlockingPageV2::PopulateStringDictionary(
978    DictionaryValue* strings,
979    const string16& title,
980    const string16& headline,
981    const string16& description1,
982    const string16& description2,
983    const string16& description3) {
984  strings->SetString("title", title);
985  strings->SetString("headLine", headline);
986  strings->SetString("description1", description1);
987  strings->SetString("description2", description2);
988  strings->SetString("description3", description3);
989  strings->SetBoolean("proceedDisabled",
990                      IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled));
991  strings->SetBoolean("isMainFrame", is_main_frame_load_blocked_);
992  strings->SetBoolean("isPhishing", interstitial_type_ == TYPE_PHISHING);
993
994  strings->SetString("back_button",
995      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_BACK_BUTTON));
996  strings->SetString("seeMore", l10n_util::GetStringUTF16(
997      IDS_SAFE_BROWSING_MALWARE_V2_SEE_MORE));
998  strings->SetString("proceed",
999      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_V2_PROCEED_LINK));
1000
1001  // Field trial
1002  strings->SetString("trialType", trialCondition_);
1003  if (trialCondition_ == kCond7MalwareFearMsg) {
1004    strings->SetString("headLine",
1005        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_FEAR_HEADLINE));
1006  } else if (trialCondition_ == kCond8PhishingFearMsg) {
1007    strings->SetString("headLine",
1008        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_FEAR_HEADLINE));
1009  } else if (trialCondition_ == kCond9MalwareCollabMsg) {
1010    strings->SetString("headLine",
1011        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_COLLAB_HEADLINE));
1012  } else if (trialCondition_ == kCond10PhishingCollabMsg) {
1013    strings->SetString("headLine",
1014        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_COLLAB_HEADLINE));
1015  } else if (trialCondition_ == kCond11MalwareQuestion) {
1016    strings->SetString("headLine",
1017        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_QUESTION_HEADLINE));
1018  } else if (trialCondition_ == kCond12PhishingQuestion) {
1019    strings->SetString("headLine",
1020        l10n_util::GetStringUTF16(
1021            IDS_SAFE_BROWSING_PHISHING_QUESTION_HEADLINE));
1022  } else if (trialCondition_ == kCond13MalwareGoBack) {
1023    strings->SetString("headLine",
1024        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_BACK_HEADLINE));
1025  } else if (trialCondition_ == kCond14PhishingGoBack) {
1026    strings->SetString("headLine",
1027        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_BACK_HEADLINE));
1028  }
1029
1030  webui::SetFontAndTextDirection(strings);
1031}
1032
1033void SafeBrowsingBlockingPageV2::PopulateMultipleThreatStringDictionary(
1034    DictionaryValue* strings) {
1035  NOTREACHED();
1036}
1037
1038void SafeBrowsingBlockingPageV2::PopulateMalwareStringDictionary(
1039    DictionaryValue* strings) {
1040  std::string diagnostic_link = base::StringPrintf(kSbDiagnosticHtml,
1041      l10n_util::GetStringUTF8(
1042        IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE).c_str());
1043
1044  // Check to see if we're blocking the main page, or a sub-resource on the
1045  // main page.
1046  string16 headline, description1, description2, description3;
1047
1048
1049  description3 = l10n_util::GetStringUTF16(
1050      IDS_SAFE_BROWSING_MALWARE_V2_DESCRIPTION3);
1051  if (is_main_frame_load_blocked_) {
1052    headline = l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_V2_HEADLINE);
1053    description1 = l10n_util::GetStringFUTF16(
1054        IDS_SAFE_BROWSING_MALWARE_V2_DESCRIPTION1,
1055        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
1056        UTF8ToUTF16(url_.host()));
1057    description2 = l10n_util::GetStringUTF16(
1058        IDS_SAFE_BROWSING_MALWARE_V2_DESCRIPTION2);
1059    strings->SetString("details", l10n_util::GetStringUTF16(
1060          IDS_SAFE_BROWSING_MALWARE_V2_DETAILS));
1061  } else {
1062    headline = l10n_util::GetStringUTF16(
1063        IDS_SAFE_BROWSING_MALWARE_V2_HEADLINE_SUBRESOURCE);
1064    description1 = l10n_util::GetStringFUTF16(
1065        IDS_SAFE_BROWSING_MALWARE_V2_DESCRIPTION1_SUBRESOURCE,
1066        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
1067        UTF8ToUTF16(web_contents_->GetURL().host()));
1068    description2 = l10n_util::GetStringFUTF16(
1069        IDS_SAFE_BROWSING_MALWARE_V2_DESCRIPTION2_SUBRESOURCE,
1070        UTF8ToUTF16(url_.host()));
1071    strings->SetString("details", l10n_util::GetStringFUTF16(
1072          IDS_SAFE_BROWSING_MALWARE_V2_DETAILS_SUBRESOURCE,
1073          UTF8ToUTF16(url_.host())));
1074  }
1075
1076  PopulateStringDictionary(
1077      strings,
1078      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_V2_TITLE),
1079      headline,
1080      description1,
1081      description2,
1082      description3);
1083
1084  if (!CanShowMalwareDetailsOption()) {
1085    strings->SetBoolean(kDisplayCheckBox, false);
1086    strings->SetString("confirm_text", std::string());
1087    strings->SetString(kBoxChecked, std::string());
1088  } else {
1089    // Show the checkbox for sending malware details.
1090    strings->SetBoolean(kDisplayCheckBox, true);
1091
1092    std::string privacy_link = base::StringPrintf(
1093        kPrivacyLinkHtml,
1094        l10n_util::GetStringUTF8(
1095            IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE_V2).c_str());
1096
1097    strings->SetString("confirm_text",
1098                       l10n_util::GetStringFUTF16(
1099                           IDS_SAFE_BROWSING_MALWARE_V2_REPORTING_AGREE,
1100                           UTF8ToUTF16(privacy_link)));
1101    if (IsPrefEnabled(prefs::kSafeBrowsingReportingEnabled))
1102      strings->SetString(kBoxChecked, "yes");
1103    else
1104      strings->SetString(kBoxChecked, std::string());
1105  }
1106
1107  strings->SetString("report_error", string16());
1108  strings->SetString("learnMore",
1109      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_V2_LEARN_MORE));
1110}
1111
1112void SafeBrowsingBlockingPageV2::PopulatePhishingStringDictionary(
1113    DictionaryValue* strings) {
1114  PopulateStringDictionary(
1115      strings,
1116      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_V2_TITLE),
1117      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_V2_HEADLINE),
1118      l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_PHISHING_V2_DESCRIPTION1,
1119                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
1120                                 UTF8ToUTF16(url_.host())),
1121      string16(),
1122      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_V2_DESCRIPTION2));
1123
1124  strings->SetString("details", std::string());
1125  strings->SetString("confirm_text", std::string());
1126  strings->SetString(kBoxChecked, std::string());
1127  strings->SetString(
1128      "report_error",
1129      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_V2_REPORT_ERROR));
1130  strings->SetBoolean(kDisplayCheckBox, false);
1131  strings->SetString("learnMore",
1132      l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_V2_LEARN_MORE));
1133}
1134