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

Side by Side Diff: content/browser/ssl/ssl_manager.cc

Issue 2408393003: Manage insecure content flags in SSLManager, not WebContentsImpl (Closed)
Patch Set: fix test failure Created 4 years, 2 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 unified diff | Download patch
« no previous file with comments | « content/browser/ssl/ssl_manager.h ('k') | content/browser/web_contents/web_contents_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/ssl/ssl_manager.h" 5 #include "content/browser/ssl/ssl_manager.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/metrics/histogram_macros.h" 11 #include "base/metrics/histogram_macros.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/supports_user_data.h" 13 #include "base/supports_user_data.h"
14 #include "content/browser/frame_host/navigation_entry_impl.h" 14 #include "content/browser/frame_host/navigation_entry_impl.h"
15 #include "content/browser/loader/resource_dispatcher_host_impl.h" 15 #include "content/browser/loader/resource_dispatcher_host_impl.h"
16 #include "content/browser/loader/resource_request_info_impl.h" 16 #include "content/browser/loader/resource_request_info_impl.h"
17 #include "content/browser/ssl/ssl_error_handler.h" 17 #include "content/browser/ssl/ssl_error_handler.h"
18 #include "content/browser/web_contents/web_contents_impl.h" 18 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/public/browser/browser_context.h" 19 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/certificate_request_result_type.h" 21 #include "content/public/browser/certificate_request_result_type.h"
22 #include "content/public/browser/content_browser_client.h" 22 #include "content/public/browser/content_browser_client.h"
23 #include "content/public/browser/navigation_details.h" 23 #include "content/public/browser/navigation_details.h"
24 #include "content/public/browser/ssl_host_state_delegate.h" 24 #include "content/public/browser/ssl_host_state_delegate.h"
25 #include "content/public/browser/ssl_status.h"
26 #include "net/url_request/url_request.h" 25 #include "net/url_request/url_request.h"
27 26
28 namespace content { 27 namespace content {
29 28
30 namespace { 29 namespace {
31 30
32 const char kSSLManagerKeyName[] = "content_ssl_manager"; 31 const char kSSLManagerKeyName[] = "content_ssl_manager";
33 32
34 // Events for UMA. Do not reorder or change! 33 // Events for UMA. Do not reorder or change!
35 enum SSLGoodCertSeenEvent { 34 enum SSLGoodCertSeenEvent {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 int render_process_id, 143 int render_process_id,
145 int render_frame_id, 144 int render_frame_id,
146 const net::SSLInfo& ssl_info, 145 const net::SSLInfo& ssl_info,
147 bool fatal) { 146 bool fatal) {
148 OnSSLCertificateError(delegate, RESOURCE_TYPE_SUB_RESOURCE, url, 147 OnSSLCertificateError(delegate, RESOURCE_TYPE_SUB_RESOURCE, url,
149 base::Bind(&WebContentsImpl::FromRenderFrameHostID, 148 base::Bind(&WebContentsImpl::FromRenderFrameHostID,
150 render_process_id, render_frame_id), 149 render_process_id, render_frame_id),
151 ssl_info, fatal); 150 ssl_info, fatal);
152 } 151 }
153 152
154 // static
155 void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
156 SSLManagerSet* managers = static_cast<SSLManagerSet*>(
157 context->GetUserData(kSSLManagerKeyName));
158
159 for (std::set<SSLManager*>::iterator i = managers->get().begin();
160 i != managers->get().end(); ++i) {
161 (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry());
162 }
163 }
164
165 SSLManager::SSLManager(NavigationControllerImpl* controller) 153 SSLManager::SSLManager(NavigationControllerImpl* controller)
166 : controller_(controller), 154 : controller_(controller),
167 ssl_host_state_delegate_( 155 ssl_host_state_delegate_(
168 controller->GetBrowserContext()->GetSSLHostStateDelegate()) { 156 controller->GetBrowserContext()->GetSSLHostStateDelegate()) {
169 DCHECK(controller_); 157 DCHECK(controller_);
170 158
171 SSLManagerSet* managers = static_cast<SSLManagerSet*>( 159 SSLManagerSet* managers = static_cast<SSLManagerSet*>(
172 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); 160 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName));
173 if (!managers) { 161 if (!managers) {
174 managers = new SSLManagerSet; 162 managers = new SSLManagerSet;
175 controller_->GetBrowserContext()->SetUserData(kSSLManagerKeyName, managers); 163 controller_->GetBrowserContext()->SetUserData(kSSLManagerKeyName, managers);
176 } 164 }
177 managers->get().insert(this); 165 managers->get().insert(this);
178 } 166 }
179 167
180 SSLManager::~SSLManager() { 168 SSLManager::~SSLManager() {
181 SSLManagerSet* managers = static_cast<SSLManagerSet*>( 169 SSLManagerSet* managers = static_cast<SSLManagerSet*>(
182 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); 170 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName));
183 managers->get().erase(this); 171 managers->get().erase(this);
184 } 172 }
185 173
186 void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) { 174 void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
187 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); 175 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
188 UpdateEntry(entry); 176 int content_status_flags = 0;
177 if (!details.is_main_frame) {
178 // If it wasn't a main-frame navigation, then carry over content
179 // status flags. (For example, the mixed content flag shouldn't
180 // clear because of a frame navigation.)
181 NavigationEntryImpl* previous_entry =
182 controller_->GetEntryAtIndex(details.previous_entry_index);
183 if (previous_entry) {
184 content_status_flags = previous_entry->GetSSL().content_status;
185 }
186 }
187 UpdateEntry(entry, content_status_flags);
189 // Always notify the WebContents that the SSL state changed when a 188 // Always notify the WebContents that the SSL state changed when a
190 // load is committed, in case the active navigation entry has changed. 189 // load is committed, in case the active navigation entry has changed.
191 NotifyDidChangeVisibleSSLState(); 190 NotifyDidChangeVisibleSSLState();
192 } 191 }
193 192
194 void SSLManager::DidRunInsecureContent(const GURL& security_origin) { 193 void SSLManager::DidDisplayMixedContent() {
194 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_INSECURE_CONTENT);
195 }
196
197 void SSLManager::DidDisplayContentWithCertErrors() {
195 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); 198 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
196 if (!entry) 199 if (!entry)
197 return; 200 return;
201 // Only record information about subresources with cert errors if the
202 // main page is HTTPS with a certificate.
203 if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
204 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS);
205 }
206 }
207
208 void SSLManager::DidShowPasswordInputOnHttp() {
209 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
210 }
211
212 void SSLManager::DidShowCreditCardInputOnHttp() {
213 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
214 }
215
216 void SSLManager::DidRunMixedContent(const GURL& security_origin) {
217 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
218 if (!entry)
219 return;
198 220
199 SiteInstance* site_instance = entry->site_instance(); 221 SiteInstance* site_instance = entry->site_instance();
200 if (!site_instance) 222 if (!site_instance)
201 return; 223 return;
202 224
203 if (ssl_host_state_delegate_) { 225 if (ssl_host_state_delegate_) {
204 ssl_host_state_delegate_->HostRanInsecureContent( 226 ssl_host_state_delegate_->HostRanInsecureContent(
205 security_origin.host(), site_instance->GetProcess()->GetID(), 227 security_origin.host(), site_instance->GetProcess()->GetID(),
206 SSLHostStateDelegate::MIXED_CONTENT); 228 SSLHostStateDelegate::MIXED_CONTENT);
207 } 229 }
208 UpdateEntry(entry); 230 UpdateEntry(entry, 0);
209 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); 231 NotifySSLInternalStateChanged(controller_->GetBrowserContext());
210 } 232 }
211 233
212 void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) { 234 void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) {
213 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); 235 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
214 if (!entry) 236 if (!entry)
215 return; 237 return;
216 238
217 SiteInstance* site_instance = entry->site_instance(); 239 SiteInstance* site_instance = entry->site_instance();
218 if (!site_instance) 240 if (!site_instance)
219 return; 241 return;
220 242
221 if (ssl_host_state_delegate_) { 243 if (ssl_host_state_delegate_) {
222 ssl_host_state_delegate_->HostRanInsecureContent( 244 ssl_host_state_delegate_->HostRanInsecureContent(
223 security_origin.host(), site_instance->GetProcess()->GetID(), 245 security_origin.host(), site_instance->GetProcess()->GetID(),
224 SSLHostStateDelegate::CERT_ERRORS_CONTENT); 246 SSLHostStateDelegate::CERT_ERRORS_CONTENT);
225 } 247 }
226 UpdateEntry(entry); 248 UpdateEntry(entry, 0);
227 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); 249 NotifySSLInternalStateChanged(controller_->GetBrowserContext());
228 } 250 }
229 251
230 void SSLManager::OnCertError(std::unique_ptr<SSLErrorHandler> handler) { 252 void SSLManager::OnCertError(std::unique_ptr<SSLErrorHandler> handler) {
231 bool expired_previous_decision = false; 253 bool expired_previous_decision = false;
232 // First we check if we know the policy for this error. 254 // First we check if we know the policy for this error.
233 DCHECK(handler->ssl_info().is_valid()); 255 DCHECK(handler->ssl_info().is_valid());
234 SSLHostStateDelegate::CertJudgment judgment = 256 SSLHostStateDelegate::CertJudgment judgment =
235 ssl_host_state_delegate_ 257 ssl_host_state_delegate_
236 ? ssl_host_state_delegate_->QueryPolicy( 258 ? ssl_host_state_delegate_->QueryPolicy(
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 const net::SSLInfo& ssl_info = handler->ssl_info(); 350 const net::SSLInfo& ssl_info = handler->ssl_info();
329 const GURL& request_url = handler->request_url(); 351 const GURL& request_url = handler->request_url();
330 ResourceType resource_type = handler->resource_type(); 352 ResourceType resource_type = handler->resource_type();
331 GetContentClient()->browser()->AllowCertificateError( 353 GetContentClient()->browser()->AllowCertificateError(
332 web_contents, cert_error, ssl_info, request_url, resource_type, 354 web_contents, cert_error, ssl_info, request_url, resource_type,
333 overridable, strict_enforcement, expired_previous_decision, 355 overridable, strict_enforcement, expired_previous_decision,
334 base::Bind(&OnAllowCertificate, base::Owned(handler.release()), 356 base::Bind(&OnAllowCertificate, base::Owned(handler.release()),
335 ssl_host_state_delegate_)); 357 ssl_host_state_delegate_));
336 } 358 }
337 359
338 void SSLManager::UpdateEntry(NavigationEntryImpl* entry) { 360 void SSLManager::UpdateEntry(NavigationEntryImpl* entry,
361 int additional_content_status_flags) {
339 // We don't always have a navigation entry to update, for example in the 362 // We don't always have a navigation entry to update, for example in the
340 // case of the Web Inspector. 363 // case of the Web Inspector.
341 if (!entry) 364 if (!entry)
342 return; 365 return;
343 366
344 SSLStatus original_ssl_status = entry->GetSSL(); // Copy! 367 SSLStatus original_ssl_status = entry->GetSSL(); // Copy!
345 entry->GetSSL().initialized = true; 368 entry->GetSSL().initialized = true;
346 369 entry->GetSSL().content_status |= additional_content_status_flags;
347 WebContentsImpl* web_contents_impl =
348 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
349
350 // For sensitive inputs (password, credit card) on HTTP, do not clear
351 // the |content_status| flag when the WebContents no longer has the
352 // flag set. This is different from how DISPLAYED_INSECURE_CONTENT and
353 // DISPLAYED_CONTENT_WITH_CERT_ERRORS are handled below. For sensitive
354 // inputs on HTTP, once the NavigationEntry has been marked as having
355 // displayed a sensitive input, it stays that way, even if the
356 // sensitive input is subsequently removed from the page.
357 if (web_contents_impl->DisplayedPasswordFieldOnHttp()) {
358 entry->GetSSL().content_status |=
359 SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP;
360 }
361
362 if (web_contents_impl->DisplayedCreditCardFieldOnHttp()) {
363 entry->GetSSL().content_status |=
364 SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP;
365 }
366
367 // Do not record information about insecure subresources if the main
368 // page is HTTP or HTTPS without a certificate.
369 if (!entry->GetURL().SchemeIsCryptographic() || !entry->GetSSL().certificate)
370 return;
371
372 // Update the entry's flags for insecure content.
373 if (!web_contents_impl->DisplayedInsecureContent())
374 entry->GetSSL().content_status &= ~SSLStatus::DISPLAYED_INSECURE_CONTENT;
375 if (web_contents_impl->DisplayedInsecureContent())
376 entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT;
377 if (!web_contents_impl->DisplayedContentWithCertErrors()) {
378 entry->GetSSL().content_status &=
379 ~SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
380 }
381 if (web_contents_impl->DisplayedContentWithCertErrors()) {
382 entry->GetSSL().content_status |=
383 SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
384 }
385 370
386 SiteInstance* site_instance = entry->site_instance(); 371 SiteInstance* site_instance = entry->site_instance();
387 // Note that |site_instance| can be NULL here because NavigationEntries don't 372 // Note that |site_instance| can be NULL here because NavigationEntries don't
388 // necessarily have site instances. Without a process, the entry can't 373 // necessarily have site instances. Without a process, the entry can't
389 // possibly have insecure content. See bug http://crbug.com/12423. 374 // possibly have insecure content. See bug http://crbug.com/12423.
390 if (site_instance && ssl_host_state_delegate_ && 375 if (site_instance && ssl_host_state_delegate_ &&
391 ssl_host_state_delegate_->DidHostRunInsecureContent( 376 ssl_host_state_delegate_->DidHostRunInsecureContent(
392 entry->GetURL().host(), site_instance->GetProcess()->GetID(), 377 entry->GetURL().host(), site_instance->GetProcess()->GetID(),
393 SSLHostStateDelegate::MIXED_CONTENT)) { 378 SSLHostStateDelegate::MIXED_CONTENT)) {
394 entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT; 379 entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT;
395 } 380 }
396 381
397 if (site_instance && ssl_host_state_delegate_ && 382 // Only record information about subresources with cert errors if the
383 // main page is HTTPS with a certificate.
384 if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate &&
385 site_instance && ssl_host_state_delegate_ &&
398 ssl_host_state_delegate_->DidHostRunInsecureContent( 386 ssl_host_state_delegate_->DidHostRunInsecureContent(
399 entry->GetURL().host(), site_instance->GetProcess()->GetID(), 387 entry->GetURL().host(), site_instance->GetProcess()->GetID(),
400 SSLHostStateDelegate::CERT_ERRORS_CONTENT)) { 388 SSLHostStateDelegate::CERT_ERRORS_CONTENT)) {
401 entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS; 389 entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS;
402 } 390 }
403 391
404 if (!entry->GetSSL().Equals(original_ssl_status)) 392 if (!entry->GetSSL().Equals(original_ssl_status))
405 NotifyDidChangeVisibleSSLState(); 393 NotifyDidChangeVisibleSSLState();
406 } 394 }
407 395
396 void SSLManager::UpdateLastCommittedEntry(int additional_content_status_flags) {
397 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
398 if (!entry)
399 return;
400 UpdateEntry(entry, additional_content_status_flags);
401 }
402
408 void SSLManager::NotifyDidChangeVisibleSSLState() { 403 void SSLManager::NotifyDidChangeVisibleSSLState() {
409 WebContentsImpl* contents = 404 WebContentsImpl* contents =
410 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents()); 405 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
411 contents->DidChangeVisibleSSLState(); 406 contents->DidChangeVisibleSSLState();
412 } 407 }
413 408
409 // static
410 void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
estark 2016/10/12 19:21:26 A note about why this is private now: we were prev
411 SSLManagerSet* managers =
412 static_cast<SSLManagerSet*>(context->GetUserData(kSSLManagerKeyName));
413
414 for (std::set<SSLManager*>::iterator i = managers->get().begin();
415 i != managers->get().end(); ++i) {
416 (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry(), 0);
417 }
418 }
419
414 } // namespace content 420 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/ssl/ssl_manager.h ('k') | content/browser/web_contents/web_contents_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698