diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/safe_browsing/safe_browsing_blocking_page.cc | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing/safe_browsing_blocking_page.cc')
-rw-r--r-- | chrome/browser/safe_browsing/safe_browsing_blocking_page.cc | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc new file mode 100644 index 0000000..ec6f671 --- /dev/null +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc @@ -0,0 +1,361 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Implementation of the SafeBrowsingBlockingPage class. + +#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" + +#include "chrome/app/locales/locale_settings.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_resources.h" +#include "chrome/browser/dom_operation_notification_details.h" +#include "chrome/browser/google_util.h" +#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/tab_util.h" +#include "chrome/browser/web_contents.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/resource_bundle.h" +#include "generated_resources.h" +#include "net/base/escape.h" + + +// For malware interstitial pages, we link the problematic URL to Google's +// diagnostic page. +// TODO(paulg): Change 'googleclient' to a proper client name before launch. +static const char* const kSbDiagnosticUrl = + "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=googleclient"; + +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;\">%s</a>"; + +// Created on the io_thread. +SafeBrowsingBlockingPage::SafeBrowsingBlockingPage( + SafeBrowsingService* sb_service, + SafeBrowsingService::Client* client, + int render_process_host_id, + int render_view_id, + const GURL& url, + ResourceType::Type resource_type, + SafeBrowsingService::UrlCheckResult result) + : sb_service_(sb_service), + client_(client), + render_process_host_id_(render_process_host_id), + render_view_id_(render_view_id), + url_(url), + result_(result), + proceed_(false), + tab_(NULL), + controller_(NULL), + delete_pending_(false), + is_main_frame_(resource_type == ResourceType::MAIN_FRAME), + created_temporary_entry_(false) { +} + +// Deleted on the io_thread. +SafeBrowsingBlockingPage::~SafeBrowsingBlockingPage() { +} + +void SafeBrowsingBlockingPage::DisplayBlockingPage() { + TabContents* tab = tab_util::GetTabContentsByID(render_process_host_id_, + render_view_id_); + if (!tab || tab->type() != TAB_CONTENTS_WEB) { + NotifyDone(); + return; + } + + tab_ = tab; + controller_ = tab->controller(); + + // Register for notifications of events from this tab. + NotificationService* ns = NotificationService::current(); + DCHECK(ns); + ns->AddObserver(this, NOTIFY_TAB_CLOSING, + Source<NavigationController>(controller_)); + ns->AddObserver(this, NOTIFY_DOM_OPERATION_RESPONSE, + Source<TabContents>(tab_)); + + // Hold an extra reference to ourself until the interstitial is gone. + AddRef(); + + WebContents* web_contents = tab->AsWebContents(); + + // Load the HTML page and create the template components. + DictionaryValue strings; + 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. + GURL top_url = tab_->GetURL(); + if (top_url == url_) { + 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(top_url.host()), + UTF8ToWide(url_.host()))); + strings.SetString(L"description2", + l10n_util::GetStringF(IDS_SAFE_BROWSING_MALWARE_DESCRIPTION5, + link, + UTF8ToWide(url_.host()))); + } + + 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"); + html = rb.GetDataResource(IDR_SAFE_BROWSING_MALWARE_BLOCK); + } else { + 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"); + html = rb.GetDataResource(IDR_SAFE_BROWSING_PHISHING_BLOCK); + } + + std::string html_page(jstemplate_builder::GetTemplateHtml(html, + &strings, + "template_root")); + + // If the malware is the actual main frame and we have no pending entry + // (typically the navigation was initiated by the page), we create a fake + // navigation entry (so the location bar shows the page's URL). + if (is_main_frame_ && tab_->controller()->GetPendingEntryIndex() == -1) { + // New navigation. + NavigationEntry* nav_entry = new NavigationEntry(TAB_CONTENTS_WEB); + + // We set the page ID to max page id so to ensure the controller considers + // this dummy entry a new one. Because we'll remove the entry when the + // interstitial is going away, it will not conflict with any future + // navigations. + nav_entry->SetPageID(tab_->GetMaxPageID() + 1); + nav_entry->SetPageType(NavigationEntry::INTERSTITIAL_PAGE); + nav_entry->SetURL(url_); + tab_->controller()->DidNavigateToEntry(nav_entry); + created_temporary_entry_ = true; + } + + // Show the interstitial page. + web_contents->ShowInterstitialPage(html_page, this); +} + +void SafeBrowsingBlockingPage::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type) { + case NOTIFY_TAB_CLOSING: + HandleClose(); + break; + case NOTIFY_DOM_OPERATION_RESPONSE: + Continue(Details<DomOperationNotificationDetails>(details)->json()); + break; + default: + NOTREACHED(); + } +} + +void SafeBrowsingBlockingPage::InterstitialClosed() { + HandleClose(); +} + +bool SafeBrowsingBlockingPage::GoBack() { + WebContents* web_contents = tab_->AsWebContents(); + NavigationEntry* prev_entry = + web_contents->controller()->GetEntryAtOffset(-1); + + if (!prev_entry) { + // Nothing to go to, default to about:blank. Navigating will cause the + // interstitial to hide which will trigger "this" to be deleted. + tab_->controller()->LoadURL(GURL("about:blank"), + PageTransition::AUTO_BOOKMARK); + } else if (prev_entry->GetType() != TAB_CONTENTS_WEB || + prev_entry->restored() || + !is_main_frame_) { + // We do navigate back if any of these is true: + // - the page is not a WebContents, its TabContents might have to be + // recreated. + // - we have not yet visited that navigation entry (typically session + // restore), in which case the page is not already available. + // - the interstitial was triggered by a sub-resource. In that case we + // really need to navigate, just hiding the interstitial would show the + // page containing the bad resource, and we don't want that. + web_contents->controller()->GoBack(); + } else { + // Otherwise, the user was viewing a page and navigated to a URL that was + // interrupted by an interstitial. Thus, we can just hide the interstitial + // and show the page the user was on before. + web_contents->HideInterstitialPage(false, false); + } + + // WARNING: at this point we are now either deleted or pending deletion from + // the IO thread. + + // Remove the navigation entry for the malware page. Note that we always + // remove the entry even if we did not create it as it has been flagged as + // malware and we don't want the user navigating back to it. + web_contents->controller()->RemoveLastEntry(); + + return true; +} + +void SafeBrowsingBlockingPage::Continue(const std::string& user_action) { + TabContents* tab = tab_util::GetTabContentsByID(render_process_host_id_, + render_view_id_); + DCHECK(tab); + WebContents* web = tab->AsWebContents(); + if (user_action == "2") { + // User pressed "Learn more". + GURL url; + if (result_ == SafeBrowsingService::URL_MALWARE) { + url = GURL(l10n_util::GetString(IDS_LEARN_MORE_MALWARE_URL)); + } else if (result_ == SafeBrowsingService::URL_PHISHING) { + url = GURL(l10n_util::GetString(IDS_LEARN_MORE_PHISHING_URL)); + } else { + NOTREACHED(); + } + web->OpenURL(url, CURRENT_TAB, PageTransition::LINK); + return; + } + if (user_action == "3") { + // 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); + GURL report_url = + safe_browsing_util::GeneratePhishingReportUrl(kSbReportPhishingUrl, + url_.spec()); + web->OpenURL(report_url, CURRENT_TAB, PageTransition::LINK); + return; + } + if (user_action == "4") { + // We're going to take the user to Google's SafeBrowsing diagnostic page. + std::string diagnostic = + StringPrintf(kSbDiagnosticUrl, + EscapeQueryParamValue(url_.spec()).c_str()); + GURL diagnostic_url(diagnostic); + diagnostic_url = google_util::AppendGoogleLocaleParam(diagnostic_url); + DCHECK(result_ == SafeBrowsingService::URL_MALWARE); + web->OpenURL(diagnostic_url, CURRENT_TAB, PageTransition::LINK); + return; + } + + proceed_ = user_action == "1"; + + if (proceed_) { + // We are continuing, if we have created a temporary navigation entry, + // delete it as a new will be created on navigation. + if (created_temporary_entry_) + web->controller()->RemoveLastEntry(); + if (is_main_frame_) + web->HideInterstitialPage(true, true); + else + web->HideInterstitialPage(false, false); + } else { + GoBack(); + } + + NotifyDone(); +} + +void SafeBrowsingBlockingPage::HandleClose() { + NotificationService* ns = NotificationService::current(); + DCHECK(ns); + ns->RemoveObserver(this, NOTIFY_TAB_CLOSING, + Source<NavigationController>(controller_)); + ns->RemoveObserver(this, NOTIFY_DOM_OPERATION_RESPONSE, + Source<TabContents>(tab_)); + + NotifyDone(); + Release(); +} + +void SafeBrowsingBlockingPage::NotifyDone() { + if (delete_pending_) + return; + + delete_pending_ = true; + + if (tab_ && tab_->AsWebContents()) { + // Ensure the WebContents does not keep a pointer to us. + tab_->AsWebContents()->set_interstitial_delegate(NULL); + } + + Thread* io_thread = g_browser_process->io_thread(); + if (!io_thread) + return; + + io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( + sb_service_, + &SafeBrowsingService::OnBlockingPageDone, + this, client_, proceed_)); +} |