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