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

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: Refactor -> WebContentsSecurityStateModel. 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/metrics/field_trial.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
13 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h" 15 #include "components/strings/grit/components_chromium_strings.h"
17 #include "chrome/browser/browser_process.h" 16 #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" 17 #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" 18 #include "content/public/browser/security_style_explanation.h"
29 #include "content/public/browser/security_style_explanations.h" 19 #include "content/public/browser/security_style_explanations.h"
30 #include "content/public/browser/ssl_status.h" 20 #include "content/public/browser/ssl_status.h"
31 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/content_client.h"
32 #include "content/public/common/origin_util.h" 23 #include "content/public/common/origin_util.h"
33 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
34 #include "net/cert/x509_certificate.h" 25 #include "net/cert/x509_certificate.h"
35 #include "net/ssl/ssl_cipher_suite_names.h" 26 #include "net/ssl/ssl_cipher_suite_names.h"
36 #include "net/ssl/ssl_connection_status_flags.h" 27 #include "net/ssl/ssl_connection_status_flags.h"
37 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
38 29
39 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromeSecurityStateModelClient); 30 namespace security_state {
40
41 using safe_browsing::SafeBrowsingUIManager;
42 using security_state::SecurityStateModel;
43 31
44 namespace { 32 namespace {
45 33
46 // Note: This is a lossy operation. Not all of the policies that can be 34 // 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 35 // expressed by a SecurityLevel can be expressed by a blink::WebSecurityStyle.
48 // a blink::WebSecurityStyle.
49 blink::WebSecurityStyle SecurityLevelToSecurityStyle( 36 blink::WebSecurityStyle SecurityLevelToSecurityStyle(
50 SecurityStateModel::SecurityLevel security_level) { 37 SecurityStateModel::SecurityLevel security_level) {
51 switch (security_level) { 38 switch (security_level) {
52 case SecurityStateModel::NONE: 39 case SecurityStateModel::NONE:
53 case SecurityStateModel::HTTP_SHOW_WARNING: 40 case SecurityStateModel::HTTP_SHOW_WARNING:
54 return blink::WebSecurityStyleUnauthenticated; 41 return blink::WebSecurityStyleUnauthenticated;
55 case SecurityStateModel::SECURITY_WARNING: 42 case SecurityStateModel::SECURITY_WARNING:
56 case SecurityStateModel::SECURE_WITH_POLICY_INSTALLED_CERT: 43 case SecurityStateModel::SECURE_WITH_POLICY_INSTALLED_CERT:
57 return blink::WebSecurityStyleWarning; 44 return blink::WebSecurityStyleWarning;
58 case SecurityStateModel::EV_SECURE: 45 case SecurityStateModel::EV_SECURE:
59 case SecurityStateModel::SECURE: 46 case SecurityStateModel::SECURE:
60 return blink::WebSecurityStyleAuthenticated; 47 return blink::WebSecurityStyleAuthenticated;
61 case SecurityStateModel::DANGEROUS: 48 case SecurityStateModel::DANGEROUS:
62 return blink::WebSecurityStyleAuthenticationBroken; 49 return blink::WebSecurityStyleAuthenticationBroken;
63 } 50 }
64 51
65 NOTREACHED(); 52 NOTREACHED();
66 return blink::WebSecurityStyleUnknown; 53 return blink::WebSecurityStyleUnknown;
67 } 54 }
68 55
69 void AddConnectionExplanation( 56 void AddConnectionExplanation(
70 const security_state::SecurityStateModel::SecurityInfo& security_info, 57 const SecurityStateModel::SecurityInfo& security_info,
71 content::SecurityStyleExplanations* security_style_explanations) { 58 content::SecurityStyleExplanations* security_style_explanations) {
72
73 // Avoid showing TLS details when we couldn't even establish a TLS connection 59 // 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 60 // (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. 61 // check the |connection_status| to see if there was a connection.
76 if (security_info.connection_status == 0) { 62 if (security_info.connection_status == 0) {
77 return; 63 return;
78 } 64 }
79 65
80 int ssl_version = 66 int ssl_version =
81 net::SSLConnectionStatusToVersion(security_info.connection_status); 67 net::SSLConnectionStatusToVersion(security_info.connection_status);
82 const char* protocol; 68 const char* protocol;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 description_replacements.push_back(cipher_name); 128 description_replacements.push_back(cipher_name);
143 129
144 security_style_explanations->info_explanations.push_back( 130 security_style_explanations->info_explanations.push_back(
145 content::SecurityStyleExplanation( 131 content::SecurityStyleExplanation(
146 l10n_util::GetStringUTF8(IDS_OBSOLETE_SSL_SUMMARY), 132 l10n_util::GetStringUTF8(IDS_OBSOLETE_SSL_SUMMARY),
147 base::UTF16ToUTF8( 133 base::UTF16ToUTF8(
148 l10n_util::GetStringFUTF16(IDS_OBSOLETE_SSL_DESCRIPTION, 134 l10n_util::GetStringFUTF16(IDS_OBSOLETE_SSL_DESCRIPTION,
149 description_replacements, nullptr)))); 135 description_replacements, nullptr))));
150 } 136 }
151 137
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 138 } // namespace
169 139
170 ChromeSecurityStateModelClient::ChromeSecurityStateModelClient( 140 class WebContentsSecurityStateModel::Client : public SecurityStateModelClient {
blundell 2016/10/26 18:30:47 This is still implementing the core Client interfa
141 public:
142 Client(WebContentsSecurityStateModel* model) : model_(model) {}
143
144 ~Client() override {}
145
146 // SecurityStateModelClient:
147 void GetVisibleSecurityState(
148 SecurityStateModel::VisibleSecurityState* state) override {
149 content::NavigationEntry* entry =
150 model_->web_contents_->GetController().GetVisibleEntry();
151 if (!entry) {
152 *state = SecurityStateModel::VisibleSecurityState();
153 return;
154 }
155
156 if (!entry->GetSSL().initialized) {
157 *state = SecurityStateModel::VisibleSecurityState();
158 // Connection security information is still being initialized, but malware
159 // status might already be known.
160 if (model_->client_) {
161 state->fails_malware_check =
162 model_->client_->GetMalwareStatus(entry, model_->web_contents_);
163 }
164 return;
165 }
166
167 state->connection_info_initialized = true;
168 state->url = entry->GetURL();
169 const content::SSLStatus& ssl = entry->GetSSL();
170 state->certificate = ssl.certificate;
171 state->cert_status = ssl.cert_status;
172 state->connection_status = ssl.connection_status;
173 state->key_exchange_group = ssl.key_exchange_group;
174 state->security_bits = ssl.security_bits;
175 state->pkp_bypassed = ssl.pkp_bypassed;
176 state->sct_verify_statuses.clear();
177 state->sct_verify_statuses.insert(state->sct_verify_statuses.begin(),
178 ssl.sct_statuses.begin(),
179 ssl.sct_statuses.end());
180 state->displayed_mixed_content =
181 !!(ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT);
182 state->ran_mixed_content =
183 !!(ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
184 state->displayed_content_with_cert_errors =
185 !!(ssl.content_status &
186 content::SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS);
187 state->ran_content_with_cert_errors = !!(
188 ssl.content_status & content::SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS);
189 state->displayed_password_field_on_http =
190 !!(ssl.content_status &
191 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
192 state->displayed_credit_card_field_on_http =
193 !!(ssl.content_status &
194 content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
195
196 if (model_->client_) {
197 state->fails_malware_check =
198 model_->client_->GetMalwareStatus(entry, model_->web_contents_);
199 }
200 }
201
202 bool UsedPolicyInstalledCertificate() override {
203 if (model_->client_)
204 return model_->client_->UsedPolicyInstalledCertificate();
205 return false;
206 }
207
208 bool IsOriginSecure(const GURL& url) override {
209 return content::IsOriginSecure(url);
210 }
211
212 private:
213 WebContentsSecurityStateModel* model_;
214 };
215
216 WebContentsSecurityStateModel::WebContentsSecurityStateModel(
171 content::WebContents* web_contents) 217 content::WebContents* web_contents)
172 : content::WebContentsObserver(web_contents), 218 : web_contents_(web_contents),
173 web_contents_(web_contents),
174 security_state_model_(new SecurityStateModel()), 219 security_state_model_(new SecurityStateModel()),
175 logged_http_warning_on_current_navigation_(false) { 220 client_(nullptr),
176 security_state_model_->SetClient(this); 221 internal_client_(new Client(this)) {
222 security_state_model_->SetClient(internal_client_.get());
177 } 223 }
178 224
179 ChromeSecurityStateModelClient::~ChromeSecurityStateModelClient() {} 225 WebContentsSecurityStateModel::~WebContentsSecurityStateModel() {}
226
227 void WebContentsSecurityStateModel::SetClient(
228 WebContentsSecurityStateModelClient* client) {
229 client_ = client;
230 }
231
232 void WebContentsSecurityStateModel::GetSecurityInfo(
233 SecurityStateModel::SecurityInfo* result) const {
234 security_state_model_->GetSecurityInfo(result);
235 }
236
237 void WebContentsSecurityStateModel::GetVisibleSecurityState(
238 SecurityStateModel::VisibleSecurityState* state) {
239 internal_client_->GetVisibleSecurityState(state);
240 }
180 241
181 // static 242 // static
182 blink::WebSecurityStyle ChromeSecurityStateModelClient::GetSecurityStyle( 243 blink::WebSecurityStyle WebContentsSecurityStateModel::GetSecurityStyle(
183 const security_state::SecurityStateModel::SecurityInfo& security_info, 244 const SecurityStateModel::SecurityInfo& security_info,
184 content::SecurityStyleExplanations* security_style_explanations) { 245 content::SecurityStyleExplanations* security_style_explanations) {
185 const blink::WebSecurityStyle security_style = 246 const blink::WebSecurityStyle security_style =
186 SecurityLevelToSecurityStyle(security_info.security_level); 247 SecurityLevelToSecurityStyle(security_info.security_level);
187 248
188 if (security_info.security_level == 249 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 250 // If the HTTP_SHOW_WARNING field trial is in use, display an
191 // unauthenticated explanation explaining why the omnibox warning is 251 // unauthenticated explanation explaining why the omnibox warning is
192 // present. 252 // present.
193 security_style_explanations->unauthenticated_explanations.push_back( 253 security_style_explanations->unauthenticated_explanations.push_back(
194 content::SecurityStyleExplanation( 254 content::SecurityStyleExplanation(
195 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), 255 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT),
196 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION))); 256 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION)));
197 } else if (security_info.security_level == 257 } else if (security_info.security_level == SecurityStateModel::NONE &&
198 security_state::SecurityStateModel::NONE &&
199 security_info.displayed_private_user_data_input_on_http) { 258 security_info.displayed_private_user_data_input_on_http) {
200 // If the HTTP_SHOW_WARNING field trial isn't in use yet, display an 259 // 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 260 // informational note that the omnibox will contain a warning for
202 // this site in a future version of Chrome. 261 // this site in a future version of Chrome.
203 security_style_explanations->info_explanations.push_back( 262 security_style_explanations->info_explanations.push_back(
204 content::SecurityStyleExplanation( 263 content::SecurityStyleExplanation(
205 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), 264 l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT),
206 l10n_util::GetStringUTF8( 265 l10n_util::GetStringUTF8(
207 IDS_PRIVATE_USER_DATA_INPUT_FUTURE_DESCRIPTION))); 266 IDS_PRIVATE_USER_DATA_INPUT_FUTURE_DESCRIPTION)));
208 } 267 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 if (security_info.pkp_bypassed) { 375 if (security_info.pkp_bypassed) {
317 security_style_explanations->info_explanations.push_back( 376 security_style_explanations->info_explanations.push_back(
318 content::SecurityStyleExplanation( 377 content::SecurityStyleExplanation(
319 "Public-Key Pinning Bypassed", 378 "Public-Key Pinning Bypassed",
320 "Public-key pinning was bypassed by a local root certificate.")); 379 "Public-key pinning was bypassed by a local root certificate."));
321 } 380 }
322 381
323 return security_style; 382 return security_style;
324 } 383 }
325 384
326 void ChromeSecurityStateModelClient::GetSecurityInfo( 385 } // 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