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

Side by Side Diff: components/security_state/content/web_contents_security_state_model.cc

Issue 2448943002: Refactor SecurityStateModel/Clients for simplicity and reusability. (Closed)
Patch Set: Remove *SecurityModelClient. Created 4 years, 1 month 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chrome/browser/ssl/chrome_security_state_model_client.h" 5 #include "components/security_state/content/web_contents_security_state_model.h"
6 6
7 #include <openssl/ssl.h> 7 #include <openssl/ssl.h>
8 8
9 #include <string>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/command_line.h" 12 #include "base/memory/ptr_util.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string16.h" 13 #include "base/strings/string16.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h" 16 #include "components/strings/grit/components_chromium_strings.h"
17 #include "chrome/browser/browser_process.h" 17 #include "components/strings/grit/components_strings.h"
18 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
19 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
22 #include "chrome/browser/safe_browsing/ui_manager.h"
23 #include "chrome/grit/chromium_strings.h"
24 #include "chrome/grit/generated_resources.h"
25 #include "content/public/browser/navigation_entry.h" 18 #include "content/public/browser/navigation_entry.h"
26 #include "content/public/browser/navigation_handle.h"
27 #include "content/public/browser/render_frame_host.h"
28 #include "content/public/browser/security_style_explanation.h" 19 #include "content/public/browser/security_style_explanation.h"
29 #include "content/public/browser/security_style_explanations.h" 20 #include "content/public/browser/security_style_explanations.h"
30 #include "content/public/browser/ssl_status.h" 21 #include "content/public/browser/ssl_status.h"
31 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/content_client.h"
32 #include "content/public/common/origin_util.h" 24 #include "content/public/common/origin_util.h"
33 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
34 #include "net/cert/x509_certificate.h" 26 #include "net/cert/x509_certificate.h"
35 #include "net/ssl/ssl_cipher_suite_names.h" 27 #include "net/ssl/ssl_cipher_suite_names.h"
36 #include "net/ssl/ssl_connection_status_flags.h" 28 #include "net/ssl/ssl_connection_status_flags.h"
37 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
38 30
39 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromeSecurityStateModelClient); 31 namespace security_state {
40
41 using safe_browsing::SafeBrowsingUIManager;
42 using security_state::SecurityStateModel;
43 32
44 namespace { 33 namespace {
45 34
46 // Note: This is a lossy operation. Not all of the policies that can be 35 // Note: This is a lossy operation. Not all of the policies that can be
47 // expressed by a SecurityLevel (a //chrome concept) can be expressed by 36 // expressed by a SecurityLevel can be expressed by a blink::WebSecurityStyle.
48 // a blink::WebSecurityStyle.
49 blink::WebSecurityStyle SecurityLevelToSecurityStyle( 37 blink::WebSecurityStyle SecurityLevelToSecurityStyle(
50 SecurityStateModel::SecurityLevel security_level) { 38 SecurityStateModel::SecurityLevel security_level) {
51 switch (security_level) { 39 switch (security_level) {
52 case SecurityStateModel::NONE: 40 case SecurityStateModel::NONE:
53 case SecurityStateModel::HTTP_SHOW_WARNING: 41 case SecurityStateModel::HTTP_SHOW_WARNING:
54 return blink::WebSecurityStyleUnauthenticated; 42 return blink::WebSecurityStyleUnauthenticated;
55 case SecurityStateModel::SECURITY_WARNING: 43 case SecurityStateModel::SECURITY_WARNING:
56 case SecurityStateModel::SECURE_WITH_POLICY_INSTALLED_CERT: 44 case SecurityStateModel::SECURE_WITH_POLICY_INSTALLED_CERT:
57 return blink::WebSecurityStyleWarning; 45 return blink::WebSecurityStyleWarning;
58 case SecurityStateModel::EV_SECURE: 46 case SecurityStateModel::EV_SECURE:
59 case SecurityStateModel::SECURE: 47 case SecurityStateModel::SECURE:
60 return blink::WebSecurityStyleAuthenticated; 48 return blink::WebSecurityStyleAuthenticated;
61 case SecurityStateModel::DANGEROUS: 49 case SecurityStateModel::DANGEROUS:
62 return blink::WebSecurityStyleAuthenticationBroken; 50 return blink::WebSecurityStyleAuthenticationBroken;
63 } 51 }
64 52
65 NOTREACHED(); 53 NOTREACHED();
66 return blink::WebSecurityStyleUnknown; 54 return blink::WebSecurityStyleUnknown;
67 } 55 }
68 56
69 void AddConnectionExplanation( 57 void AddConnectionExplanation(
70 const security_state::SecurityStateModel::SecurityInfo& security_info, 58 const SecurityStateModel::SecurityInfo& security_info,
71 content::SecurityStyleExplanations* security_style_explanations) { 59 content::SecurityStyleExplanations* security_style_explanations) {
72
73 // Avoid showing TLS details when we couldn't even establish a TLS connection 60 // Avoid showing TLS details when we couldn't even establish a TLS connection
74 // (e.g. for net errors) or if there was no real connection (some tests). We 61 // (e.g. for net errors) or if there was no real connection (some tests). We
75 // check the |connection_status| to see if there was a connection. 62 // check the |connection_status| to see if there was a connection.
76 if (security_info.connection_status == 0) { 63 if (security_info.connection_status == 0) {
77 return; 64 return;
78 } 65 }
79 66
80 int ssl_version = 67 int ssl_version =
81 net::SSLConnectionStatusToVersion(security_info.connection_status); 68 net::SSLConnectionStatusToVersion(security_info.connection_status);
82 const char* protocol; 69 const char* protocol;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 description_replacements.push_back(cipher_name); 129 description_replacements.push_back(cipher_name);
143 130
144 security_style_explanations->info_explanations.push_back( 131 security_style_explanations->info_explanations.push_back(
145 content::SecurityStyleExplanation( 132 content::SecurityStyleExplanation(
146 l10n_util::GetStringUTF8(IDS_OBSOLETE_SSL_SUMMARY), 133 l10n_util::GetStringUTF8(IDS_OBSOLETE_SSL_SUMMARY),
147 base::UTF16ToUTF8( 134 base::UTF16ToUTF8(
148 l10n_util::GetStringFUTF16(IDS_OBSOLETE_SSL_DESCRIPTION, 135 l10n_util::GetStringFUTF16(IDS_OBSOLETE_SSL_DESCRIPTION,
149 description_replacements, nullptr)))); 136 description_replacements, nullptr))));
150 } 137 }
151 138
152 // Check to see whether the security state should be downgraded to reflect
153 // a Safe Browsing verdict.
154 void CheckSafeBrowsingStatus(content::NavigationEntry* entry,
155 content::WebContents* web_contents,
156 SecurityStateModel::VisibleSecurityState* state) {
157 safe_browsing::SafeBrowsingService* sb_service =
158 g_browser_process->safe_browsing_service();
159 if (!sb_service)
160 return;
161 scoped_refptr<SafeBrowsingUIManager> sb_ui_manager = sb_service->ui_manager();
162 if (sb_ui_manager->IsUrlWhitelistedOrPendingForWebContents(
163 entry->GetURL(), false, entry, web_contents, false)) {
164 state->fails_malware_check = true;
165 }
166 }
167
168 } // namespace 139 } // namespace
169 140
170 ChromeSecurityStateModelClient::ChromeSecurityStateModelClient( 141 bool IsOriginSecure(const GURL& url) {
blundell 2016/10/28 21:59:46 Let's make this dependence explicit by having Secu
Eric Seckler 2016/11/01 16:46:36 Done.
171 content::WebContents* web_contents) 142 return content::IsOriginSecure(url);
172 : content::WebContentsObserver(web_contents),
173 web_contents_(web_contents),
174 security_state_model_(new SecurityStateModel()),
175 logged_http_warning_on_current_navigation_(false) {
176 security_state_model_->SetClient(this);
177 } 143 }
178 144
179 ChromeSecurityStateModelClient::~ChromeSecurityStateModelClient() {} 145 WebContentsSecurityStateModel::WebContentsSecurityStateModel(
146 content::WebContents* web_contents)
147 : web_contents_(web_contents),
148 security_state_model_(new SecurityStateModel()) {}
149
150 WebContentsSecurityStateModel::~WebContentsSecurityStateModel() {}
151
152 void WebContentsSecurityStateModel::GetSecurityInfo(
153 SecurityStateModel::SecurityInfo* result,
154 bool used_policy_installed_certificate,
155 bool failed_malware_check) const {
156 security_state_model_->GetSecurityInfo(
157 result, GetVisibleSecurityState(failed_malware_check),
158 used_policy_installed_certificate);
159 }
160
161 std::unique_ptr<SecurityStateModel::VisibleSecurityState>
162 WebContentsSecurityStateModel::GetVisibleSecurityState(
163 bool failed_malware_check) const {
164 auto state = base::MakeUnique<SecurityStateModel::VisibleSecurityState>();
165
166 // Malware status might already be known even if connection security
167 // information is still being initialized.
168 state->fails_malware_check = failed_malware_check;
169
170 content::NavigationEntry* entry =
171 web_contents_->GetController().GetVisibleEntry();
172 if (!entry || !entry->GetSSL().initialized)
173 return state;
174
175 state->connection_info_initialized = true;
176 state->url = entry->GetURL();
177 const content::SSLStatus& ssl = entry->GetSSL();
178 state->certificate = ssl.certificate;
179 state->cert_status = ssl.cert_status;
180 state->connection_status = ssl.connection_status;
181 state->key_exchange_group = ssl.key_exchange_group;
182 state->security_bits = ssl.security_bits;
183 state->pkp_bypassed = ssl.pkp_bypassed;
184 state->sct_verify_statuses.clear();
185 state->sct_verify_statuses.insert(state->sct_verify_statuses.begin(),
186 ssl.sct_statuses.begin(),
187 ssl.sct_statuses.end());
188 state->displayed_mixed_content =
189 !!(ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT);
190 state->ran_mixed_content =
191 !!(ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
192 state->displayed_content_with_cert_errors =
193 !!(ssl.content_status &
194 content::SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS);
195 state->ran_content_with_cert_errors =
196 !!(ssl.content_status & content::SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS);
197 state->displayed_password_field_on_http =
198 !!(ssl.content_status &
199 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
200 state->displayed_credit_card_field_on_http =
201 !!(ssl.content_status &
202 content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
203
204 return state;
205 }
180 206
181 // static 207 // static
182 blink::WebSecurityStyle ChromeSecurityStateModelClient::GetSecurityStyle( 208 blink::WebSecurityStyle WebContentsSecurityStateModel::GetSecurityStyle(
183 const security_state::SecurityStateModel::SecurityInfo& security_info, 209 const SecurityStateModel::SecurityInfo& security_info,
184 content::SecurityStyleExplanations* security_style_explanations) { 210 content::SecurityStyleExplanations* security_style_explanations) {
185 const blink::WebSecurityStyle security_style = 211 const blink::WebSecurityStyle security_style =
186 SecurityLevelToSecurityStyle(security_info.security_level); 212 SecurityLevelToSecurityStyle(security_info.security_level);
187 213
188 if (security_info.security_level == 214 if (security_info.security_level == SecurityStateModel::HTTP_SHOW_WARNING) {
189 security_state::SecurityStateModel::HTTP_SHOW_WARNING) {
190 // If the HTTP_SHOW_WARNING field trial is in use, display an 215 // If the HTTP_SHOW_WARNING field trial is in use, display an
191 // unauthenticated explanation explaining why the omnibox warning is 216 // unauthenticated explanation explaining why the omnibox warning is
192 // present. 217 // present.
193 security_style_explanations->unauthenticated_explanations.push_back( 218 security_style_explanations->unauthenticated_explanations.push_back(
194 content::SecurityStyleExplanation( 219 content::SecurityStyleExplanation(
195 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), 220 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT),
196 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION))); 221 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION)));
197 } else if (security_info.security_level == 222 } else if (security_info.security_level == SecurityStateModel::NONE &&
198 security_state::SecurityStateModel::NONE &&
199 security_info.displayed_private_user_data_input_on_http) { 223 security_info.displayed_private_user_data_input_on_http) {
200 // If the HTTP_SHOW_WARNING field trial isn't in use yet, display an 224 // If the HTTP_SHOW_WARNING field trial isn't in use yet, display an
201 // informational note that the omnibox will contain a warning for 225 // informational note that the omnibox will contain a warning for
202 // this site in a future version of Chrome. 226 // this site in a future version of Chrome.
203 security_style_explanations->info_explanations.push_back( 227 security_style_explanations->info_explanations.push_back(
204 content::SecurityStyleExplanation( 228 content::SecurityStyleExplanation(
205 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), 229 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT),
206 l10n_util::GetStringUTF8( 230 l10n_util::GetStringUTF8(
207 IDS_PRIVATE_USER_DATA_INPUT_FUTURE_DESCRIPTION))); 231 IDS_PRIVATE_USER_DATA_INPUT_FUTURE_DESCRIPTION)));
208 } 232 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 if (security_info.pkp_bypassed) { 340 if (security_info.pkp_bypassed) {
317 security_style_explanations->info_explanations.push_back( 341 security_style_explanations->info_explanations.push_back(
318 content::SecurityStyleExplanation( 342 content::SecurityStyleExplanation(
319 "Public-Key Pinning Bypassed", 343 "Public-Key Pinning Bypassed",
320 "Public-key pinning was bypassed by a local root certificate.")); 344 "Public-key pinning was bypassed by a local root certificate."));
321 } 345 }
322 346
323 return security_style; 347 return security_style;
324 } 348 }
325 349
326 void ChromeSecurityStateModelClient::GetSecurityInfo( 350 } // namespace security_state
327 SecurityStateModel::SecurityInfo* result) const {
328 security_state_model_->GetSecurityInfo(result);
329 }
330
331 void ChromeSecurityStateModelClient::VisibleSSLStateChanged() {
332 if (logged_http_warning_on_current_navigation_)
333 return;
334
335 security_state::SecurityStateModel::SecurityInfo security_info;
336 GetSecurityInfo(&security_info);
337 if (!security_info.displayed_private_user_data_input_on_http)
338 return;
339
340 std::string warning;
341 switch (security_info.security_level) {
342 case security_state::SecurityStateModel::HTTP_SHOW_WARNING:
343 warning =
344 "This page includes a password or credit card input in a non-secure "
345 "context. A warning has been added to the URL bar. For more "
346 "information, see https://goo.gl/zmWq3m.";
347 break;
348 case security_state::SecurityStateModel::NONE:
349 warning =
350 "This page includes a password or credit card input in a non-secure "
351 "context. A warning will be added to the URL bar in Chrome 56 (Jan "
352 "2017). For more information, see https://goo.gl/zmWq3m.";
353 break;
354 default:
355 return;
356 }
357
358 logged_http_warning_on_current_navigation_ = true;
359 web_contents_->GetMainFrame()->AddMessageToConsole(
360 content::CONSOLE_MESSAGE_LEVEL_WARNING, warning);
361 }
362
363 void ChromeSecurityStateModelClient::DidFinishNavigation(
364 content::NavigationHandle* navigation_handle) {
365 if (navigation_handle->IsInMainFrame() &&
366 !navigation_handle->IsSynchronousNavigation()) {
367 // Only reset the console message flag for main-frame navigations,
368 // and not for synchronous navigations like reference fragments and
369 // pushState.
370 logged_http_warning_on_current_navigation_ = false;
371 }
372 }
373
374 bool ChromeSecurityStateModelClient::UsedPolicyInstalledCertificate() {
375 #if defined(OS_CHROMEOS)
376 policy::PolicyCertService* service =
377 policy::PolicyCertServiceFactory::GetForProfile(
378 Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
379 if (service && service->UsedPolicyCertificates())
380 return true;
381 #endif
382 return false;
383 }
384
385 bool ChromeSecurityStateModelClient::IsOriginSecure(const GURL& url) {
386 return content::IsOriginSecure(url);
387 }
388
389 void ChromeSecurityStateModelClient::GetVisibleSecurityState(
390 SecurityStateModel::VisibleSecurityState* state) {
391 content::NavigationEntry* entry =
392 web_contents_->GetController().GetVisibleEntry();
393 if (!entry) {
394 *state = SecurityStateModel::VisibleSecurityState();
395 return;
396 }
397
398 if (!entry->GetSSL().initialized) {
399 *state = SecurityStateModel::VisibleSecurityState();
400 // Connection security information is still being initialized, but malware
401 // status might already be known.
402 CheckSafeBrowsingStatus(entry, web_contents_, state);
403 return;
404 }
405
406 state->connection_info_initialized = true;
407 state->url = entry->GetURL();
408 const content::SSLStatus& ssl = entry->GetSSL();
409 state->certificate = ssl.certificate;
410 state->cert_status = ssl.cert_status;
411 state->connection_status = ssl.connection_status;
412 state->key_exchange_group = ssl.key_exchange_group;
413 state->security_bits = ssl.security_bits;
414 state->pkp_bypassed = ssl.pkp_bypassed;
415 state->sct_verify_statuses.clear();
416 state->sct_verify_statuses.insert(state->sct_verify_statuses.begin(),
417 ssl.sct_statuses.begin(),
418 ssl.sct_statuses.end());
419 state->displayed_mixed_content =
420 !!(ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT);
421 state->ran_mixed_content =
422 !!(ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
423 state->displayed_content_with_cert_errors =
424 !!(ssl.content_status &
425 content::SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS);
426 state->ran_content_with_cert_errors =
427 !!(ssl.content_status & content::SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS);
428 state->displayed_password_field_on_http =
429 !!(ssl.content_status &
430 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
431 state->displayed_credit_card_field_on_http =
432 !!(ssl.content_status &
433 content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
434
435 CheckSafeBrowsingStatus(entry, web_contents_, state);
436 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698