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