- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / safe_browsing_blocking_page.cc
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 string16& title,
877     const string16& headline,
878     const string16& description1,
879     const string16& description2,
880     const 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   string16 malware_label =
894       l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_LABEL);
895   string16 malware_link =
896       l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE);
897   string16 phishing_label =
898       l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_PHISHING_LABEL);
899   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           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           string16(),
961           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 string16& title,
1040     const string16& headline,
1041     const string16& description1,
1042     const string16& description2,
1043     const 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   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", 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       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 }