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/ssl_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/ssl_blocking_page.cc')
-rw-r--r-- | chrome/browser/ssl_blocking_page.cc | 316 |
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""); + } +} |