OLD | NEW |
---|---|
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> | |
8 | |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/supports_user_data.h" | |
8 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
9 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 12 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
10 #include "content/browser/loader/resource_request_info_impl.h" | 13 #include "content/browser/loader/resource_request_info_impl.h" |
11 #include "content/browser/ssl/ssl_cert_error_handler.h" | 14 #include "content/browser/ssl/ssl_cert_error_handler.h" |
12 #include "content/browser/ssl/ssl_policy.h" | 15 #include "content/browser/ssl/ssl_policy.h" |
13 #include "content/browser/ssl/ssl_request_info.h" | 16 #include "content/browser/ssl/ssl_request_info.h" |
14 #include "content/browser/web_contents/navigation_entry_impl.h" | 17 #include "content/browser/web_contents/navigation_entry_impl.h" |
15 #include "content/browser/web_contents/web_contents_impl.h" | 18 #include "content/browser/web_contents/web_contents_impl.h" |
16 #include "content/common/ssl_status_serialization.h" | 19 #include "content/common/ssl_status_serialization.h" |
20 #include "content/public/browser/browser_context.h" | |
17 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/load_from_memory_cache_details.h" | 22 #include "content/public/browser/load_from_memory_cache_details.h" |
19 #include "content/public/browser/navigation_details.h" | 23 #include "content/public/browser/navigation_details.h" |
20 #include "content/public/browser/notification_service.h" | 24 #include "content/public/browser/notification_service.h" |
21 #include "content/public/browser/notification_source.h" | 25 #include "content/public/browser/notification_source.h" |
22 #include "content/public/browser/resource_request_details.h" | 26 #include "content/public/browser/resource_request_details.h" |
23 #include "content/public/common/ssl_status.h" | 27 #include "content/public/common/ssl_status.h" |
24 #include "net/url_request/url_request.h" | 28 #include "net/url_request/url_request.h" |
25 | 29 |
26 namespace content { | 30 namespace content { |
27 | 31 |
32 namespace { | |
33 | |
34 const char kSSLManagerKeyName[] = "content_ssl_manager"; | |
35 | |
36 class SSLManagerSet : public base::SupportsUserData::Data { | |
37 public: | |
38 SSLManagerSet() { | |
39 } | |
40 | |
41 std::set<SSLManager*>& get() { return set_; } | |
42 | |
43 private: | |
44 std::set<SSLManager*> set_; | |
45 | |
46 DISALLOW_COPY_AND_ASSIGN(SSLManagerSet); | |
47 }; | |
48 | |
49 } // namespace | |
50 | |
28 // static | 51 // static |
29 void SSLManager::OnSSLCertificateError( | 52 void SSLManager::OnSSLCertificateError( |
30 const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, | 53 const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, |
31 const GlobalRequestID& id, | 54 const GlobalRequestID& id, |
32 const ResourceType::Type resource_type, | 55 const ResourceType::Type resource_type, |
33 const GURL& url, | 56 const GURL& url, |
34 int render_process_id, | 57 int render_process_id, |
35 int render_view_id, | 58 int render_view_id, |
36 const net::SSLInfo& ssl_info, | 59 const net::SSLInfo& ssl_info, |
37 bool fatal) { | 60 bool fatal) { |
(...skipping 16 matching lines...) Expand all Loading... | |
54 id, | 77 id, |
55 resource_type, | 78 resource_type, |
56 url, | 79 url, |
57 render_process_id, | 80 render_process_id, |
58 render_view_id, | 81 render_view_id, |
59 ssl_info, | 82 ssl_info, |
60 fatal))); | 83 fatal))); |
61 } | 84 } |
62 | 85 |
63 // static | 86 // static |
64 void SSLManager::NotifySSLInternalStateChanged( | 87 void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) { |
65 NavigationControllerImpl* controller) { | 88 SSLManagerSet* managers = static_cast<SSLManagerSet*>( |
66 NotificationService::current()->Notify( | 89 context->GetUserData(kSSLManagerKeyName)); |
67 NOTIFICATION_SSL_INTERNAL_STATE_CHANGED, | 90 if (!managers) |
jam
2013/02/07 17:56:24
can this really happen? if not, i prefer not addin
Paweł Hajdan Jr.
2013/02/08 09:12:22
Done.
| |
68 Source<BrowserContext>(controller->GetBrowserContext()), | 91 return; |
69 NotificationService::NoDetails()); | 92 |
93 for (std::set<SSLManager*>::iterator i = managers->get().begin(); | |
94 i != managers->get().end(); ++i) { | |
95 (*i)->UpdateEntry(NavigationEntryImpl::FromNavigationEntry( | |
96 (*i)->controller()->GetActiveEntry())); | |
97 } | |
70 } | 98 } |
71 | 99 |
72 SSLManager::SSLManager(NavigationControllerImpl* controller) | 100 SSLManager::SSLManager(NavigationControllerImpl* controller) |
73 : backend_(controller), | 101 : backend_(controller), |
74 policy_(new SSLPolicy(&backend_)), | 102 policy_(new SSLPolicy(&backend_)), |
75 controller_(controller) { | 103 controller_(controller) { |
76 DCHECK(controller_); | 104 DCHECK(controller_); |
77 | 105 |
78 // Subscribe to various notifications. | 106 // Subscribe to various notifications. |
79 registrar_.Add( | 107 registrar_.Add( |
80 this, NOTIFICATION_RESOURCE_RESPONSE_STARTED, | 108 this, NOTIFICATION_RESOURCE_RESPONSE_STARTED, |
81 Source<WebContents>(controller_->web_contents())); | 109 Source<WebContents>(controller_->web_contents())); |
82 registrar_.Add( | 110 registrar_.Add( |
83 this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, | 111 this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, |
84 Source<WebContents>(controller_->web_contents())); | 112 Source<WebContents>(controller_->web_contents())); |
85 registrar_.Add( | 113 registrar_.Add( |
86 this, NOTIFICATION_LOAD_FROM_MEMORY_CACHE, | 114 this, NOTIFICATION_LOAD_FROM_MEMORY_CACHE, |
87 Source<NavigationController>(controller_)); | 115 Source<NavigationController>(controller_)); |
88 registrar_.Add( | 116 |
89 this, NOTIFICATION_SSL_INTERNAL_STATE_CHANGED, | 117 SSLManagerSet* managers = static_cast<SSLManagerSet*>( |
90 Source<BrowserContext>( | 118 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); |
91 controller_->GetBrowserContext())); | 119 if (!managers) { |
120 managers = new SSLManagerSet; | |
121 controller_->GetBrowserContext()->SetUserData(kSSLManagerKeyName, managers); | |
122 } | |
123 managers->get().insert(this); | |
92 } | 124 } |
93 | 125 |
94 SSLManager::~SSLManager() { | 126 SSLManager::~SSLManager() { |
127 SSLManagerSet* managers = static_cast<SSLManagerSet*>( | |
128 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); | |
129 if (managers) | |
jam
2013/02/07 17:56:24
ditto, don't see how this could happen
Paweł Hajdan Jr.
2013/02/08 09:12:22
Done.
| |
130 managers->get().erase(this); | |
95 } | 131 } |
96 | 132 |
97 void SSLManager::DidCommitProvisionalLoad( | 133 void SSLManager::DidCommitProvisionalLoad( |
98 const NotificationDetails& in_details) { | 134 const NotificationDetails& in_details) { |
99 LoadCommittedDetails* details = | 135 LoadCommittedDetails* details = |
100 Details<LoadCommittedDetails>(in_details).ptr(); | 136 Details<LoadCommittedDetails>(in_details).ptr(); |
101 | 137 |
102 NavigationEntryImpl* entry = | 138 NavigationEntryImpl* entry = |
103 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()); | 139 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()); |
104 | 140 |
(...skipping 16 matching lines...) Expand all Loading... | |
121 entry->GetSSL().cert_id = ssl_cert_id; | 157 entry->GetSSL().cert_id = ssl_cert_id; |
122 entry->GetSSL().cert_status = ssl_cert_status; | 158 entry->GetSSL().cert_status = ssl_cert_status; |
123 entry->GetSSL().security_bits = ssl_security_bits; | 159 entry->GetSSL().security_bits = ssl_security_bits; |
124 entry->GetSSL().connection_status = ssl_connection_status; | 160 entry->GetSSL().connection_status = ssl_connection_status; |
125 } | 161 } |
126 } | 162 } |
127 | 163 |
128 UpdateEntry(entry); | 164 UpdateEntry(entry); |
129 } | 165 } |
130 | 166 |
167 void SSLManager::DidDisplayInsecureContent() { | |
168 UpdateEntry( | |
169 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry())); | |
170 } | |
171 | |
131 void SSLManager::DidRunInsecureContent(const std::string& security_origin) { | 172 void SSLManager::DidRunInsecureContent(const std::string& security_origin) { |
132 policy()->DidRunInsecureContent( | 173 NavigationEntryImpl* navigation_entry = |
133 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()), | 174 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()); |
134 security_origin); | 175 policy()->DidRunInsecureContent(navigation_entry, security_origin); |
176 UpdateEntry(navigation_entry); | |
135 } | 177 } |
136 | 178 |
137 void SSLManager::Observe(int type, | 179 void SSLManager::Observe(int type, |
138 const NotificationSource& source, | 180 const NotificationSource& source, |
139 const NotificationDetails& details) { | 181 const NotificationDetails& details) { |
140 // Dispatch by type. | 182 // Dispatch by type. |
141 switch (type) { | 183 switch (type) { |
142 case NOTIFICATION_RESOURCE_RESPONSE_STARTED: | 184 case NOTIFICATION_RESOURCE_RESPONSE_STARTED: |
143 DidStartResourceResponse( | 185 DidStartResourceResponse( |
144 Details<ResourceRequestDetails>(details).ptr()); | 186 Details<ResourceRequestDetails>(details).ptr()); |
145 break; | 187 break; |
146 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: | 188 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: |
147 DidReceiveResourceRedirect( | 189 DidReceiveResourceRedirect( |
148 Details<ResourceRedirectDetails>(details).ptr()); | 190 Details<ResourceRedirectDetails>(details).ptr()); |
149 break; | 191 break; |
150 case NOTIFICATION_LOAD_FROM_MEMORY_CACHE: | 192 case NOTIFICATION_LOAD_FROM_MEMORY_CACHE: |
151 DidLoadFromMemoryCache( | 193 DidLoadFromMemoryCache( |
152 Details<LoadFromMemoryCacheDetails>(details).ptr()); | 194 Details<LoadFromMemoryCacheDetails>(details).ptr()); |
153 break; | 195 break; |
154 case NOTIFICATION_SSL_INTERNAL_STATE_CHANGED: | |
155 DidChangeSSLInternalState(); | |
156 break; | |
157 default: | 196 default: |
158 NOTREACHED() << "The SSLManager received an unexpected notification."; | 197 NOTREACHED() << "The SSLManager received an unexpected notification."; |
159 } | 198 } |
160 } | 199 } |
161 | 200 |
162 void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { | 201 void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { |
163 // Simulate loading this resource through the usual path. | 202 // Simulate loading this resource through the usual path. |
164 // Note that we specify SUB_RESOURCE as the resource type as WebCore only | 203 // Note that we specify SUB_RESOURCE as the resource type as WebCore only |
165 // caches sub-resources. | 204 // caches sub-resources. |
166 // This resource must have been loaded with no filtering because filtered | 205 // This resource must have been loaded with no filtering because filtered |
(...skipping 24 matching lines...) Expand all Loading... | |
191 } | 230 } |
192 | 231 |
193 void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) { | 232 void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) { |
194 // TODO(abarth): Make sure our redirect behavior is correct. If we ever see a | 233 // 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 | 234 // non-HTTPS resource in the redirect chain, we want to trigger |
196 // insecure content, even if the redirect chain goes back to | 235 // insecure content, even if the redirect chain goes back to |
197 // HTTPS. This is because the network attacker can redirect the | 236 // HTTPS. This is because the network attacker can redirect the |
198 // HTTP request to https://attacker.com/payload.js. | 237 // HTTP request to https://attacker.com/payload.js. |
199 } | 238 } |
200 | 239 |
201 void SSLManager::DidChangeSSLInternalState() { | |
202 UpdateEntry( | |
203 NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry())); | |
204 } | |
205 | |
206 void SSLManager::UpdateEntry(NavigationEntryImpl* entry) { | 240 void SSLManager::UpdateEntry(NavigationEntryImpl* entry) { |
207 // We don't always have a navigation entry to update, for example in the | 241 // We don't always have a navigation entry to update, for example in the |
208 // case of the Web Inspector. | 242 // case of the Web Inspector. |
209 if (!entry) | 243 if (!entry) |
210 return; | 244 return; |
211 | 245 |
212 SSLStatus original_ssl_status = entry->GetSSL(); // Copy! | 246 SSLStatus original_ssl_status = entry->GetSSL(); // Copy! |
213 | 247 |
214 policy()->UpdateEntry(entry, controller_->web_contents()); | 248 policy()->UpdateEntry(entry, controller_->web_contents()); |
215 | 249 |
216 if (!entry->GetSSL().Equals(original_ssl_status)) { | 250 if (!entry->GetSSL().Equals(original_ssl_status)) |
217 NotificationService::current()->Notify( | 251 controller_->web_contents()->DidChangeVisibleSSLState(); |
218 NOTIFICATION_SSL_VISIBLE_STATE_CHANGED, | |
219 Source<NavigationController>(controller_), | |
220 NotificationService::NoDetails()); | |
221 } | |
222 } | 252 } |
223 | 253 |
224 } // namespace content | 254 } // namespace content |
OLD | NEW |