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