summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_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.cc361
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_));
+}