diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-23 21:05:34 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-23 21:05:34 +0000 |
commit | 1b277e7f6d171b9cb2383f925373ffedcd3e4672 (patch) | |
tree | 931b42af6d84753cb1d24c1eec80e913f104c625 /chrome/browser | |
parent | deb17b8d4fc8ef1bc2222bbb83414d6983fd7d02 (diff) | |
download | chromium_src-1b277e7f6d171b9cb2383f925373ffedcd3e4672.zip chromium_src-1b277e7f6d171b9cb2383f925373ffedcd3e4672.tar.gz chromium_src-1b277e7f6d171b9cb2383f925373ffedcd3e4672.tar.bz2 |
This CL makes the safe browsing interstitial page support multiple unsafe resources in one page.
We had a bug when an interstitial was showing and another unsafe resource was detected. We would show another interstitial on top of the original one, causing the DontProceed method to be invoked several times. That would cause us to remove more than once an entry from the navigation controller and cause crashers.
With this new CL, if an interstitial shows and a new resource is flagged as bad, the SafeBrowsingBlockingPage will queue that notification. If the user decides to proceed through the interstitial, we'll create another interstitial warning about all the unsafe resources we have received so far.
This CL also contains a fix for a crasher that would happen when closing a tab with a safe browsing interstitial.
BUG=5916,6207,6306
TEST=Test all actions in the interstitial you get when opening pages with the followin scenarios:
- Main page is malware
- Main page is fishing
- Main page is OK contains resources (images,iframes...) which are malware
- Main page is OK contains resources (images,iframes...) which are phishing
- Main page is OK contains resources (images,iframes...) some of them phishing, some of then malware.
Note that when there are more than one bad resource, it is normal to see a 1st interstitial, then another one listing all the other bad resources.
(ex of malware site http://ianfette.org, phishing site http://cvisit.tripod.com)
Review URL: http://codereview.chromium.org/18346
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8578 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
12 files changed, 636 insertions, 191 deletions
diff --git a/chrome/browser/browser_resources.h b/chrome/browser/browser_resources.h index dd1fdd1..e856337 100644 --- a/chrome/browser/browser_resources.h +++ b/chrome/browser/browser_resources.h @@ -9,6 +9,8 @@ #define IDR_NEW_TAB_HTML 208 #define IDR_SAFE_BROWSING_MALWARE_BLOCK 209 #define IDR_SAFE_BROWSING_PHISHING_BLOCK 210 -#define IDR_INCOGNITO_TAB_HTML 211 -#define IDR_CREDITS_HTML 212 -#define IDR_HISTORY_HTML 213 +#define IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK 211 +#define IDR_INCOGNITO_TAB_HTML 212 +#define IDR_CREDITS_HTML 213 +#define IDR_HISTORY_HTML 214 + diff --git a/chrome/browser/browser_resources.rc b/chrome/browser/browser_resources.rc index 8ce4e17..b061e4e 100644 --- a/chrome/browser/browser_resources.rc +++ b/chrome/browser/browser_resources.rc @@ -27,6 +27,7 @@ IDR_SSL_ERROR_HTML BINDATA "browser_resources\\ssl_error_flat.html" IDR_NEW_TAB_HTML BINDATA "browser_resources\\new_tab_flat.html" IDR_SAFE_BROWSING_MALWARE_BLOCK BINDATA "browser_resources\\safe_browsing_malware_block_flat.html" IDR_SAFE_BROWSING_PHISHING_BLOCK BINDATA "browser_resources\\safe_browsing_phishing_block_flat.html" +IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK BINDATA "browser_resources\\safe_browsing_multiple_threat_block_flat.html" IDR_INCOGNITO_TAB_HTML BINDATA "browser_resources\\incognito_tab_flat.html" IDR_CREDITS_HTML BINDATA "browser_resources\\about_credits_flat.html" IDR_HISTORY_HTML BINDATA "browser_resources\\history_flat.html"
\ No newline at end of file diff --git a/chrome/browser/resources/browser_resources.vcproj b/chrome/browser/resources/browser_resources.vcproj index 94d94ee..0a51fd9 100644 --- a/chrome/browser/resources/browser_resources.vcproj +++ b/chrome/browser/resources/browser_resources.vcproj @@ -96,6 +96,10 @@ > </File> <File + RelativePath=".\safe_browsing_multiple_threat_block.html" + > + </File> + <File RelativePath=".\safe_browsing_phishing_block.html" > </File> diff --git a/chrome/browser/resources/safe_browsing_malware_block.html b/chrome/browser/resources/safe_browsing_malware_block.html index f05a27e..304374f 100644 --- a/chrome/browser/resources/safe_browsing_malware_block.html +++ b/chrome/browser/resources/safe_browsing_malware_block.html @@ -87,12 +87,12 @@ input { <div class="title" jscontent="headLine"></div> <div class="main" jseval="this.innerHTML = $this.description1;"></div> <div class="main" jseval="this.innerHTML = $this.description2;"></div> - <div class="main"><a href="" jscontent="description3" onclick="sendCommand(2); return false;" onmousedown="return false;"></a></div> + <div class="main"><a href="" jscontent="description3" onclick="sendCommand('learnMore'); return false;" onmousedown="return false;"></a></div> <div class="main"> <form class="submission"> <input name="checky" type="checkbox" onclick="agreed(this.form)"> <span jscontent="confirm_text"></span> - <input type="button" name="continue_button" jsvalues="value:continue_button" disabled="true" onclick="sendCommand(1)"><br> - <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand(0)"> + <input type="button" name="continue_button" jsvalues="value:continue_button" disabled="true" onclick="sendCommand('proceed')"><br> + <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand('takeMeBack')"> </form> </div> </div> diff --git a/chrome/browser/resources/safe_browsing_multiple_threat_block.html b/chrome/browser/resources/safe_browsing_multiple_threat_block.html new file mode 100644 index 0000000..0926320 --- /dev/null +++ b/chrome/browser/resources/safe_browsing_multiple_threat_block.html @@ -0,0 +1,142 @@ +<html id="template_root"> + +<head> +<title jscontent="title"></title> +<style type="text/css"> +body { + background-color:#500; + font-family:arial; + margin:0px; +} +.background { + position:absolute; + width:100%; + height:100%; +} +.cell { + padding:40px; +} +.box { + width:80%; + background-color:white; + color:black; + font-size:10pt; + line-height:16pt; + text-align:left; + padding:20px; + position:relative; + -webkit-box-shadow:3px 3px 8px #200; + -webkit-border-radius:5px; +} +html[dir='rtl'] .box { + text-align:right; +} + +.icon { + position:absolute; +} +.title { + margin:0px 87px 0px; + font-size:18pt; + margin-bottom:6pt; + font-weight:bold; + color:#660000; +} +.main { + margin:0px 90px 0px; +} +.submission { + margin:15px 5px 15px 0px; + padding:0px; +} +input { + margin:0px; +} +.proceedbutton { +} +.helpbutton { + float:right; +} +.example { + margin: 30px 90px 0px; + border-top:1px solid #ccc; + padding-top:6px; +} +.moreinfotitle { + margin-left:5px; + margin-right:5px; +} + +.errorlist { + background-color:white; + color:black; + font-size:10pt; + line-height:16pt; + text-align:left; +} +</style> + +<script> +function agreed(form) { + form.continue_button.disabled = !form.continue_button.disabled; +} + +function sendCommand(command) { + window.domAutomationController.setAutomationId(1); + window.domAutomationController.send(command); +} + +function showDiagnostic(errorID) { + sendCommand("showDiagnostic:" + errorID); +} + +function reportError(errorID) { + sendCommand("reportError:" + errorID); +} + +function learnMore() { + sendCommand("learnMore"); +} + +function proceed() { + sendCommand("proceed"); +} + +function takeMeBack() { + sendCommand("takeMeBack"); +} +</script> +</head> + +<body oncontextmenu="return false;"> +<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"/></div> +<table width="100%" cellspacing="0" cellpadding="0"> + <td class="cell" valign="middle" align="center"> + <div class="box"> + <div class="icon"><img src="phishing_icon.png" alt="Malware Icon" onmousedown="return false;"/></div> + <div class="title" jscontent="headLine"></div> + <div class="main" jseval="this.innerHTML = $this.description1;"></div> + <div class="main" jscontent="description2"></div> + <div class="main"> + <table cellpadding="5" jsvalues="$counter:{value: 0}"> + <tr jsselect="errors" class="errorlist"> + <td jscontent="typeLabel"></td> + <td jscontent="url"></td> + <td><a href="" onclick="var id= this.getAttribute('chromiumID'); this.getAttribute('chromiumIsMalware') ? showDiagnostic(id) : reportError(id); return false;" jscontent="errorLink" jsvalues="chromiumID:$counter.value;chromiumIsMalware:type=='malware'" jseval="$counter.value++"></a></td> + </tr> + </table> + </div> + + <div class="main"><a href="" jscontent="description3" onclick="learnMore(); return false;" onmousedown="return false;"></a></div> + <div class="main"> + <form class="submission"> + <input name="checky" type="checkbox" onclick="agreed(this.form)"> <span jscontent="confirm_text"></span> + <input type="button" name="continue_button" jsvalues="value:continue_button" disabled="true" onclick="proceed();"><br> + <input type="button" name="back_button" jsvalues="value:back_button" onclick="takeMeBack()"> + </form> + </div> + </div> + </td> +</table> +</body> +</html> diff --git a/chrome/browser/resources/safe_browsing_phishing_block.html b/chrome/browser/resources/safe_browsing_phishing_block.html index aec7acf..0269b07 100644 --- a/chrome/browser/resources/safe_browsing_phishing_block.html +++ b/chrome/browser/resources/safe_browsing_phishing_block.html @@ -88,14 +88,14 @@ html[dir='rtl'] .helpbutton { <div class="icon"><img src="phishing_icon.png" alt="Phishing Warning Icon" onmousedown="return false;"/></div> <div class="title" jscontent="headLine"></div> <div class="main" jseval="this.innerHTML = $this.description1;"></div> - <div class="main"><a href="" jscontent="description2" onclick="sendCommand(2); return false;" onmousedown="return false;"></a></div> + <div class="main"><a href="" jscontent="description2" onclick="sendCommand('learnMore'); return false;" onmousedown="return false;"></a></div> <div class="main"> <form class="submission"> - <input type="button" name="continue_button" jsvalues="value:continue_button" onclick="sendCommand(1)"> - <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand(0)"> + <input type="button" name="continue_button" jsvalues="value:continue_button" onclick="sendCommand('proceed')"> + <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand('takeMeBack')"> </form> </div> - <div class="main"><a href="" onclick="sendCommand(3); return false;" onmousedown="return false;" jscontent="report_error"></a></div> + <div class="main"><a href="" onclick="sendCommand('reportError'); return false;" onmousedown="return false;" jscontent="report_error"></a></div> </div> </td> </table> diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc index 4d34450..c6b6feb 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc @@ -6,6 +6,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" +#include "base/string_util.h" #include "chrome/app/locales/locale_settings.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_resources.h" @@ -38,23 +39,25 @@ static const char* const kSbReportPhishingUrl = "http://www.google.com/safebrowsing/report_error/"; static const wchar_t* const kSbDiagnosticHtml = - L"<a href=\"\" onClick=\"sendCommand(4); return false;\" onMouseDown=\"return false;\">%ls</a>"; + L"<a href=\"\" onClick=\"sendCommand('showDiagnostic'); return false;\" onMouseDown=\"return false;\">%ls</a>"; + +// The commands returned by the page when the user performs an action. +static const char* const kShowDiagnosticCommand = "showDiagnostic"; +static const char* const kReportErrorCommand = "reportError"; +static const char* const kLearnMoreCommand = "learnMore"; +static const char* const kProceedCommand = "proceed"; +static const char* const kTakeMeBackCommand = "takeMeBack"; SafeBrowsingBlockingPage::SafeBrowsingBlockingPage( SafeBrowsingService* sb_service, - const SafeBrowsingService::BlockingPageParam& param) - : InterstitialPage(tab_util::GetWebContentsByID( - param.render_process_host_id, param.render_view_id), - param.resource_type == ResourceType::MAIN_FRAME, - param.url), + WebContents* web_contents, + const UnsafeResourceList& unsafe_resources) + : InterstitialPage(web_contents, + IsMainPage(unsafe_resources), + unsafe_resources[0].url), sb_service_(sb_service), - client_(param.client), - render_process_host_id_(param.render_process_host_id), - render_view_id_(param.render_view_id), - result_(param.result), - proceed_(false), - did_notify_(false), - is_main_frame_(param.resource_type == ResourceType::MAIN_FRAME) { + unsafe_resources_(unsafe_resources), + is_main_frame_(IsMainPage(unsafe_resources)) { if (!is_main_frame_) { navigation_entry_index_to_remove_ = tab()->controller()->GetLastCommittedEntryIndex(); @@ -72,84 +75,200 @@ std::string SafeBrowsingBlockingPage::GetHTMLContents() { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); std::string html; - if (result_ == SafeBrowsingService::URL_MALWARE) { - std::wstring link = StringPrintf(kSbDiagnosticHtml, - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE). - c_str()); - - strings.SetString(L"badURL", UTF8ToWide(url().host())); - strings.SetString(L"title", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_TITLE)); - strings.SetString(L"headLine", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_HEADLINE)); - - // Check to see if we're blocking the main page, or a sub-resource on the - // main page. - if (is_main_frame_) { - strings.SetString(L"description1", - l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION1, - UTF8ToWide(url().host()))); - strings.SetString(L"description2", - l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION2, - link, - UTF8ToWide(url().host()))); - } else { - strings.SetString(L"description1", - l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION4, - UTF8ToWide(tab()->GetURL().host()), - UTF8ToWide(url().host()))); - strings.SetString(L"description2", - l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION5, - link, - UTF8ToWide(url().host()))); - } + if (unsafe_resources_.empty()) { + NOTREACHED(); + return std::string(); + } - strings.SetString(L"description3", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION3)); - strings.SetString(L"confirm_text", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION_AGREE)); - strings.SetString(L"continue_button", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_PROCEED_BUTTON)); - strings.SetString(L"back_button", - l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_BACK_BUTTON)); - strings.SetString(L"textdirection", - (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? - L"rtl" : L"ltr"); + if (unsafe_resources_.size() > 1) { + PopulateMultipleThreatStringDictionary(&strings); + html = rb.GetDataResource(IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK); + } else if (unsafe_resources_[0].threat_type == + SafeBrowsingService::URL_MALWARE) { + PopulateMalwareStringDictionary(&strings); html = rb.GetDataResource(IDR_SAFE_BROWSING_MALWARE_BLOCK); } else { // Phishing. - strings.SetString(L"title", - l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_TITLE)); - strings.SetString(L"headLine", - l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_HEADLINE)); - strings.SetString(L"description1", - l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION1, - UTF8ToWide(url().host()))); - strings.SetString(L"description2", - l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION2, - UTF8ToWide(url().host()))); - - strings.SetString(L"continue_button", - l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_PROCEED_BUTTON)); - strings.SetString(L"back_button", - l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_BACK_BUTTON)); - strings.SetString(L"report_error", - l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_REPORT_ERROR)); - strings.SetString(L"textdirection", - (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? - L"rtl" : L"ltr"); + DCHECK(unsafe_resources_[0].threat_type == + SafeBrowsingService::URL_PHISHING); + PopulatePhishingStringDictionary(&strings); html = rb.GetDataResource(IDR_SAFE_BROWSING_PHISHING_BLOCK); } return jstemplate_builder::GetTemplateHtml(html, &strings, "template_root"); } -void SafeBrowsingBlockingPage::CommandReceived(const std::string& command) { - if (command == "2") { +void SafeBrowsingBlockingPage::PopulateStringDictionary( + DictionaryValue* strings, + const std::wstring& title, + const std::wstring& headline, + const std::wstring& description1, + const std::wstring& description2, + const std::wstring& description3) { + strings->SetString(L"title", title); + strings->SetString(L"headLine", headline); + strings->SetString(L"description1", description1); + strings->SetString(L"description2", description2); + strings->SetString(L"description3", description3); +} + +void SafeBrowsingBlockingPage::PopulateMultipleThreatStringDictionary( + DictionaryValue* strings) { + bool malware = false; + bool phishing = false; + + std::wstring phishing_label = + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_LABEL); + std::wstring phishing_link = + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_REPORT_ERROR); + std::wstring malware_label = + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_LABEL); + std::wstring malware_link = + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE); + + ListValue* error_strings = new ListValue; + for (UnsafeResourceList::const_iterator iter = unsafe_resources_.begin(); + iter != unsafe_resources_.end(); ++iter) { + const SafeBrowsingService::UnsafeResource& resource = *iter; + DictionaryValue* current_error_strings = new DictionaryValue; + if (resource.threat_type == SafeBrowsingService::URL_MALWARE) { + malware = true; + current_error_strings->SetString(L"type", L"malware"); + current_error_strings->SetString(L"typeLabel", malware_label); + current_error_strings->SetString(L"errorLink", malware_link); + } else { + DCHECK(resource.threat_type == SafeBrowsingService::URL_PHISHING); + phishing = true; + current_error_strings->SetString(L"type", L"phishing"); + current_error_strings->SetString(L"typeLabel", phishing_label); + current_error_strings->SetString(L"errorLink", phishing_link); + } + current_error_strings->SetString(L"url", UTF8ToWide(resource.url.spec())); + error_strings->Append(current_error_strings); + } + strings->Set(L"errors", error_strings); + DCHECK(phishing || malware); + + if (malware && phishing) { + PopulateStringDictionary( + strings, + // Use the malware headline, it is the scariest one. + l10n_util::GetString(IDS_SAFE_BROWSING_MULTI_THREAT_TITLE), + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_HEADLINE), + l10n_util::GetStringF(IDS_SAFE_BROWSING_MULTI_THREAT_DESCRIPTION1, + UTF8ToWide(tab()->GetURL().host())), + l10n_util::GetString(IDS_SAFE_BROWSING_MULTI_THREAT_DESCRIPTION2), + L""); + } else if (malware) { + // Just malware. + PopulateStringDictionary( + strings, + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_TITLE), + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_HEADLINE), + l10n_util::GetStringF(IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION1, + UTF8ToWide(tab()->GetURL().host())), + l10n_util::GetString(IDS_SAFE_BROWSING_MULTI_MALWARE_DESCRIPTION2), + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION3)); + } else { + // Just phishing. + PopulateStringDictionary( + strings, + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_TITLE), + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_HEADLINE), + l10n_util::GetStringF(IDS_SAFE_BROWSING_MULTI_PHISHING_DESCRIPTION1, + UTF8ToWide(tab()->GetURL().host())), + L"", L""); + } + + strings->SetString(L"confirm_text", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION_AGREE)); + strings->SetString(L"continue_button", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_PROCEED_BUTTON)); + strings->SetString(L"back_button", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_BACK_BUTTON)); + strings->SetString(L"textdirection", + (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? + L"rtl" : L"ltr"); +} + +void SafeBrowsingBlockingPage::PopulateMalwareStringDictionary( + DictionaryValue* strings) { + std::wstring link = StringPrintf(kSbDiagnosticHtml, + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DIAGNOSTIC_PAGE).c_str()); + + strings->SetString(L"badURL", UTF8ToWide(url().host())); + // Check to see if we're blocking the main page, or a sub-resource on the + // main page. + std::wstring description1, description2; + if (is_main_frame_) { + description1 = l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION1, + UTF8ToWide(url().host())); + description2 = l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION2, + link, + UTF8ToWide(url().host())); + } else { + description1 = l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION4, + UTF8ToWide(tab()->GetURL().host()), + UTF8ToWide(url().host())); + description2 = l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION5, + link, + UTF8ToWide(url().host())); + } + + PopulateStringDictionary( + strings, + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_TITLE), + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_HEADLINE), + description1, description2, + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION3)); + + strings->SetString(L"confirm_text", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION_AGREE)); + strings->SetString(L"continue_button", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_PROCEED_BUTTON)); + strings->SetString(L"back_button", + l10n_util::GetString(IDS_SAFE_BROWSING_MALWARE_BACK_BUTTON)); + strings->SetString(L"textdirection", + (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? + L"rtl" : L"ltr"); +} + +void SafeBrowsingBlockingPage::PopulatePhishingStringDictionary( + DictionaryValue* strings) { + PopulateStringDictionary( + strings, + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_TITLE), + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_HEADLINE), + l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION1, + UTF8ToWide(url().host())), + l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION2, + UTF8ToWide(url().host())), + L""); + + strings->SetString(L"continue_button", + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_PROCEED_BUTTON)); + strings->SetString(L"back_button", + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_BACK_BUTTON)); + strings->SetString(L"report_error", + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_REPORT_ERROR)); + strings->SetString(L"textdirection", + (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? + L"rtl" : L"ltr"); +} + +void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) { + std::string command(cmd); // Make a local copy so we can modify it. + // The Jasonified response has quotes, remove them. + if (command.length() > 1 && command[0] == '"') { + command = command.substr(1, command.length() - 2); + } + + if (command == kLearnMoreCommand) { // User pressed "Learn more". GURL url; - if (result_ == SafeBrowsingService::URL_MALWARE) { + if (unsafe_resources_[0].threat_type == SafeBrowsingService::URL_MALWARE) { url = GURL(l10n_util::GetString(IDS_LEARN_MORE_MALWARE_URL)); - } else if (result_ == SafeBrowsingService::URL_PHISHING) { + } else if (unsafe_resources_[0].threat_type == + SafeBrowsingService::URL_PHISHING) { url = GURL(l10n_util::GetString(IDS_LEARN_MORE_PHISHING_URL)); } else { NOTREACHED(); @@ -157,68 +276,164 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& command) { tab()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::LINK); return; } - if (command == "3") { + + if (command == kProceedCommand) { + Proceed(); + // We are deleted after this. + return; + } + + if (command == kTakeMeBackCommand) { + DontProceed(); + // We are deleted after this. + return; + } + + // The "report error" and "show diagnostic" commands can have a number + // appended to them, which is the index of the element they apply to. + int element_index = 0; + size_t colon_index = command.find(':'); + if (colon_index != std::string::npos) { + DCHECK(colon_index < command.size() - 1); + std::string index_str = command.substr(colon_index + 1); + command = command.substr(0, colon_index); + bool result = StringToInt(index_str, &element_index); + DCHECK(result); + } + + if (element_index >= static_cast<int>(unsafe_resources_.size())) { + NOTREACHED(); + return; + } + + std::string bad_url_spec = unsafe_resources_[element_index].url.spec(); + if (command == kReportErrorCommand) { // User pressed "Report error" for a phishing site. // Note that we cannot just put a link in the interstitial at this point. // It is not OK to navigate in the context of an interstitial page. - DCHECK(result_ == SafeBrowsingService::URL_PHISHING); + DCHECK(unsafe_resources_[element_index].threat_type == + SafeBrowsingService::URL_PHISHING); GURL report_url = safe_browsing_util::GeneratePhishingReportUrl(kSbReportPhishingUrl, - url().spec()); - Hide(); + bad_url_spec); tab()->OpenURL(report_url, GURL(), CURRENT_TAB, PageTransition::LINK); return; } - if (command == "4") { + + if (command == kShowDiagnosticCommand) { // We're going to take the user to Google's SafeBrowsing diagnostic page. std::string diagnostic = StringPrintf(kSbDiagnosticUrl, - EscapeQueryParamValue(url().spec()).c_str()); + EscapeQueryParamValue(bad_url_spec).c_str()); GURL diagnostic_url(diagnostic); diagnostic_url = google_util::AppendGoogleLocaleParam(diagnostic_url); - DCHECK(result_ == SafeBrowsingService::URL_MALWARE); + DCHECK(unsafe_resources_[element_index].threat_type == + SafeBrowsingService::URL_MALWARE); tab()->OpenURL(diagnostic_url, GURL(), CURRENT_TAB, PageTransition::LINK); return; } - proceed_ = command == "1"; + NOTREACHED() << "Unexpected command: " << command; +} - if (proceed_) - Proceed(); - else - DontProceed(); +void SafeBrowsingBlockingPage::Proceed() { + NotifySafeBrowsingService(sb_service_, unsafe_resources_, true); + + // Check to see if some new notifications of unsafe resources have been + // received while we were showing the interstitial. + UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap(); + UnsafeResourceMap::iterator iter = unsafe_resource_map->find(tab()); + SafeBrowsingBlockingPage* blocking_page = NULL; + if (iter != unsafe_resource_map->end() && !iter->second.empty()) { + // Build an interstitial for all the unsafe resources notifications. + // Don't show it now as showing an interstitial while an interstitial is + // already showing would cause DontProceed() to be invoked. + blocking_page = new SafeBrowsingBlockingPage(sb_service_, tab(), + iter->second); + unsafe_resource_map->erase(iter); + } - NotifyDone(); + InterstitialPage::Proceed(); + // We are now deleted. + + // Now that this interstitial is gone, we can show the new one. + if (blocking_page) + blocking_page->Show(); } void SafeBrowsingBlockingPage::DontProceed() { - if (navigation_entry_index_to_remove_ != -1) { + NotifySafeBrowsingService(sb_service_, unsafe_resources_, false); + + // The user does not want to proceed, clear the queued unsafe resources + // notifications we received while the interstitial was showing. + UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap(); + UnsafeResourceMap::iterator iter = unsafe_resource_map->find(tab()); + if (iter != unsafe_resource_map->end() && !iter->second.empty()) { + NotifySafeBrowsingService(sb_service_, iter->second, false); + unsafe_resource_map->erase(iter); + } + + // We don't remove the navigation entry if the tab is being destroyed as this + // would trigger a navigation that would cause trouble as the render view host + // for the tab has by then already been destroyed. + if (navigation_entry_index_to_remove_ != -1 && !tab()->is_being_destroyed()) { tab()->controller()->RemoveEntryAtIndex(navigation_entry_index_to_remove_, NewTabUIURL()); + navigation_entry_index_to_remove_ = -1; } InterstitialPage::DontProceed(); // We are now deleted. } -void SafeBrowsingBlockingPage::NotifyDone() { - if (did_notify_) - return; - - did_notify_ = true; - +// static +void SafeBrowsingBlockingPage::NotifySafeBrowsingService( + SafeBrowsingService* sb_service, + const UnsafeResourceList& unsafe_resources, + bool proceed) { base::Thread* io_thread = g_browser_process->io_thread(); if (!io_thread) return; - SafeBrowsingService::BlockingPageParam param; - param.url = url(); - param.result = result_; - param.client = client_; - param.render_process_host_id = render_process_host_id_; - param.render_view_id = render_view_id_; - param.proceed = proceed_; io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - sb_service_, - &SafeBrowsingService::OnBlockingPageDone, - param)); + sb_service, &SafeBrowsingService::OnBlockingPageDone, unsafe_resources, + proceed)); +} + +// static +SafeBrowsingBlockingPage::UnsafeResourceMap* + SafeBrowsingBlockingPage::GetUnsafeResourcesMap() { + return Singleton<UnsafeResourceMap>::get(); +} + +// static +void SafeBrowsingBlockingPage::ShowBlockingPage( + SafeBrowsingService* sb_service, + const SafeBrowsingService::UnsafeResource& unsafe_resource) { + WebContents* web_contents = tab_util::GetWebContentsByID( + unsafe_resource.render_process_host_id, unsafe_resource.render_view_id); + + if (!InterstitialPage::GetInterstitialPage(web_contents)) { + // There are no interstitial currently showing in that tab, go ahead and + // show this interstitial. + std::vector<SafeBrowsingService::UnsafeResource> resources; + resources.push_back(unsafe_resource); + SafeBrowsingBlockingPage* blocking_page = + new SafeBrowsingBlockingPage(sb_service, web_contents, resources); + blocking_page->Show(); + return; + } + + // Let's queue the interstitial. + // Note we only expect resources from the page at this point. + DCHECK(unsafe_resource.resource_type != ResourceType::MAIN_FRAME); + UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap(); + (*unsafe_resource_map)[web_contents].push_back(unsafe_resource); +} + +// static +bool SafeBrowsingBlockingPage::IsMainPage( + const UnsafeResourceList& unsafe_resources) { + return unsafe_resources.size() == 1 && + unsafe_resources[0].resource_type == ResourceType::MAIN_FRAME; } + diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h index 7b94290..8e3d1fd 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h @@ -17,27 +17,47 @@ // The blocking page forwards the result of the user's choice back to the // SafeBrowsingService so that we can cancel the request for the new page, or // or allow it to continue. +// +// A web page may contain several resources flagged as malware/phishing. This +// results into more than one interstitial being shown. On the first unsafe +// resource received we show an interstitial. Any subsequent unsafe resource +// notifications while the first interstitial is showing is queued. If the user +// decides to proceed in the first interstitial, we display all queued unsafe +// resources in a new interstitial. #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ +#include <map> +#include <vector> + #include "base/logging.h" #include "chrome/browser/tab_contents/interstitial_page.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "googleurl/src/gurl.h" +class DictionaryValue; class MessageLoop; -class TabContents; class NavigationController; +class WebContents; + class SafeBrowsingBlockingPage : public InterstitialPage { public: - SafeBrowsingBlockingPage(SafeBrowsingService* service, - const SafeBrowsingService::BlockingPageParam& param); virtual ~SafeBrowsingBlockingPage(); + // Shows a blocking page warning the user about phishing/malware for a + // specific resource. + // You can call this method several times, if an interstitial is already + // showing, the new one will be queued and displayed if the user decides + // to proceed on the currently showing interstitial. + static void ShowBlockingPage( + SafeBrowsingService* service, + const SafeBrowsingService::UnsafeResource& resource); + // InterstitialPage method: virtual std::string GetHTMLContents(); + virtual void Proceed(); virtual void DontProceed(); protected: @@ -45,34 +65,48 @@ class SafeBrowsingBlockingPage : public InterstitialPage { virtual void CommandReceived(const std::string& command); private: - // Tells the SafeBrowsingService that the handling of the current page is - // done. - void NotifyDone(); + typedef std::vector<SafeBrowsingService::UnsafeResource> UnsafeResourceList; + + // Don't instanciate this class directly, use ShowBlockingPage instead. + SafeBrowsingBlockingPage(SafeBrowsingService* service, + WebContents* web_contents, + const UnsafeResourceList& unsafe_resources); + + // Fills the passed dictionary with the strings passed to JS Template when + // creating the HTML. + void PopulateMultipleThreatStringDictionary(DictionaryValue* strings); + void PopulateMalwareStringDictionary(DictionaryValue* strings); + void PopulatePhishingStringDictionary(DictionaryValue* strings); + + // A helper method used by the Populate methods above used to populate common + // fields. + void PopulateStringDictionary(DictionaryValue* strings, + const std::wstring& title, + const std::wstring& headline, + const std::wstring& description1, + const std::wstring& description2, + const std::wstring& description3); + + + // A list of SafeBrowsingService::UnsafeResource for a tab that the user + // should be warned about. They are queued when displaying more than one + // interstitial at a time. + typedef std::map<WebContents*, UnsafeResourceList> UnsafeResourceMap; + static UnsafeResourceMap* GetUnsafeResourcesMap(); + + // Notifies the SafeBrowsingService on the IO thread whether to proceed or not + // for the |resources|. + static void NotifySafeBrowsingService(SafeBrowsingService* sb_service, + const UnsafeResourceList& resources, + bool proceed); + + // Returns true if the passed |unsafe_resources| is for the main page. + static bool IsMainPage(const UnsafeResourceList& unsafe_resources); private: // For reporting back user actions. SafeBrowsingService* sb_service_; - SafeBrowsingService::Client* client_; MessageLoop* report_loop_; - SafeBrowsingService::UrlCheckResult result_; - - // For determining which tab to block (note that we need this even though we - // have access to the tab as when the interstitial is showing, retrieving the - // tab RPH and RV id would return the ones of the interstitial, not the ones - // for the page containing the malware). - // TODO(jcampan): when we refactor the interstitial to run as a separate view - // that does not interact with the WebContents as much, we can - // get rid of these. - int render_process_host_id_; - int render_view_id_; - - // Inform the SafeBrowsingService whether we are continuing with this page - // load or going back to the previous page. - bool proceed_; - - // Whether we have notify the SafeBrowsingService yet that a decision had been - // made whether to proceed or block the unsafe resource. - bool did_notify_; // Whether the flagged resource is the main page (or a sub-resource is false). bool is_main_frame_; @@ -81,6 +115,9 @@ class SafeBrowsingBlockingPage : public InterstitialPage { // is invoked, -1 if not entry should be removed. int navigation_entry_index_to_remove_; + // The list of unsafe resources this page is warning about. + UnsafeResourceList unsafe_resources_; + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage); }; diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index 14f31bc..ba6701e 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc @@ -267,39 +267,37 @@ void SafeBrowsingService::DisplayBlockingPage(const GURL& url, } } - BlockingPageParam param; - param.url = url; - param.resource_type = resource_type; - param.result = result; - param.client = client; - param.render_process_host_id = render_process_host_id; - param.render_view_id = render_view_id; + UnsafeResource resource; + resource.url = url; + resource.resource_type = resource_type; + resource.threat_type= result; + resource.client = client; + resource.render_process_host_id = render_process_host_id; + resource.render_view_id = render_view_id; // The blocking page must be created from the UI thread. ui_loop->PostTask(FROM_HERE, NewRunnableMethod(this, &SafeBrowsingService::DoDisplayBlockingPage, - param)); + resource)); } // Invoked on the UI thread. void SafeBrowsingService::DoDisplayBlockingPage( - const BlockingPageParam& param) { + const UnsafeResource& resource) { // The tab might have been closed. - if (!tab_util::GetWebContentsByID(param.render_process_host_id, - param.render_view_id)) { + if (!tab_util::GetWebContentsByID(resource.render_process_host_id, + resource.render_view_id)) { // The tab is gone and we did not have a chance at showing the interstitial. // Just act as "Don't Proceed" was chosen. base::Thread* io_thread = g_browser_process->io_thread(); if (!io_thread) return; - BlockingPageParam response_param = param; - response_param.proceed = false; + std::vector<UnsafeResource> resources; + resources.push_back(resource); io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - this, &SafeBrowsingService::OnBlockingPageDone, response_param)); + this, &SafeBrowsingService::OnBlockingPageDone, resources, false)); return; } - SafeBrowsingBlockingPage* blocking_page = new SafeBrowsingBlockingPage(this, - param); - blocking_page->Show(); + SafeBrowsingBlockingPage::ShowBlockingPage(this, resource); } void SafeBrowsingService::CancelCheck(Client* client) { @@ -519,18 +517,24 @@ void SafeBrowsingService::DatabaseUpdateFinished(bool update_succeeded) { GetDatabase()->UpdateFinished(update_succeeded); } -void SafeBrowsingService::OnBlockingPageDone(const BlockingPageParam& param) { - NotifyClientBlockingComplete(param.client, param.proceed); - - if (param.proceed) { - // Whitelist this domain and warning type for the given tab. - WhiteListedEntry entry; - entry.render_process_host_id = param.render_process_host_id; - entry.render_view_id = param.render_view_id; - entry.domain = - net::RegistryControlledDomainService::GetDomainAndRegistry(param.url); - entry.result = param.result; - white_listed_entries_.push_back(entry); +void SafeBrowsingService::OnBlockingPageDone( + const std::vector<UnsafeResource>& resources, + bool proceed) { + for (std::vector<UnsafeResource>::const_iterator iter = resources.begin(); + iter != resources.end(); ++iter) { + const UnsafeResource& resource = *iter; + NotifyClientBlockingComplete(resource.client, proceed); + + if (proceed) { + // Whitelist this domain and warning type for the given tab. + WhiteListedEntry entry; + entry.render_process_host_id = resource.render_process_host_id; + entry.render_view_id = resource.render_view_id; + entry.domain = net::RegistryControlledDomainService::GetDomainAndRegistry( + resource.url); + entry.result = resource.threat_type; + white_listed_entries_.push_back(entry); + } } } diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index 1d5f229..0917ec9 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h @@ -57,14 +57,13 @@ class SafeBrowsingService // Structure used to pass parameters between the IO and UI thread when // interacting with the blocking page. - struct BlockingPageParam { + struct UnsafeResource { GURL url; - bool proceed; - UrlCheckResult result; + ResourceType::Type resource_type; + UrlCheckResult threat_type; Client* client; int render_process_host_id; int render_view_id; - ResourceType::Type resource_type; }; // Creates the safe browsing service. Need to initialize before using. @@ -142,7 +141,8 @@ class SafeBrowsingService void UpdateFinished(bool update_succeeded); // The blocking page on the UI thread has completed. - void OnBlockingPageDone(const BlockingPageParam& param); + void OnBlockingPageDone(const std::vector<UnsafeResource>& resources, + bool proceed); // Called when the SafeBrowsingProtocolManager has received updated MAC keys. void OnNewMacKeys(const std::string& client_key, @@ -242,7 +242,7 @@ class SafeBrowsingService void HandleResume(); // Invoked on the UI thread to show the blocking page. - void DoDisplayBlockingPage(const BlockingPageParam& param); + void DoDisplayBlockingPage(const UnsafeResource& resource); // During a reset or the initial load we may have to queue checks until the // database is ready. This method is run once the database has loaded (or if diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc index bc65504..942c126 100644 --- a/chrome/browser/tab_contents/interstitial_page.cc +++ b/chrome/browser/tab_contents/interstitial_page.cc @@ -21,11 +21,12 @@ namespace { class ResourceRequestTask : public Task { public: - ResourceRequestTask(RenderViewHost* render_view_host, + ResourceRequestTask(int process_id, + int render_view_host_id, ResourceRequestAction action) : action_(action), - process_id_(render_view_host->process()->host_id()), - render_view_host_id_(render_view_host->routing_id()), + process_id_(process_id), + render_view_host_id_(render_view_host_id), resource_dispatcher_host_( g_browser_process->resource_dispatcher_host()) { } @@ -72,7 +73,10 @@ InterstitialPage::InterstitialPage(WebContents* tab, action_taken_(false), enabled_(true), new_navigation_(new_navigation), + original_rvh_process_id_(tab->render_view_host()->process()->host_id()), + original_rvh_id_(tab->render_view_host()->routing_id()), render_view_host_(NULL), + resource_dispatcher_host_notified_(false), should_revert_tab_title_(false), ui_loop_(MessageLoop::current()) { InitInterstitialPageMap(); @@ -157,16 +161,26 @@ void InterstitialPage::Observe(NotificationType type, const NotificationDetails& details) { switch (type) { case NOTIFY_NAV_ENTRY_PENDING: - // We are navigating away from the interstitial. Make sure clicking on - // the interstitial will have no effect. + // We are navigating away from the interstitial (the user has typed a URL + // in the location bar or clicked a bookmark). Make sure clicking on the + // interstitial will have no effect. Also cancel any blocked requests + // on the ResourceDispatcherHost. Note that when we get this notification + // the RenderViewHost has not yet navigated so we'll unblock the + // RenderViewHost before the resource request for the new page we are + // navigating arrives in the ResourceDispatcherHost. This ensures that + // request won't be blocked if the same RenderViewHost was used for the + // new navigation. Disable(); + DCHECK(!resource_dispatcher_host_notified_); + TakeActionOnResourceDispatcher(CANCEL); break; case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: if (!action_taken_) { // The RenderViewHost is being destroyed (as part of the tab being // closed), make sure we clear the blocked requests. - DCHECK(Source<RenderViewHost>(source).ptr() == - tab_->render_view_host()); + RenderViewHost* rvh = Source<RenderViewHost>(source).ptr(); + DCHECK(rvh->process()->host_id() == original_rvh_process_id_ && + rvh->routing_id() == original_rvh_id_); TakeActionOnResourceDispatcher(CANCEL); } break; @@ -210,7 +224,10 @@ RenderViewHost* InterstitialPage::CreateRenderViewHost() { } void InterstitialPage::Proceed() { - DCHECK(!action_taken_); + if (action_taken_) { + NOTREACHED(); + return; + } Disable(); action_taken_ = true; @@ -235,7 +252,10 @@ void InterstitialPage::Proceed() { } void InterstitialPage::DontProceed() { - DCHECK(!action_taken_); + if (action_taken_) { + NOTREACHED(); + return; + } Disable(); action_taken_ = true; @@ -326,14 +346,25 @@ void InterstitialPage::TakeActionOnResourceDispatcher( ResourceRequestAction action) { DCHECK(MessageLoop::current() == ui_loop_) << "TakeActionOnResourceDispatcher should be called on the main thread."; + + if (action == CANCEL || action == RESUME) { + if (resource_dispatcher_host_notified_) + return; + resource_dispatcher_host_notified_ = true; + } + // The tab might not have a render_view_host if it was closed (in which case, // we have taken care of the blocked requests when processing // NOTIFY_RENDER_WIDGET_HOST_DESTROYED. // Also we need to test there is an IO thread, as when unit-tests we don't // have one. - if (tab_->render_view_host() && g_browser_process->io_thread()) { + RenderViewHost* rvh = RenderViewHost::FromID(original_rvh_process_id_, + original_rvh_id_); + if (rvh && g_browser_process->io_thread()) { g_browser_process->io_thread()->message_loop()->PostTask( - FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action)); + FROM_HERE, new ResourceRequestTask(original_rvh_process_id_, + original_rvh_id_, + action)); } } @@ -354,3 +385,4 @@ InterstitialPage* InterstitialPage::GetInterstitialPage( return iter->second; } + diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h index 755ec65..eb18b60 100644 --- a/chrome/browser/tab_contents/interstitial_page.h +++ b/chrome/browser/tab_contents/interstitial_page.h @@ -150,10 +150,18 @@ class InterstitialPage : public NotificationObserver, // The RenderViewHost displaying the interstitial contents. RenderViewHost* render_view_host_; + // The IDs for the RenderViewHost hidden by this interstitial. + int original_rvh_process_id_; + int original_rvh_id_; + // Whether or not we should change the title of the tab when hidden (to revert // it to its original value). bool should_revert_tab_title_; + // Whether the ResourceDispatcherHost has been notified to cancel/resume the + // resource requests blocked for the RenderViewHost. + bool resource_dispatcher_host_notified_; + // The original title of the tab that should be reverted to when the // interstitial is hidden. std::wstring original_tab_title_; |