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