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

Side by Side Diff: chrome/browser/ssl/bad_clock_blocking_page.cc

Issue 1481213003: Componentize the bad clock blocking page (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change for pkasting Created 5 years 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/bad_clock_blocking_page.h" 5 #include "chrome/browser/ssl/bad_clock_blocking_page.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/build_time.h"
10 #include "base/callback_helpers.h" 7 #include "base/callback_helpers.h"
11 #include "base/command_line.h" 8 #include "base/prefs/pref_service.h"
12 #include "base/files/file_util.h"
13 #include "base/i18n/rtl.h"
14 #include "base/i18n/time_formatting.h"
15 #include "base/process/launch.h"
16 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_piece.h" 10 #include "chrome/browser/interstitials/chrome_controller_client.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/time/time.h"
22 #include "base/values.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/interstitials/chrome_metrics_helper.h" 11 #include "chrome/browser/interstitials/chrome_metrics_helper.h"
25 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/renderer_preferences_util.h" 13 #include "chrome/browser/renderer_preferences_util.h"
27 #include "chrome/browser/ssl/cert_report_helper.h" 14 #include "chrome/browser/ssl/cert_report_helper.h"
28 #include "chrome/browser/ssl/ssl_cert_reporter.h" 15 #include "chrome/browser/ssl/ssl_cert_reporter.h"
29 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
30 #include "chrome/grit/generated_resources.h" 17 #include "components/security_interstitials/core/bad_clock_ui.h"
31 #include "components/google/core/browser/google_util.h"
32 #include "components/security_interstitials/core/controller_client.h" 18 #include "components/security_interstitials/core/controller_client.h"
33 #include "components/ssl_errors/error_classification.h" 19 #include "components/security_interstitials/core/metrics_helper.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/cert_store.h" 20 #include "content/public/browser/cert_store.h"
36 #include "content/public/browser/interstitial_page.h" 21 #include "content/public/browser/interstitial_page.h"
37 #include "content/public/browser/interstitial_page_delegate.h" 22 #include "content/public/browser/interstitial_page_delegate.h"
38 #include "content/public/browser/navigation_controller.h" 23 #include "content/public/browser/navigation_controller.h"
39 #include "content/public/browser/navigation_entry.h" 24 #include "content/public/browser/navigation_entry.h"
40 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/render_process_host.h"
41 #include "content/public/browser/render_view_host.h" 26 #include "content/public/browser/render_view_host.h"
42 #include "content/public/browser/signed_certificate_timestamp_store.h" 27 #include "content/public/browser/signed_certificate_timestamp_store.h"
43 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
44 #include "content/public/common/renderer_preferences.h" 29 #include "content/public/common/renderer_preferences.h"
45 #include "content/public/common/ssl_status.h" 30 #include "content/public/common/ssl_status.h"
46 #include "grit/browser_resources.h"
47 #include "grit/components_strings.h"
48 #include "net/base/net_errors.h" 31 #include "net/base/net_errors.h"
49 #include "net/base/net_util.h"
50 #include "net/cert/x509_certificate.h"
51 #include "ui/base/l10n/l10n_util.h"
52 32
53 #if defined(OS_ANDROID)
54 #include "chrome/browser/android/intent_helper.h"
55 #endif
56
57 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/profiles/profile_manager.h"
59 #include "chrome/browser/ui/chrome_pages.h"
60 #include "chrome/common/url_constants.h"
61 #endif
62
63 #if defined(OS_WIN)
64 #include "base/base_paths_win.h"
65 #include "base/path_service.h"
66 #include "base/strings/string16.h"
67 #include "base/win/windows_version.h"
68 #endif
69
70 using base::ASCIIToUTF16;
71 using base::TimeTicks;
72 using content::InterstitialPage;
73 using content::InterstitialPageDelegate; 33 using content::InterstitialPageDelegate;
74 using content::NavigationController; 34 using content::NavigationController;
75 using content::NavigationEntry; 35 using content::NavigationEntry;
76 36
77 namespace { 37 namespace {
78 38
79 const char kMetricsName[] = "bad_clock"; 39 const char kMetricsName[] = "bad_clock";
80 40
81 void LaunchDateAndTimeSettings() {
82 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
83 // The code for each OS is completely separate, in order to avoid bugs like
84 // https://crbug.com/430877 .
85 #if defined(OS_ANDROID)
86 chrome::android::OpenDateAndTimeSettings();
87
88 #elif defined(OS_CHROMEOS)
89 std::string sub_page =
90 std::string(chrome::kSearchSubPage) + "#" +
91 l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME);
92 chrome::ShowSettingsSubPageForProfile(ProfileManager::GetActiveUserProfile(),
93 sub_page);
94
95 #elif defined(OS_IOS)
96 // iOS does not have a way to launch the date and time settings.
97 NOTREACHED();
98
99 #elif defined(OS_LINUX)
100 struct ClockCommand {
101 const char* pathname;
102 const char* argument;
103 };
104 static const ClockCommand kClockCommands[] = {
105 // Unity
106 {"/usr/bin/unity-control-center", "datetime"},
107 // GNOME
108 //
109 // NOTE: On old Ubuntu, naming control panels doesn't work, so it
110 // opens the overview. This will have to be good enough.
111 {"/usr/bin/gnome-control-center", "datetime"},
112 {"/usr/local/bin/gnome-control-center", "datetime"},
113 {"/opt/bin/gnome-control-center", "datetime"},
114 // KDE
115 {"/usr/bin/kcmshell4", "clock"},
116 {"/usr/local/bin/kcmshell4", "clock"},
117 {"/opt/bin/kcmshell4", "clock"},
118 };
119
120 base::CommandLine command(base::FilePath(""));
121 for (const ClockCommand& cmd : kClockCommands) {
122 base::FilePath pathname(cmd.pathname);
123 if (base::PathExists(pathname)) {
124 command.SetProgram(pathname);
125 command.AppendArg(cmd.argument);
126 break;
127 }
128 }
129 if (command.GetProgram().empty()) {
130 // Alas, there is nothing we can do.
131 return;
132 }
133
134 base::LaunchOptions options;
135 options.wait = false;
136 options.allow_new_privs = true;
137 base::LaunchProcess(command, options);
138
139 #elif defined(OS_MACOSX)
140 base::CommandLine command(base::FilePath("/usr/bin/open"));
141 command.AppendArg("/System/Library/PreferencePanes/DateAndTime.prefPane");
142
143 base::LaunchOptions options;
144 options.wait = false;
145 base::LaunchProcess(command, options);
146
147 #elif defined(OS_WIN)
148 base::FilePath path;
149 PathService::Get(base::DIR_SYSTEM, &path);
150 static const base::char16 kControlPanelExe[] = L"control.exe";
151 path = path.Append(base::string16(kControlPanelExe));
152 base::CommandLine command(path);
153 command.AppendArg(std::string("/name"));
154 command.AppendArg(std::string("Microsoft.DateAndTime"));
155
156 base::LaunchOptions options;
157 options.wait = false;
158 base::LaunchProcess(command, options);
159
160 #else
161 NOTREACHED();
162
163 #endif
164 // Don't add code here! (See the comment at the beginning of the function.)
165 }
166
167 } // namespace 41 } // namespace
168 42
169 // static 43 // static
170 InterstitialPageDelegate::TypeID BadClockBlockingPage::kTypeForTesting = 44 InterstitialPageDelegate::TypeID BadClockBlockingPage::kTypeForTesting =
171 &BadClockBlockingPage::kTypeForTesting; 45 &BadClockBlockingPage::kTypeForTesting;
172 46
173 // Note that we always create a navigation entry with SSL errors. 47 // Note that we always create a navigation entry with SSL errors.
174 // No error happening loading a sub-resource triggers an interstitial so far. 48 // No error happening loading a sub-resource triggers an interstitial so far.
175 // Creating an interstitial without showing (e.g. from chrome://interstitials) 49 // Creating an interstitial without showing (e.g. from chrome://interstitials)
176 // it leaks memory, so don't create it here. 50 // it leaks memory, so don't create it here.
177 BadClockBlockingPage::BadClockBlockingPage( 51 BadClockBlockingPage::BadClockBlockingPage(
178 content::WebContents* web_contents, 52 content::WebContents* web_contents,
179 int cert_error, 53 int cert_error,
180 const net::SSLInfo& ssl_info, 54 const net::SSLInfo& ssl_info,
181 const GURL& request_url, 55 const GURL& request_url,
182 const base::Time& time_triggered, 56 const base::Time& time_triggered,
183 scoped_ptr<SSLCertReporter> ssl_cert_reporter, 57 scoped_ptr<SSLCertReporter> ssl_cert_reporter,
184 const base::Callback<void(bool)>& callback) 58 const base::Callback<void(bool)>& callback)
185 : SecurityInterstitialPage(web_contents, request_url), 59 : SecurityInterstitialPage(web_contents, request_url),
186 callback_(callback), 60 callback_(callback),
187 cert_error_(cert_error), 61 cert_error_(cert_error),
188 ssl_info_(ssl_info), 62 ssl_info_(ssl_info),
189 time_triggered_(time_triggered) { 63 time_triggered_(time_triggered),
64 controller_(new ChromeControllerClient(web_contents)) {
65 // Get the language for the BadClockUI.
66 std::string languages;
67 Profile* profile =
68 Profile::FromBrowserContext(web_contents->GetBrowserContext());
69 if (profile)
70 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
71
72 // Set up the metrics helper for the BadClockUI.
190 security_interstitials::MetricsHelper::ReportDetails reporting_info; 73 security_interstitials::MetricsHelper::ReportDetails reporting_info;
191 reporting_info.metric_prefix = kMetricsName; 74 reporting_info.metric_prefix = kMetricsName;
192 scoped_ptr<ChromeMetricsHelper> chrome_metrics_helper(new ChromeMetricsHelper( 75 ChromeMetricsHelper* chrome_metrics_helper = new ChromeMetricsHelper(
193 web_contents, request_url, reporting_info, kMetricsName)); 76 web_contents, request_url, reporting_info, kMetricsName);
194 chrome_metrics_helper->StartRecordingCaptivePortalMetrics(false); 77 chrome_metrics_helper->StartRecordingCaptivePortalMetrics(false);
195 set_metrics_helper(chrome_metrics_helper.Pass()); 78 scoped_ptr<security_interstitials::MetricsHelper> metrics_helper(
196 metrics_helper()->RecordUserInteraction( 79 chrome_metrics_helper);
197 security_interstitials::MetricsHelper::TOTAL_VISITS); 80 controller_->set_metrics_helper(metrics_helper.Pass());
198 81
199 cert_report_helper_.reset(new CertReportHelper( 82 cert_report_helper_.reset(new CertReportHelper(
200 ssl_cert_reporter.Pass(), web_contents, request_url, ssl_info, 83 ssl_cert_reporter.Pass(), web_contents, request_url, ssl_info,
201 certificate_reporting::ErrorReport::INTERSTITIAL_CLOCK, 84 certificate_reporting::ErrorReport::INTERSTITIAL_CLOCK,
202 false /* overridable */, metrics_helper())); 85 false /* overridable */, controller_->metrics_helper()));
203 86
204 // TODO(felt): Separate the clock statistics from the main ssl statistics. 87 bad_clock_ui_.reset(new security_interstitials::BadClockUI(
205 ssl_errors::RecordUMAStatistics(false, time_triggered_, request_url, 88 request_url, cert_error, ssl_info, time_triggered, languages,
206 cert_error_, *ssl_info_.cert.get()); 89 controller_.get()));
90 }
91
92 BadClockBlockingPage::~BadClockBlockingPage() {
93 if (!callback_.is_null()) {
94 // Deny when the page is closed.
95 NotifyDenyCertificate();
96 }
207 } 97 }
208 98
209 bool BadClockBlockingPage::ShouldCreateNewNavigation() const { 99 bool BadClockBlockingPage::ShouldCreateNewNavigation() const {
210 return true; 100 return true;
211 } 101 }
212 102
213 InterstitialPageDelegate::TypeID BadClockBlockingPage::GetTypeForTesting() 103 InterstitialPageDelegate::TypeID BadClockBlockingPage::GetTypeForTesting()
214 const { 104 const {
215 return BadClockBlockingPage::kTypeForTesting; 105 return BadClockBlockingPage::kTypeForTesting;
216 } 106 }
217 107
218 BadClockBlockingPage::~BadClockBlockingPage() { 108 void BadClockBlockingPage::AfterShow() {
219 metrics_helper()->RecordShutdownMetrics(); 109 controller_->set_interstitial_page(interstitial_page());
220 if (!callback_.is_null()) {
221 // Deny when the page is closed.
222 NotifyDenyCertificate();
223 }
224 } 110 }
225 111
226 void BadClockBlockingPage::PopulateInterstitialStrings( 112 void BadClockBlockingPage::PopulateInterstitialStrings(
227 base::DictionaryValue* load_time_data) { 113 base::DictionaryValue* load_time_data) {
228 CHECK(load_time_data); 114 bad_clock_ui_->PopulateStringsForHTML(load_time_data);
229 base::string16 url(GetFormattedHostName());
230
231 // Values that are currently still shared with the SSL interstitial.
232 load_time_data->SetString("type", "SSL");
233 load_time_data->SetString("errorCode", net::ErrorToString(cert_error_));
234 load_time_data->SetString(
235 "openDetails", l10n_util::GetStringUTF16(IDS_SSL_OPEN_DETAILS_BUTTON));
236 load_time_data->SetString(
237 "closeDetails",
238 l10n_util::GetStringUTF16(IDS_SSL_CLOSE_DETAILS_BUTTON));
239
240 // Strings for the bad clock warning specifically.
241 load_time_data->SetBoolean("bad_clock", true);
242 load_time_data->SetBoolean("overridable", false);
243 #if defined(OS_IOS)
244 load_time_data->SetBoolean("hide_primary_button", true);
245 #else
246 load_time_data->SetBoolean("hide_primary_button", false);
247 #endif
248
249 int heading_string = ssl_errors::IsUserClockInTheFuture(time_triggered_)
250 ? IDS_CLOCK_ERROR_AHEAD_HEADING
251 : IDS_CLOCK_ERROR_BEHIND_HEADING;
252
253 load_time_data->SetString("tabTitle",
254 l10n_util::GetStringUTF16(IDS_CLOCK_ERROR_TITLE));
255 load_time_data->SetString("heading",
256 l10n_util::GetStringUTF16(heading_string));
257 load_time_data->SetString(
258 "primaryParagraph",
259 l10n_util::GetStringFUTF16(
260 IDS_CLOCK_ERROR_PRIMARY_PARAGRAPH, url,
261 base::TimeFormatFriendlyDateAndTime(time_triggered_)));
262
263 load_time_data->SetString(
264 "primaryButtonText",
265 l10n_util::GetStringUTF16(IDS_CLOCK_ERROR_UPDATE_DATE_AND_TIME));
266 load_time_data->SetString(
267 "explanationParagraph",
268 l10n_util::GetStringUTF16(IDS_CLOCK_ERROR_EXPLANATION));
269
270 // The interstitial template expects this string, but we're not using it.
271 load_time_data->SetString("finalParagraph", std::string());
272
273 // Set debugging information at the bottom of the warning.
274 load_time_data->SetString("subject",
275 ssl_info_.cert->subject().GetDisplayName());
276 load_time_data->SetString("issuer",
277 ssl_info_.cert->issuer().GetDisplayName());
278 load_time_data->SetString(
279 "expirationDate",
280 base::TimeFormatShortDate(ssl_info_.cert->valid_expiry()));
281 load_time_data->SetString("currentDate",
282 base::TimeFormatShortDate(time_triggered_));
283 std::vector<std::string> encoded_chain;
284 ssl_info_.cert->GetPEMEncodedChain(&encoded_chain);
285 load_time_data->SetString(
286 "pem", base::JoinString(encoded_chain, base::StringPiece()));
287
288 cert_report_helper_->PopulateExtendedReportingOption(load_time_data); 115 cert_report_helper_->PopulateExtendedReportingOption(load_time_data);
289 } 116 }
290 117
291 void BadClockBlockingPage::OverrideEntry(NavigationEntry* entry) { 118 void BadClockBlockingPage::OverrideEntry(NavigationEntry* entry) {
292 const int process_id = web_contents()->GetRenderProcessHost()->GetID(); 119 const int process_id = web_contents()->GetRenderProcessHost()->GetID();
293 const int cert_id = content::CertStore::GetInstance()->StoreCert( 120 const int cert_id = content::CertStore::GetInstance()->StoreCert(
294 ssl_info_.cert.get(), process_id); 121 ssl_info_.cert.get(), process_id);
295 DCHECK(cert_id); 122 DCHECK(cert_id);
296 123
297 content::SignedCertificateTimestampStore* sct_store( 124 content::SignedCertificateTimestampStore* sct_store(
(...skipping 10 matching lines...) Expand all
308 content::SSLStatus(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, cert_id, 135 content::SSLStatus(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, cert_id,
309 sct_ids, ssl_info_); 136 sct_ids, ssl_info_);
310 } 137 }
311 138
312 void BadClockBlockingPage::SetSSLCertReporterForTesting( 139 void BadClockBlockingPage::SetSSLCertReporterForTesting(
313 scoped_ptr<SSLCertReporter> ssl_cert_reporter) { 140 scoped_ptr<SSLCertReporter> ssl_cert_reporter) {
314 cert_report_helper_->SetSSLCertReporterForTesting(ssl_cert_reporter.Pass()); 141 cert_report_helper_->SetSSLCertReporterForTesting(ssl_cert_reporter.Pass());
315 } 142 }
316 143
317 // This handles the commands sent from the interstitial JavaScript. 144 // This handles the commands sent from the interstitial JavaScript.
318 // DO NOT reorder or change this logic without also changing the JavaScript!
319 void BadClockBlockingPage::CommandReceived(const std::string& command) { 145 void BadClockBlockingPage::CommandReceived(const std::string& command) {
320 if (command == "\"pageLoadComplete\"") { 146 if (command == "\"pageLoadComplete\"") {
321 // content::WaitForRenderFrameReady sends this message when the page 147 // content::WaitForRenderFrameReady sends this message when the page
322 // load completes. Ignore it. 148 // load completes. Ignore it.
323 return; 149 return;
324 } 150 }
325 151
326 int cmd = 0; 152 int cmd = 0;
327 bool retval = base::StringToInt(command, &cmd); 153 bool retval = base::StringToInt(command, &cmd);
328 DCHECK(retval); 154 DCHECK(retval);
329 switch (cmd) { 155
330 case security_interstitials::CMD_DONT_PROCEED: 156 bad_clock_ui_->HandleCommand(
331 interstitial_page()->DontProceed(); 157 static_cast<security_interstitials::SecurityInterstitialCommands>(cmd));
332 break;
333 case security_interstitials::CMD_DO_REPORT:
334 SetReportingPreference(true);
335 break;
336 case security_interstitials::CMD_DONT_REPORT:
337 SetReportingPreference(false);
338 break;
339 case security_interstitials::CMD_SHOW_MORE_SECTION:
340 metrics_helper()->RecordUserInteraction(
341 security_interstitials::MetricsHelper::SHOW_ADVANCED);
342 break;
343 case security_interstitials::CMD_OPEN_DATE_SETTINGS:
344 metrics_helper()->RecordUserInteraction(
345 security_interstitials::MetricsHelper::OPEN_TIME_SETTINGS);
346 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
347 base::Bind(&LaunchDateAndTimeSettings));
348 break;
349 case security_interstitials::CMD_OPEN_REPORTING_PRIVACY:
350 OpenExtendedReportingPrivacyPolicy();
351 break;
352 case security_interstitials::CMD_PROCEED:
353 case security_interstitials::CMD_OPEN_HELP_CENTER:
354 case security_interstitials::CMD_RELOAD:
355 case security_interstitials::CMD_OPEN_DIAGNOSTIC:
356 // Not supported for the bad clock interstitial.
357 NOTREACHED() << "Unexpected command: " << command;
358 }
359 } 158 }
360 159
361 void BadClockBlockingPage::OverrideRendererPrefs( 160 void BadClockBlockingPage::OverrideRendererPrefs(
362 content::RendererPreferences* prefs) { 161 content::RendererPreferences* prefs) {
363 Profile* profile = 162 Profile* profile =
364 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 163 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
365 renderer_preferences_util::UpdateFromSystemSettings(prefs, profile, 164 renderer_preferences_util::UpdateFromSystemSettings(prefs, profile,
366 web_contents()); 165 web_contents());
367 } 166 }
368 167
369 void BadClockBlockingPage::OnDontProceed() { 168 void BadClockBlockingPage::OnDontProceed() {
370 cert_report_helper_->FinishCertCollection( 169 cert_report_helper_->FinishCertCollection(
371 certificate_reporting::ErrorReport::USER_DID_NOT_PROCEED); 170 certificate_reporting::ErrorReport::USER_DID_NOT_PROCEED);
372 NotifyDenyCertificate(); 171 NotifyDenyCertificate();
373 } 172 }
374 173
375 void BadClockBlockingPage::NotifyDenyCertificate() { 174 void BadClockBlockingPage::NotifyDenyCertificate() {
376 // It's possible that callback_ may not exist if the user clicks "Proceed" 175 // It's possible that callback_ may not exist if the user clicks "Proceed"
377 // followed by pressing the back button before the interstitial is hidden. 176 // followed by pressing the back button before the interstitial is hidden.
378 // In that case the certificate will still be treated as allowed. 177 // In that case the certificate will still be treated as allowed.
379 if (callback_.is_null()) 178 if (callback_.is_null())
380 return; 179 return;
381 180
382 base::ResetAndReturn(&callback_).Run(false); 181 base::ResetAndReturn(&callback_).Run(false);
383 } 182 }
OLDNEW
« no previous file with comments | « chrome/browser/ssl/bad_clock_blocking_page.h ('k') | chrome/browser/ssl/captive_portal_blocking_page.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698