Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Unified Diff: chrome/browser/ui/login/login_prompt.cc

Issue 403933002: Set SSL info when an HTTP auth dialog is triggered by direct navigation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Set SSL status for all HTTP basic auth prompts Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/login/login_prompt.cc
diff --git a/chrome/browser/ui/login/login_prompt.cc b/chrome/browser/ui/login/login_prompt.cc
index 53f68a7b4a8f518502bdf7c005e1aaa274b15769..3585140168b45706fd7f647ba939e7b08b9732b9 100644
--- a/chrome/browser/ui/login/login_prompt.cc
+++ b/chrome/browser/ui/login/login_prompt.cc
@@ -13,22 +13,33 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/prerender/prerender_contents.h"
+#include "chrome/browser/ssl/ssl_error_info.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/login/login_interstitial_delegate.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cert_store.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_request_info.h"
+#include "content/public/browser/signed_certificate_timestamp_store.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/security_style.h"
+#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
+#include "content/public/common/ssl_status.h"
#include "grit/generated_resources.h"
#include "net/base/auth.h"
#include "net/base/load_flags.h"
#include "net/base/net_util.h"
#include "net/http/http_transaction_factory.h"
+#include "net/ssl/ssl_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "ui/base/l10n/l10n_util.h"
@@ -45,6 +56,27 @@ using content::WebContents;
class LoginHandlerImpl;
+namespace {
+// TODO(meacer): This is the same as
+// ResourceLoader::StoreSignedCertificateTimestamps. Can't include
+// resource_loader.h so it's copied here. Remove duplication.
+void StoreSignedCertificateTimestamps(
+ const net::SignedCertificateTimestampAndStatusList& sct_list,
+ int process_id,
+ content::SignedCertificateTimestampIDStatusList* sct_ids) {
+ content::SignedCertificateTimestampStore* sct_store(
+ content::SignedCertificateTimestampStore::GetInstance());
+
+ for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
+ sct_list.begin(); iter != sct_list.end(); ++iter) {
+ const int sct_id(sct_store->Store(iter->sct, process_id));
+ sct_ids->push_back(
+ content::SignedCertificateTimestampIDAndStatus(sct_id, iter->status));
+ }
+}
+
+} // namespace
+
// Helper to remove the ref from an net::URLRequest to the LoginHandler.
// Should only be called from the IO thread, since it accesses an
// net::URLRequest.
@@ -489,6 +521,65 @@ void ShowLoginPrompt(const GURL& request_url,
handler->BuildViewForPasswordManager(password_manager, explanation);
}
+// static
+void LoginHandler::UpdateSSLState(content::NavigationEntry* entry,
+ content::WebContents* web_contents,
+ const net::SSLInfo& ssl_info) {
+ // Login prompts are displayed before the provisional navigation entry
+ // is committed so SSL information isn't yet set. Override it here.
+ content::SSLStatus original_ssl_status = entry->GetSSL(); // Copy.
+
+ if (entry->GetSSL().security_style != content::SECURITY_STYLE_UNKNOWN)
+ return;
+ entry->GetSSL().cert_status = ssl_info.cert_status;
+ entry->GetSSL().security_bits = ssl_info.security_bits;
+ entry->GetSSL().connection_status = ssl_info.connection_status;
+
+ int render_process_host_id = web_contents->GetRenderProcessHost()->GetID();
+ // Storing an existing cert does nothing and just returns the existing id.
+ int cert_id = content::CertStore::GetInstance()->StoreCert(
+ ssl_info.cert.get(), render_process_host_id);
+ DCHECK(cert_id);
+ entry->GetSSL().cert_id = cert_id;
+
+ content::SignedCertificateTimestampIDStatusList
+ signed_certificate_timestamp_ids;
+ StoreSignedCertificateTimestamps(
+ ssl_info.signed_certificate_timestamps,
+ render_process_host_id,
+ &signed_certificate_timestamp_ids);
+ entry->GetSSL().signed_certificate_timestamp_ids =
+ signed_certificate_timestamp_ids;
+
+ // The rest is a subset of the logic from SSLPolicy::UpdateEntry.
+ // Since login prompts display before the page is shown, there is no need to
+ // check for mixed content. In any case, the SSL information will be fully
+ // updated once the navigation is committed.
+ // TODO(meacer): Reuse the code from ssl_policy.cc here. Can't link against
+ // it from ui code.
+ entry->GetSSL().security_style =
+ entry->GetURL().SchemeIsSecure() ?
+ content::SECURITY_STYLE_AUTHENTICATED :
+ content::SECURITY_STYLE_UNAUTHENTICATED;
+ // An HTTPS response may not have a certificate for some reason. When that
+ // happens, use the unauthenticated (HTTP) rather than the authentication
+ // broken security style so that we can detect this error condition.
+ if (!entry->GetSSL().cert_id) {
+ entry->GetSSL().security_style = content::SECURITY_STYLE_UNAUTHENTICATED;
+ return;
+ }
+ if (net::IsCertStatusError(entry->GetSSL().cert_status)) {
+ // Minor errors don't lower the security style to
+ // SECURITY_STYLE_AUTHENTICATION_BROKEN.
+ if (!net::IsCertStatusMinorError(entry->GetSSL().cert_status)) {
+ entry->GetSSL().security_style =
+ content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
+ }
+ }
+ if (!entry->GetSSL().Equals(original_ssl_status))
+ web_contents->GetDelegate()->VisibleSSLStateChanged(web_contents);
+}
+
// This callback is run on the UI thread and creates a constrained window with
// a LoginView to prompt the user. If the prompt is triggered because of
// a cross origin navigation in the main frame, a blank interstitial is first
@@ -498,7 +589,8 @@ void ShowLoginPrompt(const GURL& request_url,
void LoginDialogCallback(const GURL& request_url,
net::AuthChallengeInfo* auth_info,
LoginHandler* handler,
- bool is_main_frame) {
+ bool is_main_frame,
+ const net::SSLInfo& ssl_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
WebContents* parent_contents = handler->GetWebContentsForLogin();
if (!parent_contents || handler->WasAuthHandled()) {
@@ -508,6 +600,14 @@ void LoginDialogCallback(const GURL& request_url,
handler->CancelAuth();
return;
}
+ if (is_main_frame) {
+ // Update SSL state for all main frame navigations. For cross origin
+ // navigations, LoginInterstitialDelegate creates a new navigation entry
+ // and updates the SSL state itself.
+ NavigationController* controller = &parent_contents->GetController();
+ content::NavigationEntry* entry = controller->GetVisibleEntry();
+ LoginHandler::UpdateSSLState(entry, parent_contents, ssl_info);
+ }
if (is_main_frame &&
parent_contents->GetVisibleURL().GetOrigin() != request_url.GetOrigin()) {
@@ -517,10 +617,12 @@ void LoginDialogCallback(const GURL& request_url,
request_url,
make_scoped_refptr(auth_info),
make_scoped_refptr(handler));
+
// This is owned by the interstitial it creates.
new LoginInterstitialDelegate(parent_contents,
request_url,
- callback);
+ callback,
+ ssl_info);
} else {
ShowLoginPrompt(request_url,
auth_info,
@@ -535,10 +637,12 @@ LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
net::URLRequest* request) {
bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0;
LoginHandler* handler = LoginHandler::Create(auth_info, request);
+ const net::SSLInfo& ssl_info = request->response_info().ssl_info;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&LoginDialogCallback, request->url(),
make_scoped_refptr(auth_info), make_scoped_refptr(handler),
- is_main_frame));
+ is_main_frame,
+ ssl_info));
return handler;
}

Powered by Google App Engine
This is Rietveld 408576698