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