summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ssl_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/ssl_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/ssl_blocking_page.cc')
-rw-r--r--chrome/browser/ssl_blocking_page.cc316
1 files changed, 316 insertions, 0 deletions
diff --git a/chrome/browser/ssl_blocking_page.cc b/chrome/browser/ssl_blocking_page.cc
new file mode 100644
index 0000000..cb5d3ac
--- /dev/null
+++ b/chrome/browser/ssl_blocking_page.cc
@@ -0,0 +1,316 @@
+// 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.
+
+#include "chrome/browser/ssl_blocking_page.h"
+
+#include "base/string_piece.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_resources.h"
+#include "chrome/browser/cert_store.h"
+#include "chrome/browser/dom_operation_notification_details.h"
+#include "chrome/browser/navigation_controller.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/render_view_host.h"
+#include "chrome/browser/ssl_error_info.h"
+#include "chrome/browser/tab_contents.h"
+#include "chrome/browser/web_contents.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/common/resource_bundle.h"
+
+#include "generated_resources.h"
+
+// static
+SSLBlockingPage::SSLBlockingPageMap*
+ SSLBlockingPage::tab_to_blocking_page_ = NULL;
+
+SSLBlockingPage::SSLBlockingPage(SSLManager::CertError* error,
+ Delegate* delegate)
+ : error_(error),
+ delegate_(delegate),
+ delegate_has_been_notified_(false),
+ remove_last_entry_(true),
+ created_nav_entry_(false) {
+ InitSSLBlockingPageMap();
+ // Remember the tab, because we might not be able to get to it later
+ // via the error.
+ tab_ = error->GetTabContents();
+ DCHECK(tab_);
+
+ // If there's already an interstitial in this tab, then we're about to
+ // replace it. We should be ok with just deleting the previous
+ // SSLBlockingPage (not hiding it first), since we're about to be shown.
+ SSLBlockingPageMap::const_iterator iter = tab_to_blocking_page_->find(tab_);
+ if (iter != tab_to_blocking_page_->end()) {
+ // Deleting the SSLBlockingPage will also remove it from the map.
+ delete iter->second;
+
+ // Since WebContents::InterstitialPageGone won't be called, we need
+ // to clear the last NavigationEntry manually.
+ tab_->controller()->RemoveLastEntry();
+ }
+ (*tab_to_blocking_page_)[tab_] = this;
+
+ // Register notifications so we can delete ourself if the tab is closed.
+ NotificationService::current()->AddObserver(this,
+ NOTIFY_TAB_CLOSING,
+ Source<NavigationController>(tab_->controller()));
+
+ NotificationService::current()->AddObserver(this,
+ NOTIFY_INTERSTITIAL_PAGE_CLOSED,
+ Source<TabContents>(tab_));
+
+ // Register for DOM operations, this is how the blocking page notifies us of
+ // what the user chooses.
+ NotificationService::current()->AddObserver(this,
+ NOTIFY_DOM_OPERATION_RESPONSE,
+ Source<TabContents>(tab_));
+}
+
+SSLBlockingPage::~SSLBlockingPage() {
+ NotificationService::current()->RemoveObserver(this,
+ NOTIFY_TAB_CLOSING,
+ Source<NavigationController>(tab_->controller()));
+
+ NotificationService::current()->RemoveObserver(this,
+ NOTIFY_INTERSTITIAL_PAGE_CLOSED,
+ Source<TabContents>(tab_));
+
+ NotificationService::current()->RemoveObserver(this,
+ NOTIFY_DOM_OPERATION_RESPONSE,
+ Source<TabContents>(tab_));
+
+ SSLBlockingPageMap::iterator iter =
+ tab_to_blocking_page_->find(tab_);
+ DCHECK(iter != tab_to_blocking_page_->end());
+ tab_to_blocking_page_->erase(iter);
+
+ if (!delegate_has_been_notified_) {
+ // The page is closed without the user having chosen what to do, default to
+ // deny.
+ NotifyDenyCertificate();
+ }
+}
+
+void SSLBlockingPage::Show() {
+ // Let's build the html error page.
+ DictionaryValue strings;
+ SSLErrorInfo error_info = delegate_->GetSSLErrorInfo(error_);
+ strings.SetString(L"title",
+ l10n_util::GetString(IDS_SSL_BLOCKING_PAGE_TITLE));
+ strings.SetString(L"headLine", error_info.title());
+ strings.SetString(L"description", error_info.details());
+
+ strings.SetString(L"moreInfoTitle",
+ l10n_util::GetString(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
+ SetExtraInfo(&strings, error_info.extra_information());
+
+ strings.SetString(L"proceed",
+ l10n_util::GetString(IDS_SSL_BLOCKING_PAGE_PROCEED));
+ strings.SetString(L"exit",
+ l10n_util::GetString(IDS_SSL_BLOCKING_PAGE_EXIT));
+
+ strings.SetString(L"textdirection",
+ (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
+ L"rtl" : L"ltr");
+
+ static const StringPiece html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_SSL_ROAD_BLOCK_HTML));
+
+ std::string html_text(jstemplate_builder::GetTemplateHtml(html,
+ &strings,
+ "template_root"));
+
+ DCHECK(tab_->type() == TAB_CONTENTS_WEB);
+ WebContents* tab = tab_->AsWebContents();
+ const net::SSLInfo& ssl_info = error_->ssl_info();
+ int cert_id = CertStore::GetSharedInstance()->StoreCert(
+ ssl_info.cert, tab->render_view_host()->process()->host_id());
+
+ NavigationEntry* nav_entry = new NavigationEntry(TAB_CONTENTS_WEB);
+ if (tab_->controller()->GetPendingEntryIndex() == -1) {
+ // New navigation.
+ // 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.
+ created_nav_entry_ = true;
+ nav_entry->SetPageID(tab_->GetMaxPageID() + 1);
+ nav_entry->SetURL(error_->request_url());
+ } else {
+ // Make sure to update the current entry ssl state to reflect the error.
+ *nav_entry = *(tab_->controller()->GetPendingEntry());
+ }
+ nav_entry->SetPageType(NavigationEntry::INTERSTITIAL_PAGE);
+ nav_entry->SetSecurityStyle(SECURITY_STYLE_AUTHENTICATION_BROKEN);
+ nav_entry->SetSSLCertID(cert_id);
+ nav_entry->SetSSLCertStatus(ssl_info.cert_status);
+ nav_entry->SetSSLSecurityBits(ssl_info.security_bits);
+ // The controller will own the entry.
+ int page_id = nav_entry->GetPageID();
+ tab_->controller()->DidNavigateToEntry(nav_entry);
+ tab_->controller()->SyncSessionWithEntryByPageID(TAB_CONTENTS_WEB,
+ NULL,
+ page_id);
+ tab->ShowInterstitialPage(html_text, NULL);
+}
+
+void SSLBlockingPage::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type) {
+ case NOTIFY_TAB_CLOSING:
+ case NOTIFY_INTERSTITIAL_PAGE_CLOSED: {
+ // We created a navigation entry for the interstitial, remove it.
+ // Note that we don't remove the entry if we are closing all tabs so that
+ // the last entry is kept for the restoring on next start-up.
+ Browser* browser = Browser::GetBrowserForController(tab_->controller(),
+ NULL);
+ if (remove_last_entry_ &&
+ !browser->tabstrip_model()->closing_all()) {
+ tab_->controller()->RemoveLastEntry();
+ }
+ delete this;
+ break;
+ }
+ case NOTIFY_DOM_OPERATION_RESPONSE: {
+ std::string json =
+ Details<DomOperationNotificationDetails>(details)->json();
+ if (json == "1") {
+ Proceed();
+ } else {
+ DontProceed();
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+void SSLBlockingPage::Proceed() {
+ // We hide the interstitial page first as allowing the certificate will
+ // resume the request and we want the WebContents back to showing the
+ // non interstitial page (otherwise the request completion messages may
+ // confuse the WebContents if it is still showing the interstitial
+ // page).
+ DCHECK(tab_->type() == TAB_CONTENTS_WEB);
+ tab_->AsWebContents()->HideInterstitialPage(true, true);
+
+ // Accepting the certificate resumes the loading of the page.
+ NotifyAllowCertificate();
+
+ // Do not remove the navigation entry if we have not created it explicitly
+ // as in such cases (session restore) the controller would not create a new
+ // entry on navigation since the page id is less than max page id.
+ if (!created_nav_entry_)
+ remove_last_entry_ = false;
+}
+
+void SSLBlockingPage::DontProceed() {
+ NotifyDenyCertificate();
+
+ // We are navigating, remove the current entry before we mess with it.
+ remove_last_entry_ = false;
+ tab_->controller()->RemoveLastEntry();
+
+ NavigationEntry* entry = tab_->controller()->GetActiveEntry();
+ if (!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 (entry->GetType() != TAB_CONTENTS_WEB) {
+ // Not a WebContent, reload it so to recreate the TabContents for it.
+ tab_->controller()->Reload();
+ } else {
+ DCHECK(tab_->type() == TAB_CONTENTS_WEB);
+ if (entry->restored()) {
+ // If this page was restored, it is not available, we have to navigate to
+ // it.
+ tab_->controller()->GoToOffset(0);
+ } else {
+ tab_->AsWebContents()->HideInterstitialPage(false, false);
+ }
+ }
+ // WARNING: we are now deleted!
+}
+
+// static
+void SSLBlockingPage::InitSSLBlockingPageMap() {
+ if (!tab_to_blocking_page_)
+ tab_to_blocking_page_ = new SSLBlockingPageMap;
+}
+
+void SSLBlockingPage::NotifyDenyCertificate() {
+ DCHECK(!delegate_has_been_notified_);
+
+ delegate_->OnDenyCertificate(error_);
+ delegate_has_been_notified_ = true;
+}
+
+void SSLBlockingPage::NotifyAllowCertificate() {
+ DCHECK(!delegate_has_been_notified_);
+
+ delegate_->OnAllowCertificate(error_);
+ delegate_has_been_notified_ = true;
+}
+
+// static
+SSLBlockingPage* SSLBlockingPage::GetSSLBlockingPage(
+ TabContents* tab_contents) {
+ InitSSLBlockingPageMap();
+ SSLBlockingPageMap::const_iterator iter =
+ tab_to_blocking_page_->find(tab_contents);
+ if (iter == tab_to_blocking_page_->end())
+ return NULL;
+
+ return iter->second;
+}
+
+// static
+void SSLBlockingPage::SetExtraInfo(
+ DictionaryValue* strings,
+ const std::vector<std::wstring>& extra_info) {
+ DCHECK(extra_info.size() < 5); // We allow 5 paragraphs max.
+ const std::wstring keys[5] = {
+ L"moreInfo1", L"moreInfo2", L"moreInfo3", L"moreInfo4", L"moreInfo5"
+ };
+ int i;
+ for (i = 0; i < static_cast<int>(extra_info.size()); i++) {
+ strings->SetString(keys[i], extra_info[i]);
+ }
+ for (;i < 5; i++) {
+ strings->SetString(keys[i], L"");
+ }
+}