Broke ContentSettingBubbleModelTest.Plugins on Android.
[chromium-blink-merge.git] / content / browser / ssl / ssl_manager.cc
blobd41260e583e325a7dc9ef4e251c148ba006ce283
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
3 // found in the LICENSE file.
5 #include "content/browser/ssl/ssl_manager.h"
7 #include "base/bind.h"
8 #include "base/utf_string_conversions.h"
9 #include "content/browser/loader/resource_dispatcher_host_impl.h"
10 #include "content/browser/loader/resource_request_info_impl.h"
11 #include "content/browser/ssl/ssl_cert_error_handler.h"
12 #include "content/browser/ssl/ssl_policy.h"
13 #include "content/browser/ssl/ssl_request_info.h"
14 #include "content/browser/web_contents/navigation_entry_impl.h"
15 #include "content/browser/web_contents/web_contents_impl.h"
16 #include "content/common/ssl_status_serialization.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/load_from_memory_cache_details.h"
19 #include "content/public/browser/navigation_details.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_source.h"
22 #include "content/public/browser/resource_request_details.h"
23 #include "content/public/common/ssl_status.h"
24 #include "net/url_request/url_request.h"
26 namespace content {
28 // static
29 void SSLManager::OnSSLCertificateError(
30 const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
31 const GlobalRequestID& id,
32 const ResourceType::Type resource_type,
33 const GURL& url,
34 int render_process_id,
35 int render_view_id,
36 const net::SSLInfo& ssl_info,
37 bool fatal) {
38 DCHECK(delegate);
39 DVLOG(1) << "OnSSLCertificateError() cert_error: "
40 << net::MapCertStatusToNetError(ssl_info.cert_status)
41 << " id: " << id.child_id << "," << id.request_id
42 << " resource_type: " << resource_type
43 << " url: " << url.spec()
44 << " render_process_id: " << render_process_id
45 << " render_view_id: " << render_view_id
46 << " cert_status: " << std::hex << ssl_info.cert_status;
48 // A certificate error occurred. Construct a SSLCertErrorHandler object and
49 // hand it over to the UI thread for processing.
50 BrowserThread::PostTask(
51 BrowserThread::UI, FROM_HERE,
52 base::Bind(&SSLCertErrorHandler::Dispatch,
53 new SSLCertErrorHandler(delegate,
54 id,
55 resource_type,
56 url,
57 render_process_id,
58 render_view_id,
59 ssl_info,
60 fatal)));
63 // static
64 void SSLManager::NotifySSLInternalStateChanged(
65 NavigationControllerImpl* controller) {
66 NotificationService::current()->Notify(
67 NOTIFICATION_SSL_INTERNAL_STATE_CHANGED,
68 Source<BrowserContext>(controller->GetBrowserContext()),
69 NotificationService::NoDetails());
72 SSLManager::SSLManager(NavigationControllerImpl* controller)
73 : backend_(controller),
74 policy_(new SSLPolicy(&backend_)),
75 controller_(controller) {
76 DCHECK(controller_);
78 // Subscribe to various notifications.
79 registrar_.Add(
80 this, NOTIFICATION_RESOURCE_RESPONSE_STARTED,
81 Source<WebContents>(controller_->web_contents()));
82 registrar_.Add(
83 this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
84 Source<WebContents>(controller_->web_contents()));
85 registrar_.Add(
86 this, NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
87 Source<NavigationController>(controller_));
88 registrar_.Add(
89 this, NOTIFICATION_SSL_INTERNAL_STATE_CHANGED,
90 Source<BrowserContext>(
91 controller_->GetBrowserContext()));
94 SSLManager::~SSLManager() {
97 void SSLManager::DidCommitProvisionalLoad(
98 const NotificationDetails& in_details) {
99 LoadCommittedDetails* details =
100 Details<LoadCommittedDetails>(in_details).ptr();
102 NavigationEntryImpl* entry =
103 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry());
105 if (details->is_main_frame) {
106 if (entry) {
107 // Decode the security details.
108 int ssl_cert_id;
109 net::CertStatus ssl_cert_status;
110 int ssl_security_bits;
111 int ssl_connection_status;
112 DeserializeSecurityInfo(details->serialized_security_info,
113 &ssl_cert_id,
114 &ssl_cert_status,
115 &ssl_security_bits,
116 &ssl_connection_status);
118 // We may not have an entry if this is a navigation to an initial blank
119 // page. Reset the SSL information and add the new data we have.
120 entry->GetSSL() = SSLStatus();
121 entry->GetSSL().cert_id = ssl_cert_id;
122 entry->GetSSL().cert_status = ssl_cert_status;
123 entry->GetSSL().security_bits = ssl_security_bits;
124 entry->GetSSL().connection_status = ssl_connection_status;
128 UpdateEntry(entry);
131 void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
132 policy()->DidRunInsecureContent(
133 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()),
134 security_origin);
137 void SSLManager::Observe(int type,
138 const NotificationSource& source,
139 const NotificationDetails& details) {
140 // Dispatch by type.
141 switch (type) {
142 case NOTIFICATION_RESOURCE_RESPONSE_STARTED:
143 DidStartResourceResponse(
144 Details<ResourceRequestDetails>(details).ptr());
145 break;
146 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT:
147 DidReceiveResourceRedirect(
148 Details<ResourceRedirectDetails>(details).ptr());
149 break;
150 case NOTIFICATION_LOAD_FROM_MEMORY_CACHE:
151 DidLoadFromMemoryCache(
152 Details<LoadFromMemoryCacheDetails>(details).ptr());
153 break;
154 case NOTIFICATION_SSL_INTERNAL_STATE_CHANGED:
155 DidChangeSSLInternalState();
156 break;
157 default:
158 NOTREACHED() << "The SSLManager received an unexpected notification.";
162 void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) {
163 // Simulate loading this resource through the usual path.
164 // Note that we specify SUB_RESOURCE as the resource type as WebCore only
165 // caches sub-resources.
166 // This resource must have been loaded with no filtering because filtered
167 // resouces aren't cachable.
168 scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
169 details->url,
170 ResourceType::SUB_RESOURCE,
171 details->pid,
172 details->cert_id,
173 details->cert_status));
175 // Simulate loading this resource through the usual path.
176 policy()->OnRequestStarted(info.get());
179 void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) {
180 scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
181 details->url,
182 details->resource_type,
183 details->origin_child_id,
184 details->ssl_cert_id,
185 details->ssl_cert_status));
187 // Notify our policy that we started a resource request. Ideally, the
188 // policy should have the ability to cancel the request, but we can't do
189 // that yet.
190 policy()->OnRequestStarted(info.get());
193 void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) {
194 // TODO(abarth): Make sure our redirect behavior is correct. If we ever see a
195 // non-HTTPS resource in the redirect chain, we want to trigger
196 // insecure content, even if the redirect chain goes back to
197 // HTTPS. This is because the network attacker can redirect the
198 // HTTP request to https://attacker.com/payload.js.
201 void SSLManager::DidChangeSSLInternalState() {
202 UpdateEntry(
203 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()));
206 void SSLManager::UpdateEntry(NavigationEntryImpl* entry) {
207 // We don't always have a navigation entry to update, for example in the
208 // case of the Web Inspector.
209 if (!entry)
210 return;
212 SSLStatus original_ssl_status = entry->GetSSL(); // Copy!
214 policy()->UpdateEntry(entry, controller_->web_contents());
216 if (!entry->GetSSL().Equals(original_ssl_status)) {
217 NotificationService::current()->Notify(
218 NOTIFICATION_SSL_VISIBLE_STATE_CHANGED,
219 Source<NavigationController>(controller_),
220 NotificationService::NoDetails());
224 } // namespace content