Merge lp:~chrisccoulson/oxide/lp1504853 into lp:~oxide-developers/oxide/oxide.trunk

Proposed by Chris Coulson on 2015-10-15
Status: Merged
Merged at revision: 1232
Proposed branch: lp:~chrisccoulson/oxide/lp1504853
Merge into: lp:~oxide-developers/oxide/oxide.trunk
Diff against target: 2354 lines (+1100/-732)
22 files modified
qt/core/api/oxideqcertificateerror.cc (+3/-3)
qt/core/browser/oxide_qt_web_view.cc (+16/-9)
qt/core/browser/oxide_qt_web_view.h (+5/-1)
qt/tests/qmltests/ssl/tst_CertificateError.qml (+329/-217)
qt/tests/qmltests/ssl/tst_CertificateError_initial.html (+5/-0)
shared/browser/oxide_content_browser_client.cc (+21/-21)
shared/browser/oxide_web_frame_tree.cc (+6/-0)
shared/browser/oxide_web_view.cc (+28/-80)
shared/browser/oxide_web_view.h (+0/-26)
shared/browser/oxide_web_view_client.cc (+0/-2)
shared/browser/oxide_web_view_client.h (+0/-2)
shared/browser/oxide_web_view_contents_helper.cc (+7/-1)
shared/browser/ssl/oxide_certificate_error.cc (+50/-268)
shared/browser/ssl/oxide_certificate_error.h (+20/-100)
shared/browser/ssl/oxide_certificate_error_dispatcher.cc (+196/-0)
shared/browser/ssl/oxide_certificate_error_dispatcher.h (+77/-0)
shared/browser/ssl/oxide_certificate_error_dispatcher_client.h (+36/-0)
shared/browser/ssl/oxide_certificate_error_placeholder_page.cc (+58/-0)
shared/browser/ssl/oxide_certificate_error_placeholder_page.h (+64/-0)
shared/browser/ssl/oxide_certificate_error_proxy.cc (+105/-0)
shared/browser/ssl/oxide_certificate_error_proxy.h (+65/-0)
shared/shared.gyp (+9/-2)
To merge this branch: bzr merge lp:~chrisccoulson/oxide/lp1504853
Reviewer Review Type Date Requested Status
Chris Coulson Pending
Review via email: mp+274525@code.launchpad.net
To post a comment you must log in.
lp:~chrisccoulson/oxide/lp1504853 updated on 2015-10-21
1218. By Chris Coulson on 2015-10-15

Remove spurious printf

1219. By Chris Coulson on 2015-10-15

Add missing file

1220. By Chris Coulson on 2015-10-15

Add missing file

1221. By Chris Coulson on 2015-10-20

Merge from trunk

1222. By Chris Coulson on 2015-10-21

Merge from trunk

1223. By Chris Coulson on 2015-10-21

Merge from trunk

1224. By Chris Coulson on 2015-10-21

Remove unnecessary DCHECK

1225. By Chris Coulson on 2015-10-21

Fix a test crash

1226. By Chris Coulson on 2015-10-21

Merge from trunk

1227. By Chris Coulson on 2015-10-21

Merge from trunk

1228. By Chris Coulson on 2015-10-21

Clean up WebFrameTreeObserver

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qt/core/api/oxideqcertificateerror.cc'
2--- qt/core/api/oxideqcertificateerror.cc 2015-07-02 15:53:48 +0000
3+++ qt/core/api/oxideqcertificateerror.cc 2015-10-21 20:26:37 +0000
4@@ -27,8 +27,8 @@
5 #include "base/macros.h"
6 #include "net/cert/x509_certificate.h"
7
8-#include "shared/browser/oxide_certificate_error.h"
9 #include "shared/browser/oxide_security_types.h"
10+#include "shared/browser/ssl/oxide_certificate_error.h"
11
12 #include "oxideqsslcertificate_p.h"
13
14@@ -58,7 +58,7 @@
15 return;
16 }
17
18- if (error_->is_cancelled()) {
19+ if (error_->IsCancelled()) {
20 qWarning() << "Cannot respond to a CertificateError that has been cancelled";
21 return;
22 }
23@@ -138,7 +138,7 @@
24 bool OxideQCertificateError::isCancelled() const {
25 Q_D(const OxideQCertificateError);
26
27- return d->error_->is_cancelled();
28+ return d->error_->IsCancelled();
29 }
30
31 bool OxideQCertificateError::isMainFrame() const {
32
33=== modified file 'qt/core/browser/oxide_qt_web_view.cc'
34--- qt/core/browser/oxide_qt_web_view.cc 2015-10-21 17:09:06 +0000
35+++ qt/core/browser/oxide_qt_web_view.cc 2015-10-21 20:26:37 +0000
36@@ -81,6 +81,8 @@
37 #include "shared/browser/oxide_web_view.h"
38 #include "shared/browser/permissions/oxide_permission_request.h"
39 #include "shared/browser/permissions/oxide_permission_request_dispatcher.h"
40+#include "shared/browser/ssl/oxide_certificate_error.h"
41+#include "shared/browser/ssl/oxide_certificate_error_dispatcher.h"
42 #include "shared/common/oxide_enum_flags.h"
43
44 #include "oxide_qt_file_picker.h"
45@@ -408,6 +410,8 @@
46 void WebView::CommonInit(OxideQFindController* find_controller) {
47 content::WebContents* contents = view_->GetWebContents();
48
49+ oxide::CertificateErrorDispatcher::FromWebContents(
50+ contents)->set_client(this);
51 oxide::PermissionRequestDispatcher::FromWebContents(
52 contents)->set_client(this);
53 OxideQSecurityStatusPrivate::get(security_status_)->view = this;
54@@ -854,14 +858,6 @@
55 OxideQSecurityStatusPrivate::get(security_status_)->Update(old);
56 }
57
58-void WebView::OnCertificateError(scoped_ptr<oxide::CertificateError> error) {
59- scoped_ptr<OxideQCertificateError> qerror(
60- OxideQCertificateErrorPrivate::Create(error.Pass()));
61-
62- // Embedder takes ownership of qerror
63- client_->CertificateError(qerror.release());
64-}
65-
66 void WebView::ContentBlocked() {
67 client_->ContentBlocked();
68 }
69@@ -952,6 +948,14 @@
70 f->client()->LoadCommitted();
71 }
72
73+void WebView::OnCertificateError(scoped_ptr<oxide::CertificateError> error) {
74+ scoped_ptr<OxideQCertificateError> qerror(
75+ OxideQCertificateErrorPrivate::Create(error.Pass()));
76+
77+ // Embedder takes ownership of qerror
78+ client_->CertificateError(qerror.release());
79+}
80+
81 QUrl WebView::url() const {
82 return QUrl(QString::fromStdString(view_->GetURL().spec()));
83 }
84@@ -1428,12 +1432,15 @@
85 }
86
87 WebView::~WebView() {
88+ content::WebContents* contents = view_->GetWebContents();
89+ oxide::CertificateErrorDispatcher::FromWebContents(
90+ contents)->set_client(nullptr);
91 DCHECK(frame_tree_torn_down_);
92
93 input_method_context_->DetachClient();
94
95 oxide::PermissionRequestDispatcher::FromWebContents(
96- view_->GetWebContents())->set_client(nullptr);
97+ contents)->set_client(nullptr);
98 }
99
100 // static
101
102=== modified file 'qt/core/browser/oxide_qt_web_view.h'
103--- qt/core/browser/oxide_qt_web_view.h 2015-10-21 16:44:08 +0000
104+++ qt/core/browser/oxide_qt_web_view.h 2015-10-21 20:26:37 +0000
105@@ -34,6 +34,7 @@
106 #include "shared/browser/oxide_web_view_client.h"
107 #include "shared/browser/oxide_web_frame_tree_observer.h"
108 #include "shared/browser/permissions/oxide_permission_request_dispatcher_client.h"
109+#include "shared/browser/ssl/oxide_certificate_error_dispatcher_client.h"
110
111 QT_BEGIN_NAMESPACE
112 class QFocusEvent;
113@@ -61,6 +62,7 @@
114 public oxide::WebViewClient,
115 public oxide::PermissionRequestDispatcherClient,
116 public oxide::WebFrameTreeObserver,
117+ public oxide::CertificateErrorDispatcherClient,
118 public WebViewProxy {
119 public:
120 WebView(WebViewProxyClient* client,
121@@ -166,7 +168,6 @@
122 oxide::InputMethodContext* GetInputMethodContext() const override;
123 void UpdateCursor(const content::WebCursor& cursor) override;
124 void SecurityStatusChanged(const oxide::SecurityStatus& old) override;
125- void OnCertificateError(scoped_ptr<oxide::CertificateError> error) override;
126 void ContentBlocked() override;
127 void PrepareToCloseResponseReceived(bool proceed) override;
128 void CloseRequested() override;
129@@ -189,6 +190,9 @@
130 void FrameDeleted(oxide::WebFrame* frame) override;
131 void LoadCommittedInFrame(oxide::WebFrame* frame) override;
132
133+ // oxide::CertificateErrorDispatcherClient implementation
134+ void OnCertificateError(scoped_ptr<oxide::CertificateError> error) override;
135+
136 // WebViewProxy implementation
137 QUrl url() const override;
138 void setUrl(const QUrl& url) override;
139
140=== modified file 'qt/tests/qmltests/ssl/tst_CertificateError.qml'
141--- qt/tests/qmltests/ssl/tst_CertificateError.qml 2015-06-22 22:57:01 +0000
142+++ qt/tests/qmltests/ssl/tst_CertificateError.qml 2015-10-21 20:26:37 +0000
143@@ -19,11 +19,22 @@
144 signalName: "cancelled"
145 }
146
147+ SignalSpy {
148+ id: urlSpy
149+ target: webView
150+ signalName: "urlChanged"
151+ }
152+
153+ SignalSpy {
154+ id: titleSpy
155+ target: webView
156+ signalName: "titleChanged"
157+ }
158+
159 property var certError: null
160
161 onCertificateError: {
162 if (certError) {
163- error.allow();
164 return;
165 }
166 certError = error;
167@@ -38,23 +49,16 @@
168 spy.clear();
169 cancelSpy.target = null;
170 cancelSpy.clear();
171+ urlSpy.clear();
172+ titleSpy.clear();
173 certError = null;
174 webView.clearLoadEventCounters();
175 }
176
177- function test_CertificateError1_denials_data() {
178+ function test_CertificateError1_subresource_deny_data() {
179 function _verify_1() {
180 // This verifies that either there is no document or it is an error page
181 try {
182- compare(webView.getTestApi().documentURI, "data:text/html,chromewebdata");
183- } catch(e) {
184- compare(e.error, ScriptMessageRequest.ErrorDestinationNotFound);
185- }
186- }
187-
188- function _verify_2() {
189- // This verifies that either there is no document or it is an error page
190- try {
191 compare(webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).documentURI,
192 "data:text/html,chromewebdata");
193 } catch(e) {
194@@ -62,15 +66,15 @@
195 }
196 }
197
198+ function _verify_2() {
199+ var colour = webView.getTestApi().evaluateCode("
200+var elem = document.getElementById(\"foo\");
201+var style = window.getComputedStyle(elem);
202+return style.getPropertyValue(\"color\");", true);
203+ compare(colour, "rgb(0, 0, 0)");
204+ }
205+
206 function _verify_3() {
207- var colour = webView.getTestApi().evaluateCode("
208-var elem = document.getElementById(\"foo\");
209-var style = window.getComputedStyle(elem);
210-return style.getPropertyValue(\"color\");", true);
211- compare(colour, "rgb(0, 0, 0)");
212- }
213-
214- function _verify_4() {
215 var colour = webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).evaluateCode("
216 var elem = document.getElementById(\"foo\");
217 var style = window.getComputedStyle(elem);
218@@ -81,234 +85,342 @@
219 // FIXME: Test overridable and strictEnforcement properties
220 return [
221 {
222- loadUrl: "https://expired.testsuite/tst_CertificateError_broken_iframe.html",
223- url: "https://expired.testsuite/tst_CertificateError_broken_iframe.html",
224- mainframe: true, subresource: false, overridable: true,
225- strictEnforcement: false, error: CertificateError.ErrorExpired,
226- certificate: "df17c8da033e2d5ed64d1f187fdf419e1fc68e47",
227- verifyFunc: _verify_1
228- },
229- {
230 loadUrl: "https://testsuite/tst_CertificateError_broken_iframe.html",
231 url: "https://selfsigned.testsuite/empty.html",
232- mainframe: false, subresource: false, overridable: false,
233+ mainframe: false, subresource: false,
234 strictEnforcement: false, error: CertificateError.ErrorAuthorityInvalid,
235 certificate: "f0357f544e27adaa51211663a28cc8d64b057e63",
236+ verifyFunc: _verify_1
237+ },
238+ {
239+ loadUrl: "https://testsuite/tst_CertificateError_broken_subresource.html",
240+ url: "https://badidentity.testsuite/tst_CertificateError_broken_subresource.css",
241+ mainframe: true, subresource: true,
242+ strictEnforcement: false, error: CertificateError.ErrorBadIdentity,
243+ certificate: "89c5760286e897ad32b9dd500d70755e1e026588",
244 verifyFunc: _verify_2
245 },
246 {
247- loadUrl: "https://testsuite/tst_CertificateError_broken_subresource.html",
248+ loadUrl: "https://testsuite/tst_CertificateError_broken_subresource_in_iframe.html",
249 url: "https://badidentity.testsuite/tst_CertificateError_broken_subresource.css",
250- mainframe: true, subresource: true, overridable: false,
251+ mainframe: false, subresource: true,
252 strictEnforcement: false, error: CertificateError.ErrorBadIdentity,
253 certificate: "89c5760286e897ad32b9dd500d70755e1e026588",
254 verifyFunc: _verify_3
255- },
256- {
257- loadUrl: "https://testsuite/tst_CertificateError_broken_subresource_in_iframe.html",
258- url: "https://badidentity.testsuite/tst_CertificateError_broken_subresource.css",
259- mainframe: false, subresource: true, overridable: false,
260- strictEnforcement: false, error: CertificateError.ErrorBadIdentity,
261- certificate: "89c5760286e897ad32b9dd500d70755e1e026588",
262- verifyFunc: _verify_4
263 }
264 ];
265 }
266
267- // Verify that CertificateError.deny() works correctly, and check that other
268- // properties behave as expected
269- function test_CertificateError1_denials(data) {
270+ // This tests CertificateError for various subresource errors, and verifies
271+ // that those subresources are always blocked
272+ function test_CertificateError1_subresource_deny(data) {
273 webView.url = data.loadUrl;
274+ verify(webView.waitForLoadSucceeded());
275+
276 spy.wait();
277
278+ if (!data.mainframe) {
279+ // This is a bit of a hack, but we don't have another event we can
280+ // fire off for subframe loads
281+ wait(100);
282+ }
283+
284 compare(certError.url, data.url);
285 verify(!certError.isCancelled);
286 compare(certError.isMainFrame, data.mainframe);
287 compare(certError.isSubresource, data.subresource);
288+ compare(certError.overridable, false);
289+ compare(certError.strictEnforcement, data.strictEnforcement);
290+ compare(certError.certError, data.error);
291+ compare(certError.certificate.fingerprintSHA1, data.certificate);
292+
293+ compare(webView.url, data.loadUrl);
294+
295+ compare(webView.securityStatus.securityLevel,SecurityStatus.SecurityLevelSecure);
296+ compare(webView.securityStatus.contentStatus, SecurityStatus.ContentStatusNormal);
297+ compare(webView.securityStatus.certStatus, SecurityStatus.CertStatusOk);
298+
299+ data.verifyFunc();
300+
301+ // There's nothing to deny, but it shouldn't crash
302+ certError.deny();
303+ }
304+
305+ function test_CertificateError2_mainframe_deny_data() {
306+ function _verify_1() {
307+ // This verifies that the old document still exists
308+ compare(webView.getTestApi().documentURI, "https://testsuite/tst_CertificateError_initial.html");
309+ }
310+
311+ // FIXME: Test non-overridable errors too
312+ return [
313+ {
314+ loadUrl: "https://expired.testsuite/empty.html",
315+ overridable: true,
316+ strictEnforcement: false, error: CertificateError.ErrorExpired,
317+ certificate: "df17c8da033e2d5ed64d1f187fdf419e1fc68e47",
318+ verifyFunc: _verify_1
319+ },
320+ ];
321+
322+ }
323+
324+ // This test CertificateError for main frame errors, and verifies that
325+ // calling deny() blocks them
326+ function test_CertificateError2_mainframe_deny(data) {
327+ webView.url = "https://testsuite/tst_CertificateError_initial.html";
328+ verify(webView.waitForLoadSucceeded());
329+
330+ compare(webView.title, "Test");
331+
332+ webView.clearLoadEventCounters();
333+ titleSpy.clear();
334+
335+ webView.url = data.loadUrl;
336+ spy.wait();
337+ titleSpy.wait();
338+ if (!data.overridable) {
339+ verify(webView.waitForLoadStopped());
340+ }
341+
342+ compare(certError.url, data.loadUrl);
343+ verify(!certError.isCancelled);
344+ compare(certError.isMainFrame, true);
345+ compare(certError.isSubresource, false);
346 compare(certError.overridable, data.overridable);
347 compare(certError.strictEnforcement, data.strictEnforcement);
348 compare(certError.certError, data.error);
349 compare(certError.certificate.fingerprintSHA1, data.certificate);
350
351+ compare(webView.loadsStartedCount, 1);
352+ compare(webView.loadsCommittedCount, 0);
353+ compare(webView.loadsFailedCount, 0);
354+ compare(webView.loadsSucceededCount, 0);
355+
356+ // WebView.url should indicate the URL of the failing resource even for
357+ // non-overridable errors, as we show a placeholder transient page
358+ compare(webView.url, data.loadUrl);
359+ compare(webView.title, data.loadUrl);
360+
361+ data.verifyFunc();
362+
363+ urlSpy.clear();
364+ titleSpy.clear();
365+
366 certError.deny();
367
368- if (data.mainframe && !data.subresource) {
369- verify(webView.waitForLoadStopped());
370- compare(webView.loadsFailedCount, 0);
371- compare(webView.loadsStoppedCount, 1);
372- compare(webView.loadsSucceededCount, 0);
373- } else {
374+ if (data.overridable) {
375+ verify(webView.waitForLoadStopped());
376+ }
377+ urlSpy.wait();
378+ titleSpy.wait();
379+
380+ compare(webView.url, "https://testsuite/tst_CertificateError_initial.html");
381+ compare(webView.title, "Test");
382+
383+ data.verifyFunc();
384+ }
385+
386+ function test_CertificateError3_subresource_allow_data() {
387+ function _verify_1() {
388+ // This verifies that either there is no document or it is an error page
389+ try {
390+ compare(webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).documentURI,
391+ "data:text/html,chromewebdata");
392+ } catch(e) {
393+ compare(e.error, ScriptMessageRequest.ErrorDestinationNotFound);
394+ }
395+ }
396+
397+ function _verify_2() {
398+ var colour = webView.getTestApi().evaluateCode("
399+var elem = document.getElementById(\"foo\");
400+var style = window.getComputedStyle(elem);
401+return style.getPropertyValue(\"color\");", true);
402+ compare(colour, "rgb(0, 0, 0)");
403+ }
404+
405+ function _verify_3() {
406+ var colour = webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).evaluateCode("
407+var elem = document.getElementById(\"foo\");
408+var style = window.getComputedStyle(elem);
409+return style.getPropertyValue(\"color\");", true);
410+ compare(colour, "rgb(0, 0, 0)");
411+ }
412+
413+ return [
414+ {
415+ loadUrl: "https://testsuite/tst_CertificateError_broken_iframe.html",
416+ verifyFunc: _verify_1
417+ },
418+ {
419+ loadUrl: "https://testsuite/tst_CertificateError_broken_subresource.html",
420+ verifyFunc: _verify_2
421+ },
422+ {
423+ loadUrl: "https://testsuite/tst_CertificateError_broken_subresource_in_iframe.html",
424+ verifyFunc: _verify_3
425+ }
426+ ];
427+ }
428+
429+ // Verifies that calling allow() on subresource errors cannot override
430+ // them
431+ function test_CertificateError3_subresource_allow(data) {
432+ webView.url = data.loadUrl;
433+ verify(webView.waitForLoadSucceeded());
434+
435+ spy.wait();
436+
437+ certError.allow();
438+
439+ // This is a bit of a hack, but we don't have another event we can fire off
440+ wait(100);
441+
442+ data.verifyFunc();
443+ }
444+
445+ function test_CertificateError4_mainframe_allow_data() {
446+ function _verify_1() {
447+ compare(webView.getTestApi().documentURI, "https://expired.testsuite/empty.html");
448+ }
449+
450+ // FIXME: Test non-overridable errors too
451+ return [
452+ {
453+ loadUrl: "https://expired.testsuite/empty.html",
454+ overridable: true, verifyFunc: _verify_1
455+ },
456+ ];
457+ }
458+
459+ // Verifies that calling allow() on overridable main frame errors allows
460+ // the page to continue loading
461+ function test_CertificateError4_mainframe_allow(data) {
462+ webView.url = "https://testsuite/tst_CertificateError_initial.html";
463+ verify(webView.waitForLoadSucceeded());
464+
465+ webView.clearLoadEventCounters();
466+
467+ webView.url = data.loadUrl;
468+ spy.wait();
469+ if (!data.overridable) {
470+ verify(webView.waitForLoadStopped());
471+ }
472+
473+ compare(webView.loadsStartedCount, 1);
474+ compare(webView.loadsCommittedCount, 0);
475+ compare(webView.loadsFailedCount, 0);
476+ compare(webView.loadsSucceededCount, 0);
477+
478+ certError.allow();
479+
480+ if (data.overridable) {
481 verify(webView.waitForLoadSucceeded());
482- if (!data.mainframe) {
483- // This is a bit of a hack, but we don't have another event we can
484- // fire off for subframe loads
485- wait(100);
486- }
487- }
488-
489- compare(webView.securityStatus.securityLevel,
490- data.mainframe && !data.subresource ?
491- SecurityStatus.SecurityLevelNone : SecurityStatus.SecurityLevelSecure);
492- compare(webView.securityStatus.contentStatus, SecurityStatus.ContentStatusNormal);
493- compare(webView.securityStatus.certStatus, SecurityStatus.CertStatusOk);
494-
495- data.verifyFunc();
496- }
497-
498- function test_CertificateError2_allow_data() {
499- function _verify_1() {
500- compare(webView.getTestApi().documentURI, "https://expired.testsuite/tst_CertificateError_broken_iframe.html");
501- }
502-
503- function _verify_2() {
504- // This verifies that either there is no document or it is an error page
505- try {
506- compare(webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).documentURI,
507- "data:text/html,chromewebdata");
508- } catch(e) {
509- compare(e.error, ScriptMessageRequest.ErrorDestinationNotFound);
510- }
511- }
512-
513- function _verify_3() {
514- var colour = webView.getTestApi().evaluateCode("
515-var elem = document.getElementById(\"foo\");
516-var style = window.getComputedStyle(elem);
517-return style.getPropertyValue(\"color\");", true);
518- compare(colour, "rgb(0, 0, 0)");
519- }
520-
521- function _verify_4() {
522- var colour = webView.getTestApiForFrame(webView.rootFrame.childFrames[0]).evaluateCode("
523-var elem = document.getElementById(\"foo\");
524-var style = window.getComputedStyle(elem);
525-return style.getPropertyValue(\"color\");", true);
526- compare(colour, "rgb(0, 0, 0)");
527- }
528-
529- return [
530- {
531- loadUrl: "https://expired.testsuite/tst_CertificateError_broken_iframe.html",
532- mainframe: true, overridable: true, verifyFunc: _verify_1
533- },
534- {
535- loadUrl: "https://testsuite/tst_CertificateError_broken_iframe.html",
536- mainframe: false, overridable: false, verifyFunc: _verify_2
537- },
538- {
539- loadUrl: "https://testsuite/tst_CertificateError_broken_subresource.html",
540- mainframe: false, overridable: false, verifyFunc: _verify_3
541- },
542- {
543- loadUrl: "https://testsuite/tst_CertificateError_broken_subresource_in_iframe.html",
544- mainframe: false, overridable: false, verifyFunc: _verify_4
545- }
546- ];
547- }
548-
549- // Verify that CertificateError.allow works correctly for overridable errors
550- function test_CertificateError2_allow(data) {
551- webView.url = data.loadUrl;
552- spy.wait();
553-
554- certError.allow();
555-
556- verify(webView.waitForLoadSucceeded());
557-
558- if (data.mainframe) {
559- compare(webView.loadsFailedCount, 0);
560- compare(webView.loadsStoppedCount, 0);
561- compare(webView.loadsSucceededCount, 1);
562- } else {
563- // This is a bit of a hack, but we don't have another event we can fire off
564- wait(100);
565- }
566-
567- data.verifyFunc();
568- }
569-
570- function test_CertificateError3_cancellation_data() {
571- // Test that starting a new load cancels pending frame errors
572- function _action_1() {
573- webView.url = "http://testsuite/empty.html";
574- verify(webView.waitForLoadStarted());
575- }
576-
577- // Test that stopping a load cancels pending frame errors
578- function _action_2() {
579- webView.stop();
580- verify(webView.waitForLoadStopped());
581- }
582-
583- // Test that committing a load cancels non-overridable frame errors
584- function _action_3() {
585- var frame = webView.rootFrame.childFrames[0];
586- webView.getTestApiForFrame(frame).evaluateCode(
587- "window.location = \"https://testsuite/empty.html\";",
588- true);
589- TestUtils.waitFor(function() { return frame.url == "https://testsuite/empty.html" });
590- }
591-
592- // Test that deleting a frame cancels errors
593- function _action_4() {
594- var frame = webView.rootFrame.childFrames[0];
595- var obs = Utils.createDestructionObserver(frame);
596- webView.getTestApi().evaluateCode("
597-var f = document.getElementsByTagName(\"iframe\")[0];
598-f.parentElement.removeChild(f);", true);
599- TestUtils.waitFor(function() { return obs.destroyed; });
600- }
601-
602- // Test that interrupting a load before it's committed doesn't cancel
603- // subresource errors
604- function _action_5() {
605- var savedError = certError;
606- certError = null;
607-
608- webView.url = "https://expired.testsuite/empty.html";
609- spy.wait();
610- webView.stop();
611- verify(webView.waitForLoadStopped());
612-
613- certError = savedError;
614- }
615-
616- // Test that committing a load cancels subresource errors
617- function _action_6() {
618- webView.url = "https://testsuite/empty.html";
619- verify(webView.waitForLoadCommitted());
620- }
621-
622- return [
623- { url: "https://expired.testsuite/tst_CertificateError_broken_iframe.html",
624- action: _action_1, expectCancel: true },
625- { url: "https://expired.testsuite/tst_CertificateError_broken_iframe.html",
626- action: _action_2, expectCancel: true },
627- { url: "https://testsuite/tst_CertificateError_broken_iframe.html",
628- action: _action_3, expectCancel: true },
629- { url: "https://testsuite/tst_CertificateError_broken_iframe.html",
630- action: _action_4, expectCancel: true },
631- { url: "https://testsuite/tst_CertificateError_broken_subresource.html",
632- action: _action_5, expectCancel: false },
633- { url: "https://testsuite/tst_CertificateError_broken_subresource.html",
634- action: _action_6, expectCancel: true }
635- ];
636- }
637-
638- // Verify that CertificateError cancellation works as expected
639- function test_CertificateError3_cancellation(data) {
640- webView.url = data.url;
641- spy.wait();
642-
643- verify(!certError.isCancelled);
644-
645- cancelSpy.target = certError;
646-
647- webView.clearLoadEventCounters();
648- data.action();
649-
650- compare(certError.isCancelled, data.expectCancel);
651- compare(cancelSpy.count, data.expectCancel ? 1 : 0);
652+ }
653+
654+ data.verifyFunc();
655+ }
656+
657+ function test_CertificateError5_cancellation_browser_initiated_navigation_data() {
658+ // Test non-overridable too
659+ return [
660+ { loadUrl: "https://badidentity.testsuite/empty.html", overridable: true }
661+ ];
662+ }
663+
664+ // Verify that main frame errors are cancelled on a browser-initiated navigation
665+ function test_CertificateError5_cancellation_browser_initiated_navigation(data) {
666+ webView.url = "https://testsuite/empty.html";
667+ verify(webView.waitForLoadSucceeded());
668+
669+ webView.url = data.loadUrl;
670+ spy.wait();
671+ if (!data.overridable) {
672+ verify(webView.waitForLoadStopped());
673+ }
674+
675+ cancelSpy.target = certError;
676+ verify(!certError.isCancelled);
677+
678+ webView.clearLoadEventCounters();
679+
680+ webView.url = "https://foo.testsuite/empty.html";
681+ verify(webView.waitForLoadCommitted());
682+
683+ compare(cancelSpy.count, 1);
684+ verify(certError.isCancelled);
685+
686+ verify(webView.waitForLoadSucceeded());
687+ compare(webView.url, "https://foo.testsuite/empty.html");
688+ }
689+
690+ function test_CertificateError6_cancellation_history_navigation_data() {
691+ return test_CertificateError5_cancellation_browser_initiated_navigation_data();
692+ }
693+
694+ function test_CertificateError6_cancellation_history_navigation(data) {
695+ webView.url = "https://testsuite/empty.html";
696+ verify(webView.waitForLoadSucceeded());
697+
698+ webView.url = data.loadUrl;
699+ spy.wait();
700+ if (!data.overridable) {
701+ verify(webView.waitForLoadStopped());
702+ }
703+
704+ cancelSpy.target = certError;
705+ verify(!certError.isCancelled);
706+
707+ urlSpy.clear();
708+
709+ // FIXME(chrisccoulson): The test fails without the delay - cancellation
710+ // never happens. I suspect this is because we go back before getting
711+ // the commit from the renderer, which means that the interstitial is
712+ // not attached to the WebContents and DontProceed doesn't get called
713+ wait(100);
714+
715+ webView.goBack();
716+ // There's no new load here, so just wait for the URL to change back
717+ urlSpy.wait();
718+ cancelSpy.wait();
719+
720+ compare(cancelSpy.count, 1);
721+ verify(certError.isCancelled);
722+ compare(webView.url, "https://testsuite/empty.html");
723+ }
724+
725+ function test_CertificateError7_content_initiated_navigation_data() {
726+ return test_CertificateError5_cancellation_browser_initiated_navigation_data();
727+ }
728+
729+ function test_CertificateError7_content_initiated_navigation(data) {
730+ webView.url = "https://testsuite/tst_CertificateError_initial.html";
731+ verify(webView.waitForLoadSucceeded());
732+
733+ urlSpy.clear();
734+ titleSpy.clear();
735+ webView.clearLoadEventCounters();
736+
737+ webView.getTestApi().evaluateCode("window.location = \"" + data.loadUrl + "\";");
738+ spy.wait();
739+ urlSpy.wait();
740+ titleSpy.wait();
741+ if (!data.overridable) {
742+ verify(webView.waitForLoadStopped());
743+ }
744+
745+ compare(webView.loadsStartedCount, 1);
746+ compare(webView.loadsCommittedCount, 0);
747+ compare(webView.loadsFailedCount, 0);
748+ compare(webView.loadsSucceededCount, 0);
749+
750+ compare(webView.url, data.loadUrl);
751+ compare(webView.loadsStartedCount, 1);
752+ compare(webView.loadsCommittedCount, 0);
753+ compare(webView.loadsFailedCount, 0);
754+ compare(webView.loadsSucceededCount, 0);
755+ compare(webView.title, data.loadUrl);
756 }
757 }
758 }
759
760=== added file 'qt/tests/qmltests/ssl/tst_CertificateError_initial.html'
761--- qt/tests/qmltests/ssl/tst_CertificateError_initial.html 1970-01-01 00:00:00 +0000
762+++ qt/tests/qmltests/ssl/tst_CertificateError_initial.html 2015-10-21 20:26:37 +0000
763@@ -0,0 +1,5 @@
764+<html>
765+<head>
766+ <title>Test</title>
767+</head>
768+</html>
769
770=== modified file 'shared/browser/oxide_content_browser_client.cc'
771--- shared/browser/oxide_content_browser_client.cc 2015-10-07 01:36:57 +0000
772+++ shared/browser/oxide_content_browser_client.cc 2015-10-21 20:26:37 +0000
773@@ -36,6 +36,7 @@
774 #include "shared/browser/compositor/oxide_compositor_utils.h"
775 #include "shared/browser/media/oxide_media_capture_devices_dispatcher.h"
776 #include "shared/browser/notifications/oxide_platform_notification_service.h"
777+#include "shared/browser/ssl/oxide_certificate_error_dispatcher.h"
778 #include "shared/common/oxide_constants.h"
779 #include "shared/common/oxide_content_client.h"
780 #include "shared/common/oxide_form_factor.h"
781@@ -169,25 +170,16 @@
782 bool expired_previous_decision,
783 const base::Callback<void(bool)>& callback,
784 content::CertificateRequestResultType* result) {
785- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
786-
787- content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
788- render_process_id, render_frame_id);
789- if (!rfh) {
790- *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
791- return;
792- }
793-
794- WebView* webview = WebView::FromRenderFrameHost(rfh);
795- if (!webview) {
796- *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
797- return;
798- }
799-
800- webview->AllowCertificateError(rfh, cert_error, ssl_info, request_url,
801- resource_type, overridable,
802- strict_enforcement, callback,
803- result);
804+ CertificateErrorDispatcher::AllowCertificateError(render_process_id,
805+ render_frame_id,
806+ cert_error,
807+ ssl_info,
808+ request_url,
809+ resource_type,
810+ overridable,
811+ strict_enforcement,
812+ callback,
813+ result);
814 }
815
816 content::MediaObserver* ContentBrowserClient::GetMediaObserver() {
817@@ -241,7 +233,13 @@
818 WebViewContentsHelper* contents_helper =
819 WebViewContentsHelper::FromRenderViewHost(render_view_host);
820
821- WebPreferences* web_prefs = contents_helper->GetWebPreferences();
822+ WebPreferences* web_prefs = nullptr;
823+ if (contents_helper) {
824+ // If RVH is for an InterstitialPage, we can't map to WebContents
825+ // XXX: If we ever expose transient pages in the public API, we should find
826+ // a way around this, so that transient pages get the same preferences
827+ web_prefs = contents_helper->GetWebPreferences();
828+ }
829 if (!web_prefs) {
830 web_prefs = WebPreferences::GetFallback();
831 }
832@@ -253,7 +251,9 @@
833 prefs->device_supports_touch = platform_integration_->IsTouchSupported();
834
835 prefs->javascript_can_open_windows_automatically =
836- !contents_helper->GetBrowserContext()->IsPopupBlockerEnabled();
837+ !BrowserContext::FromContent(
838+ render_view_host->GetProcess()->GetBrowserContext())
839+ ->IsPopupBlockerEnabled();
840
841 FormFactor form_factor = GetFormFactorHint();
842 if (form_factor == FORM_FACTOR_TABLET || form_factor == FORM_FACTOR_PHONE) {
843
844=== modified file 'shared/browser/oxide_web_frame_tree.cc'
845--- shared/browser/oxide_web_frame_tree.cc 2015-10-16 21:36:30 +0000
846+++ shared/browser/oxide_web_frame_tree.cc 2015-10-21 20:26:37 +0000
847@@ -83,6 +83,12 @@
848 return;
849 }
850
851+ if (!content::WebContents::FromRenderFrameHost(old_host)) {
852+ // This is from an interstitial
853+ // XXX(chrisccoulson): Is there a better way to detect this?
854+ return;
855+ }
856+
857 WebFrame* frame = WebFrame::FromRenderFrameHost(old_host);
858 DCHECK(frame);
859
860
861=== modified file 'shared/browser/oxide_web_view.cc'
862--- shared/browser/oxide_web_view.cc 2015-10-21 20:14:13 +0000
863+++ shared/browser/oxide_web_view.cc 2015-10-21 20:26:37 +0000
864@@ -75,6 +75,7 @@
865 #include "shared/browser/media/oxide_media_capture_devices_dispatcher.h"
866 #include "shared/browser/permissions/oxide_permission_request_dispatcher.h"
867 #include "shared/browser/permissions/oxide_temporary_saved_permission_context.h"
868+#include "shared/browser/ssl/oxide_certificate_error_dispatcher.h"
869 #include "shared/common/oxide_content_client.h"
870 #include "shared/common/oxide_enum_flags.h"
871 #include "shared/common/oxide_messages.h"
872@@ -137,6 +138,7 @@
873 void CreateHelpers(content::WebContents* contents,
874 content::WebContents* opener = nullptr) {
875 new WebViewContentsHelper(contents, opener);
876+ CertificateErrorDispatcher::CreateForWebContents(contents);
877 PermissionRequestDispatcher::CreateForWebContents(contents);
878 ScriptMessageContentsHelper::CreateForWebContents(contents);
879 #if defined(ENABLE_MEDIAHUB)
880@@ -850,22 +852,6 @@
881 return status == TEMPORARY_SAVED_PERMISSION_STATUS_ALLOWED;
882 }
883
884-void WebView::RenderFrameDeleted(content::RenderFrameHost* render_frame_host) {
885- // XXX(chrisccoulson): Make CertificateErrorManager a WebContentsObserver so
886- // that we can get rid of this
887- certificate_error_manager_.FrameDetached(render_frame_host);
888-}
889-
890-void WebView::RenderFrameHostChanged(content::RenderFrameHost* old_host,
891- content::RenderFrameHost* new_host) {
892- // XXX(chrisccoulson): Make CertificateErrorManager a WebContentsObserver so
893- // that we can get rid of this
894- if (!old_host) {
895- return;
896- }
897- certificate_error_manager_.FrameDetached(old_host);
898-}
899-
900 void WebView::RenderViewReady() {
901 client_->CrashedStatusChanged();
902 }
903@@ -951,14 +937,11 @@
904 return;
905 }
906
907- if (!render_frame_host->GetParent()) {
908- client_->LoadStarted(validated_url);
909+ if (render_frame_host->GetParent()) {
910+ return;
911 }
912
913- // XXX(chrisccoulson): Make CertificateErrorManager a WebContentsObserver so
914- // that we can get rid of this
915- certificate_error_manager_.DidStartProvisionalLoadForFrame(
916- render_frame_host);
917+ client_->LoadStarted(validated_url);
918 }
919
920 void WebView::DidCommitProvisionalLoadForFrame(
921@@ -982,18 +965,15 @@
922 int error_code,
923 const base::string16& error_description,
924 bool was_ignored_by_handler) {
925- if (!render_frame_host->GetParent() &&
926- validated_url.spec() != content::kUnreachableWebDataURL) {
927- DispatchLoadFailed(validated_url, error_code, error_description, true);
928- }
929-
930- if (error_code != net::ERR_ABORTED) {
931- return;
932- }
933-
934- // XXX(chrisccoulson): Make CertificateErrorManager a WebContentsObserverso
935- // that we can get rid of this
936- certificate_error_manager_.DidStopProvisionalLoadForFrame(render_frame_host);
937+ if (render_frame_host->GetParent()) {
938+ return;
939+ }
940+
941+ if (validated_url.spec() == content::kUnreachableWebDataURL) {
942+ return;
943+ }
944+
945+ DispatchLoadFailed(validated_url, error_code, error_description, true);
946 }
947
948 void WebView::DidNavigateMainFrame(
949@@ -1010,18 +990,6 @@
950 }
951 }
952
953-void WebView::DidNavigateAnyFrame(
954- content::RenderFrameHost* render_frame_host,
955- const content::LoadCommittedDetails& details,
956- const content::FrameNavigateParams& params) {
957- // XXX(chrisccoulson): Make CertificateErrorManager a WebContentsObserver
958- if (details.is_in_page) {
959- return;
960- }
961-
962- certificate_error_manager_.DidNavigateFrame(render_frame_host);
963-}
964-
965 void WebView::DidGetRedirectForResourceRequest(
966 content::RenderFrameHost* render_frame_host,
967 const content::ResourceRedirectDetails& details) {
968@@ -1205,12 +1173,24 @@
969
970 // static
971 WebView* WebView::FromRenderViewHost(content::RenderViewHost* rvh) {
972- return FromWebContents(content::WebContents::FromRenderViewHost(rvh));
973+ content::WebContents* contents =
974+ content::WebContents::FromRenderViewHost(rvh);
975+ if (!contents) {
976+ return nullptr;
977+ }
978+
979+ return FromWebContents(contents);
980 }
981
982 // static
983 WebView* WebView::FromRenderFrameHost(content::RenderFrameHost* rfh) {
984- return FromWebContents(content::WebContents::FromRenderFrameHost(rfh));
985+ content::WebContents* contents =
986+ content::WebContents::FromRenderFrameHost(rfh);
987+ if (!contents) {
988+ return nullptr;
989+ }
990+
991+ return FromWebContents(contents);
992 }
993
994 const GURL& WebView::GetURL() const {
995@@ -1663,38 +1643,6 @@
996 web_contents_->DispatchBeforeUnload(false);
997 }
998
999-void WebView::AllowCertificateError(
1000- content::RenderFrameHost* rfh,
1001- int cert_error,
1002- const net::SSLInfo& ssl_info,
1003- const GURL& request_url,
1004- content::ResourceType resource_type,
1005- bool overridable,
1006- bool strict_enforcement,
1007- const base::Callback<void(bool)>& callback,
1008- content::CertificateRequestResultType* result) {
1009- // We can't safely allow the embedder to override errors for subresources or
1010- // subframes because they don't always result in the API indicating a
1011- // degraded security level. Mark these non-overridable for now and just
1012- // deny them outright
1013- // See https://launchpad.net/bugs/1368385
1014- if (!overridable || resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
1015- overridable = false;
1016- *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
1017- }
1018-
1019- scoped_ptr<CertificateError> error(new CertificateError(
1020- &certificate_error_manager_,
1021- rfh,
1022- cert_error,
1023- ssl_info,
1024- request_url,
1025- resource_type,
1026- strict_enforcement,
1027- overridable ? callback : base::Callback<void(bool)>()));
1028- client_->OnCertificateError(error.Pass());
1029-}
1030-
1031 void WebView::HandleKeyEvent(const content::NativeWebKeyboardEvent& event) {
1032 content::RenderViewHost* rvh = GetRenderViewHost();
1033 if (!rvh) {
1034
1035=== modified file 'shared/browser/oxide_web_view.h'
1036--- shared/browser/oxide_web_view.h 2015-10-21 20:14:13 +0000
1037+++ shared/browser/oxide_web_view.h 2015-10-21 20:26:37 +0000
1038@@ -29,14 +29,12 @@
1039 #include "base/strings/string16.h"
1040 #include "cc/output/compositor_frame_metadata.h"
1041 #include "components/sessions/core/serialized_navigation_entry.h"
1042-#include "content/public/browser/certificate_request_result_type.h"
1043 #include "content/public/browser/navigation_controller.h"
1044 #include "content/public/browser/notification_observer.h"
1045 #include "content/public/browser/notification_registrar.h"
1046 #include "content/public/browser/web_contents_delegate.h"
1047 #include "content/public/browser/web_contents_observer.h"
1048 #include "content/public/common/javascript_message_type.h"
1049-#include "content/public/common/resource_type.h"
1050 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
1051 #include "third_party/WebKit/public/platform/WebTopControlsState.h"
1052 #include "ui/gfx/geometry/point.h"
1053@@ -46,7 +44,6 @@
1054 #include "shared/browser/compositor/oxide_compositor_client.h"
1055 #include "shared/browser/compositor/oxide_compositor_observer.h"
1056 #include "shared/browser/input/oxide_input_method_context_observer.h"
1057-#include "shared/browser/oxide_certificate_error.h"
1058 #include "shared/browser/oxide_content_types.h"
1059 #include "shared/browser/oxide_render_widget_host_view_container.h"
1060 #include "shared/browser/oxide_script_message_target.h"
1061@@ -85,10 +82,6 @@
1062 class Size;
1063 }
1064
1065-namespace net {
1066-class SSLInfo;
1067-}
1068-
1069 namespace ui {
1070 class TouchEvent;
1071 }
1072@@ -261,16 +254,6 @@
1073
1074 void PrepareToClose();
1075
1076- void AllowCertificateError(content::RenderFrameHost* rfh,
1077- int cert_error,
1078- const net::SSLInfo& ssl_info,
1079- const GURL& request_url,
1080- content::ResourceType resource_type,
1081- bool overridable,
1082- bool strict_enforcement,
1083- const base::Callback<void(bool)>& callback,
1084- content::CertificateRequestResultType* result);
1085-
1086 void HandleKeyEvent(const content::NativeWebKeyboardEvent& event);
1087 void HandleMouseEvent(const blink::WebMouseEvent& event);
1088 void HandleTouchEvent(const ui::TouchEvent& event);
1089@@ -434,9 +417,6 @@
1090 content::MediaStreamType type) final;
1091
1092 // content::WebContentsObserver implementation
1093- void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) final;
1094- void RenderFrameHostChanged(content::RenderFrameHost* old_host,
1095- content::RenderFrameHost* new_host) final;
1096 void RenderViewReady() final;
1097 void RenderProcessGone(base::TerminationStatus status) final;
1098 void RenderViewHostChanged(content::RenderViewHost* old_host,
1099@@ -468,10 +448,6 @@
1100 void DidNavigateMainFrame(
1101 const content::LoadCommittedDetails& details,
1102 const content::FrameNavigateParams& params) final;
1103- void DidNavigateAnyFrame(
1104- content::RenderFrameHost* render_frame_host,
1105- const content::LoadCommittedDetails& details,
1106- const content::FrameNavigateParams& params) final;
1107 void DidGetRedirectForResourceRequest(
1108 content::RenderFrameHost* render_frame_host,
1109 const content::ResourceRedirectDetails& details) final;
1110@@ -510,8 +486,6 @@
1111 base::WeakPtr<WebPopupMenu> active_popup_menu_;
1112 base::WeakPtr<FilePicker> active_file_picker_;
1113
1114- CertificateErrorManager certificate_error_manager_;
1115-
1116 ContentType blocked_content_;
1117
1118 cc::CompositorFrameMetadata pending_compositor_frame_metadata_;
1119
1120=== modified file 'shared/browser/oxide_web_view_client.cc'
1121--- shared/browser/oxide_web_view_client.cc 2015-10-21 15:17:02 +0000
1122+++ shared/browser/oxide_web_view_client.cc 2015-10-21 20:26:37 +0000
1123@@ -141,8 +141,6 @@
1124
1125 void WebViewClient::SecurityStatusChanged(const SecurityStatus& old) {}
1126
1127-void WebViewClient::OnCertificateError(scoped_ptr<CertificateError> error) {}
1128-
1129 void WebViewClient::ContentBlocked() {}
1130
1131 void WebViewClient::PrepareToCloseResponseReceived(bool proceed) {}
1132
1133=== modified file 'shared/browser/oxide_web_view_client.h'
1134--- shared/browser/oxide_web_view_client.h 2015-10-21 15:17:02 +0000
1135+++ shared/browser/oxide_web_view_client.h 2015-10-21 20:26:37 +0000
1136@@ -173,8 +173,6 @@
1137 // TODO(chrisccoulson): Get rid of |old| and add |changed_flags|
1138 virtual void SecurityStatusChanged(const SecurityStatus& old);
1139
1140- virtual void OnCertificateError(scoped_ptr<CertificateError> error);
1141-
1142 // TODO(chrisccoulson): Rename to BlockedContentChanged or something
1143 // TODO(chrisccoulson): Move content tracking to a separate class with its
1144 // own delegate, as this is going to be expanded with content settings
1145
1146=== modified file 'shared/browser/oxide_web_view_contents_helper.cc'
1147--- shared/browser/oxide_web_view_contents_helper.cc 2015-09-24 15:53:36 +0000
1148+++ shared/browser/oxide_web_view_contents_helper.cc 2015-10-21 20:26:37 +0000
1149@@ -111,7 +111,13 @@
1150 // static
1151 WebViewContentsHelper* WebViewContentsHelper::FromRenderViewHost(
1152 content::RenderViewHost* rvh) {
1153- return FromWebContents(content::WebContents::FromRenderViewHost(rvh));
1154+ content::WebContents* contents =
1155+ content::WebContents::FromRenderViewHost(rvh);
1156+ if (!contents) {
1157+ return nullptr;
1158+ }
1159+
1160+ return FromWebContents(contents);
1161 }
1162
1163 content::WebContents* WebViewContentsHelper::GetWebContents() const {
1164
1165=== added directory 'shared/browser/ssl'
1166=== renamed file 'shared/browser/oxide_certificate_error.cc' => 'shared/browser/ssl/oxide_certificate_error.cc'
1167--- shared/browser/oxide_certificate_error.cc 2015-10-07 17:20:23 +0000
1168+++ shared/browser/ssl/oxide_certificate_error.cc 2015-10-21 20:26:37 +0000
1169@@ -17,293 +17,75 @@
1170
1171 #include "oxide_certificate_error.h"
1172
1173-#include <algorithm>
1174-
1175 #include "base/logging.h"
1176-#include "content/public/browser/render_frame_host.h"
1177-#include "net/base/net_errors.h"
1178 #include "net/cert/x509_certificate.h"
1179-#include "net/ssl/ssl_info.h"
1180+
1181+#include "oxide_certificate_error_proxy.h"
1182
1183 namespace oxide {
1184
1185-namespace {
1186-
1187-CertError ToCertError(int error, net::X509Certificate* cert) {
1188- DCHECK(net::IsCertificateError(error));
1189-
1190- switch (error) {
1191- case net::ERR_CERT_COMMON_NAME_INVALID:
1192- return CERT_ERROR_BAD_IDENTITY;
1193- case net::ERR_CERT_DATE_INVALID: {
1194- if (cert && cert->HasExpired()) {
1195- return CERT_ERROR_EXPIRED;
1196- }
1197- return CERT_ERROR_DATE_INVALID;
1198- }
1199- case net::ERR_CERT_AUTHORITY_INVALID:
1200- return CERT_ERROR_AUTHORITY_INVALID;
1201- case net::ERR_CERT_CONTAINS_ERRORS:
1202- case net::ERR_CERT_INVALID:
1203- case net::ERR_CERT_VALIDITY_TOO_LONG:
1204- return CERT_ERROR_INVALID;
1205- case net::ERR_CERT_REVOKED:
1206- return CERT_ERROR_REVOKED;
1207- case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
1208- case net::ERR_CERT_WEAK_KEY:
1209- return CERT_ERROR_INSECURE;
1210- //case net::ERR_CERT_NO_REVOCATION_MECHANISM:
1211- //case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
1212- //case net::ERR_CERT_NON_UNIQUE_NAME:
1213- //case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
1214- default:
1215- return CERT_ERROR_GENERIC;
1216- }
1217-}
1218-
1219-}
1220-
1221-class CertificateErrorManager::IteratorGuard {
1222- public:
1223- IteratorGuard(CertificateErrorManager* manager);
1224- ~IteratorGuard();
1225-
1226- private:
1227- base::WeakPtr<CertificateErrorManager> manager_;
1228- bool iterating_original_;
1229-
1230- DISALLOW_COPY_AND_ASSIGN(IteratorGuard);
1231-};
1232-
1233-CertificateErrorManager::IteratorGuard::IteratorGuard(
1234- CertificateErrorManager* manager)
1235- : manager_(manager->weak_factory_.GetWeakPtr()),
1236- iterating_original_(manager->iterating_) {
1237- manager->iterating_ = true;
1238-}
1239-
1240-CertificateErrorManager::IteratorGuard::~IteratorGuard() {
1241- if (!manager_) {
1242- return;
1243- }
1244-
1245- manager_->iterating_ = iterating_original_;
1246- if (!manager_->iterating_) {
1247- manager_->Compact();
1248- }
1249-}
1250-
1251-void CertificateErrorManager::AddError(CertificateError* error) {
1252- DCHECK_EQ(error->manager_, this);
1253- DCHECK(std::find(errors_.begin(), errors_.end(), error) == errors_.end());
1254-
1255- errors_.push_back(error);
1256-}
1257-
1258-void CertificateErrorManager::RemoveError(CertificateError* error) {
1259- auto it = std::find(errors_.begin(), errors_.end(), error);
1260- DCHECK(it != errors_.end());
1261- if (iterating_) {
1262- *it = nullptr;
1263- } else {
1264- errors_.erase(it);
1265- }
1266-
1267- error->manager_ = nullptr;
1268-}
1269-
1270-void CertificateErrorManager::Compact() {
1271- DCHECK(!iterating_);
1272-
1273- errors_.erase(
1274- std::remove(errors_.begin(), errors_.end(), nullptr),
1275- errors_.end());
1276-}
1277-
1278-void CertificateErrorManager::CancelPendingFrameErrorsForFrame(
1279- content::RenderFrameHost* frame) {
1280- RenderFrameHostID frame_id = RenderFrameHostID::FromHost(frame);
1281-
1282- IteratorGuard guard(this);
1283-
1284- for (auto it = errors_.begin(); it != errors_.end(); ++it) {
1285- CertificateError* error = *it;
1286- if (!error) {
1287- continue;
1288- }
1289-
1290- if (error->frame_id_ != frame_id) {
1291- continue;
1292- }
1293-
1294- if (error->is_subresource()) {
1295- continue;
1296- }
1297-
1298- if (error->non_overridable_frame_error_committed_) {
1299- continue;
1300- }
1301-
1302- RemoveError(error);
1303- error->Cancel();
1304- }
1305-}
1306-
1307-CertificateErrorManager::CertificateErrorManager()
1308- : iterating_(false),
1309- weak_factory_(this) {}
1310-
1311-CertificateErrorManager::~CertificateErrorManager() {
1312- IteratorGuard guard(this);
1313- for (auto it = errors_.begin(); it != errors_.end(); ++it) {
1314- CertificateError* error = *it;
1315- if (!error) {
1316- continue;
1317- }
1318-
1319- RemoveError(error);
1320- error->Cancel();
1321- }
1322-}
1323-
1324-void CertificateErrorManager::DidStartProvisionalLoadForFrame(
1325- content::RenderFrameHost* frame) {
1326- DCHECK(frame);
1327- CancelPendingFrameErrorsForFrame(frame);
1328-}
1329-
1330-void CertificateErrorManager::DidNavigateFrame(
1331- content::RenderFrameHost* frame) {
1332- DCHECK(frame);
1333-
1334- RenderFrameHostID frame_id = RenderFrameHostID::FromHost(frame);
1335-
1336- IteratorGuard guard(this);
1337-
1338- for (auto it = errors_.begin(); it != errors_.end(); ++it) {
1339- CertificateError* error = *it;
1340- if (!error) {
1341- continue;
1342- }
1343-
1344- if (error->frame_id_ != frame_id) {
1345- continue;
1346- }
1347-
1348- if (!error->is_subresource() &&
1349- !error->non_overridable_frame_error_committed_) {
1350- error->non_overridable_frame_error_committed_ = true;
1351- continue;
1352- }
1353-
1354- RemoveError(error);
1355- error->Cancel();
1356- }
1357-}
1358-
1359-void CertificateErrorManager::DidStopProvisionalLoadForFrame(
1360- content::RenderFrameHost* frame) {
1361- DCHECK(frame);
1362- CancelPendingFrameErrorsForFrame(frame);
1363-}
1364-
1365-void CertificateErrorManager::FrameDetached(content::RenderFrameHost* frame) {
1366- DCHECK(frame);
1367-
1368- RenderFrameHostID frame_id = RenderFrameHostID::FromHost(frame);
1369-
1370- IteratorGuard guard(this);
1371-
1372- for (auto it = errors_.begin(); it != errors_.end(); ++it) {
1373- CertificateError* error = *it;
1374- if (!error) {
1375- continue;
1376- }
1377-
1378- if (error->frame_id_ != frame_id) {
1379- continue;
1380- }
1381-
1382- RemoveError(error);
1383- error->Cancel();
1384- }
1385-}
1386-
1387-void CertificateError::Cancel() {
1388- DCHECK(!is_cancelled_);
1389- DCHECK(!callback_.is_null() || !overridable_);
1390-
1391- is_cancelled_ = true;
1392-
1393- if (!callback_.is_null()) {
1394- callback_.Run(false);
1395- callback_.Reset();
1396- }
1397-
1398- if (!cancel_callback_.is_null()) {
1399- cancel_callback_.Run();
1400- cancel_callback_.Reset();
1401- }
1402-}
1403-
1404-CertificateError::CertificateError(
1405- CertificateErrorManager* manager,
1406- content::RenderFrameHost* frame,
1407- int cert_error,
1408- const net::SSLInfo& ssl_info,
1409- const GURL& url,
1410- content::ResourceType resource_type,
1411- bool strict_enforcement,
1412- const base::Callback<void(bool)>& callback)
1413- : manager_(manager),
1414- frame_id_(RenderFrameHostID::FromHost(frame)),
1415- is_main_frame_(!frame->GetParent()),
1416- is_subresource_(!content::IsResourceTypeFrame(resource_type)),
1417- cert_error_(ToCertError(cert_error, ssl_info.cert.get())),
1418- cert_(ssl_info.cert),
1419+CertificateError::CertificateError(bool is_main_frame,
1420+ bool is_subresource,
1421+ CertError cert_error,
1422+ net::X509Certificate* cert,
1423+ const GURL& url,
1424+ bool strict_enforcement,
1425+ bool overridable,
1426+ CertificateErrorProxy* proxy)
1427+ : is_main_frame_(is_main_frame),
1428+ is_subresource_(is_subresource),
1429+ cert_error_(cert_error),
1430+ cert_(cert),
1431 url_(url),
1432- overridable_(!callback.is_null()),
1433 strict_enforcement_(strict_enforcement),
1434- callback_(callback),
1435- is_cancelled_(false),
1436- non_overridable_frame_error_committed_(false) {
1437- DCHECK(manager_);
1438- DCHECK(frame);
1439- CHECK(!overridable_ || !strict_enforcement_) <<
1440- "overridable and strict_enforcement are expected to be mutually exclusive";
1441-
1442- manager_->AddError(this);
1443-}
1444+ overridable_(overridable),
1445+ proxy_(proxy) {}
1446
1447 CertificateError::~CertificateError() {
1448- if (!callback_.is_null()) {
1449- Deny();
1450- } else if (manager_) {
1451- manager_->RemoveError(this);
1452+ if (!proxy_->did_respond() && !proxy_->is_cancelled()) {
1453+ proxy_->Deny();
1454 }
1455 }
1456
1457+bool CertificateError::IsCancelled() const {
1458+ return proxy_->is_cancelled();
1459+}
1460+
1461 void CertificateError::SetCancelCallback(const base::Closure& callback) {
1462- DCHECK(!is_cancelled_);
1463- cancel_callback_ = callback;
1464+ proxy_->set_cancel_callback(callback);
1465 }
1466
1467 void CertificateError::Allow() {
1468- DCHECK(!callback_.is_null());
1469-
1470- callback_.Run(true);
1471- callback_.Reset();
1472-
1473- manager_->RemoveError(this);
1474+ if (!overridable()) {
1475+ LOG(WARNING) << "Can't override a non-overridable error";
1476+ return;
1477+ }
1478+
1479+ if (proxy_->is_cancelled()) {
1480+ LOG(WARNING) << "Can't override an error that's been cancelled";
1481+ return;
1482+ }
1483+
1484+ if (proxy_->did_respond()) {
1485+ LOG(WARNING) << "Can't respond more than once to a CertificateError";
1486+ return;
1487+ }
1488+
1489+ proxy_->Allow();
1490 }
1491
1492 void CertificateError::Deny() {
1493- DCHECK(!callback_.is_null());
1494-
1495- callback_.Run(false);
1496- callback_.Reset();
1497-
1498- manager_->RemoveError(this);
1499+ if (proxy_->is_cancelled()) {
1500+ LOG(WARNING) << "Can't override an error that's been cancelled";
1501+ return;
1502+ }
1503+
1504+ if (proxy_->did_respond()) {
1505+ LOG(WARNING) << "Can't respond more than once to a CertificateError";
1506+ return;
1507+ }
1508+
1509+ proxy_->Deny();
1510 }
1511
1512 } // namespace oxide
1513
1514=== renamed file 'shared/browser/oxide_certificate_error.h' => 'shared/browser/ssl/oxide_certificate_error.h'
1515--- shared/browser/oxide_certificate_error.h 2015-10-07 17:20:23 +0000
1516+++ shared/browser/ssl/oxide_certificate_error.h 2015-10-21 20:26:37 +0000
1517@@ -15,96 +15,36 @@
1518 // License along with this library; if not, write to the Free Software
1519 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1520
1521-#ifndef _OXIDE_SHARED_BROWSER_CERTIFICATE_ERROR_H_
1522-#define _OXIDE_SHARED_BROWSER_CERTIFICATE_ERROR_H_
1523-
1524-#include <vector>
1525+#ifndef _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_H_
1526+#define _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_H_
1527
1528 #include "base/callback.h"
1529 #include "base/macros.h"
1530 #include "base/memory/ref_counted.h"
1531-#include "base/memory/weak_ptr.h"
1532-#include "content/public/common/resource_type.h"
1533 #include "url/gurl.h"
1534
1535-#include "shared/browser/oxide_render_frame_host_id.h"
1536 #include "shared/browser/oxide_security_types.h"
1537
1538-namespace content {
1539-class RenderFrameHost;
1540-}
1541-
1542 namespace net {
1543-class SSLInfo;
1544 class X509Certificate;
1545 }
1546
1547 namespace oxide {
1548
1549-class CertificateError;
1550-
1551-// This class tracks CertificateErrors
1552-class CertificateErrorManager {
1553- public:
1554- CertificateErrorManager();
1555- ~CertificateErrorManager();
1556-
1557- // Cancels any pending frame errors for |frame|
1558- void DidStartProvisionalLoadForFrame(content::RenderFrameHost* frame);
1559-
1560- // Cancels any errors for |frame| with the exception of
1561- // non-overridable frame errors if this is the corresponding error page
1562- void DidNavigateFrame(content::RenderFrameHost* frame);
1563-
1564- // Cancels any pending frame errors for |frame|
1565- void DidStopProvisionalLoadForFrame(content::RenderFrameHost* frame);
1566-
1567- // Cancels all errors for frame
1568- void FrameDetached(content::RenderFrameHost* frame);
1569-
1570- private:
1571- friend class CertificateError;
1572- class IteratorGuard;
1573-
1574- // Add a CertificateError
1575- void AddError(CertificateError* error);
1576-
1577- // Remove a CertificateError, clearing its pointers to this
1578- // and the frame that generated the error
1579- void RemoveError(CertificateError* error);
1580-
1581- // Remove empty slots from errors_
1582- void Compact();
1583-
1584- void CancelPendingFrameErrorsForFrame(content::RenderFrameHost* frame);
1585-
1586- typedef std::vector<CertificateError*> CertErrorVector;
1587-
1588- // Used to indicate that errors_ is being iterated over, and
1589- // will prevent RemoveError from removing entries from it
1590- bool iterating_;
1591-
1592- // The list of CertificateErrors
1593- CertErrorVector errors_;
1594-
1595- base::WeakPtrFactory<CertificateErrorManager> weak_factory_;
1596-
1597- DISALLOW_COPY_AND_ASSIGN(CertificateErrorManager);
1598-};
1599+class CertificateErrorProxy;
1600
1601 // Represents a SSL certificate error. It provides access to the relevant
1602 // information about the error, as well as methods to accept or deny it
1603 class CertificateError {
1604 public:
1605- CertificateError(
1606- CertificateErrorManager* manager,
1607- content::RenderFrameHost* frame,
1608- int cert_error,
1609- const net::SSLInfo& ssl_info,
1610- const GURL& url,
1611- content::ResourceType resource_type,
1612- bool strict_enforcement,
1613- const base::Callback<void(bool)>& callback);
1614+ CertificateError(bool is_main_frame,
1615+ bool is_subresource,
1616+ CertError cert_error,
1617+ net::X509Certificate* cert,
1618+ const GURL& url,
1619+ bool strict_enforcement,
1620+ bool overridable,
1621+ CertificateErrorProxy* proxy);
1622 ~CertificateError();
1623
1624 // If the error is from the main frame
1625@@ -128,55 +68,35 @@
1626 // Whether the error was generated from a URL that uses HSTS
1627 bool strict_enforcement() const { return strict_enforcement_; }
1628
1629- // Whether the error has been cancelled by Oxide. A cancelled error is no
1630- // longer relevant. This can happen if the frame navigates or goes away
1631- bool is_cancelled() const { return is_cancelled_; }
1632+ // Whether the error has been cancelled by Oxide. This is only relevant
1633+ // for main frame errors (is_main_frame_ && !is_subresource_) and is used
1634+ // to signal to the application when it should hide its certificate error UI
1635+ bool IsCancelled() const;
1636
1637 // Set a callback to be invoked when this error is cancelled
1638 void SetCancelCallback(const base::Closure& callback);
1639
1640 // Allow the request that generated the error to continue, ignoring the
1641- // error. Only possible if overridable() returns true
1642+ // error. Only possible if IsOverridable() returns true
1643 void Allow();
1644
1645 // Cancel the request that generated the error
1646 void Deny();
1647
1648 private:
1649- friend class CertificateErrorManager;
1650-
1651- // Cancel the request that generated the error and run the cancel callback.
1652- // This is only called from CertificateErrorManager
1653- void Cancel();
1654-
1655- CertificateErrorManager* manager_;
1656-
1657- // The ID of the frame the generated this error
1658- RenderFrameHostID frame_id_;
1659-
1660 bool is_main_frame_;
1661 bool is_subresource_;
1662 CertError cert_error_;
1663 scoped_refptr<net::X509Certificate> cert_;
1664 GURL url_;
1665+ bool strict_enforcement_;
1666 bool overridable_;
1667- bool strict_enforcement_;
1668-
1669- // The callback provided by Chromium, which we use to respond to the error
1670- base::Callback<void(bool)> callback_;
1671-
1672- bool is_cancelled_;
1673- base::Closure cancel_callback_;
1674-
1675- // Subresource errors are cancelled when a frame is committed.
1676- // However, non-overridable frame errors should persist beyond the error
1677- // page commit for this failed load and then be cancelled on a subsequent
1678- // commit. This is used for tracking that
1679- bool non_overridable_frame_error_committed_;
1680+
1681+ scoped_refptr<CertificateErrorProxy> proxy_;
1682
1683 DISALLOW_COPY_AND_ASSIGN(CertificateError);
1684 };
1685
1686 } // namespace oxide
1687
1688-#endif // _OXIDE_SHARED_BROWSER_CERTIFICATE_ERROR_H_
1689+#endif // _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_H_
1690
1691=== added file 'shared/browser/ssl/oxide_certificate_error_dispatcher.cc'
1692--- shared/browser/ssl/oxide_certificate_error_dispatcher.cc 1970-01-01 00:00:00 +0000
1693+++ shared/browser/ssl/oxide_certificate_error_dispatcher.cc 2015-10-21 20:26:37 +0000
1694@@ -0,0 +1,196 @@
1695+// vim:expandtab:shiftwidth=2:tabstop=2:
1696+// Copyright (C) 2015 Canonical Ltd.
1697+
1698+// This library is free software; you can redistribute it and/or
1699+// modify it under the terms of the GNU Lesser General Public
1700+// License as published by the Free Software Foundation; either
1701+// version 2.1 of the License, or (at your option) any later version.
1702+
1703+// This library is distributed in the hope that it will be useful,
1704+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1705+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1706+// Lesser General Public License for more details.
1707+
1708+// You should have received a copy of the GNU Lesser General Public
1709+// License along with this library; if not, write to the Free Software
1710+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1711+
1712+#include "oxide_certificate_error_dispatcher.h"
1713+
1714+#include "base/logging.h"
1715+#include "base/memory/ref_counted.h"
1716+#include "content/public/browser/browser_thread.h"
1717+#include "content/public/browser/certificate_request_result_type.h"
1718+#include "content/public/browser/render_frame_host.h"
1719+#include "content/public/browser/web_contents.h"
1720+#include "net/base/net_errors.h"
1721+#include "net/cert/x509_certificate.h"
1722+#include "net/ssl/ssl_info.h"
1723+#include "url/gurl.h"
1724+
1725+#include "shared/browser/oxide_security_types.h"
1726+
1727+#include "oxide_certificate_error.h"
1728+#include "oxide_certificate_error_dispatcher_client.h"
1729+#include "oxide_certificate_error_placeholder_page.h"
1730+#include "oxide_certificate_error_proxy.h"
1731+
1732+namespace oxide {
1733+
1734+namespace {
1735+
1736+CertError ToCertError(int error, net::X509Certificate* cert) {
1737+ DCHECK(net::IsCertificateError(error));
1738+
1739+ switch (error) {
1740+ case net::ERR_CERT_COMMON_NAME_INVALID:
1741+ return CERT_ERROR_BAD_IDENTITY;
1742+ case net::ERR_CERT_DATE_INVALID: {
1743+ if (cert && cert->HasExpired()) {
1744+ return CERT_ERROR_EXPIRED;
1745+ }
1746+ return CERT_ERROR_DATE_INVALID;
1747+ }
1748+ case net::ERR_CERT_AUTHORITY_INVALID:
1749+ return CERT_ERROR_AUTHORITY_INVALID;
1750+ case net::ERR_CERT_CONTAINS_ERRORS:
1751+ case net::ERR_CERT_INVALID:
1752+ case net::ERR_CERT_VALIDITY_TOO_LONG:
1753+ return CERT_ERROR_INVALID;
1754+ case net::ERR_CERT_REVOKED:
1755+ return CERT_ERROR_REVOKED;
1756+ case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
1757+ case net::ERR_CERT_WEAK_KEY:
1758+ return CERT_ERROR_INSECURE;
1759+ //case net::ERR_CERT_NO_REVOCATION_MECHANISM:
1760+ //case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
1761+ //case net::ERR_CERT_NON_UNIQUE_NAME:
1762+ //case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
1763+ default:
1764+ return CERT_ERROR_GENERIC;
1765+ }
1766+}
1767+
1768+}
1769+
1770+DEFINE_WEB_CONTENTS_USER_DATA_KEY(CertificateErrorDispatcher);
1771+
1772+CertificateErrorDispatcher::CertificateErrorDispatcher()
1773+ : client_(nullptr) {}
1774+
1775+bool CertificateErrorDispatcher::CanDispatch() const {
1776+ return !!client_;
1777+}
1778+
1779+void CertificateErrorDispatcher::Dispatch(scoped_ptr<CertificateError> error) {
1780+ client_->OnCertificateError(error.Pass());
1781+}
1782+
1783+CertificateErrorDispatcher::~CertificateErrorDispatcher() {}
1784+
1785+// static
1786+void CertificateErrorDispatcher::CreateForWebContents(
1787+ content::WebContents* contents) {
1788+ DCHECK(contents);
1789+ if (!FromWebContents(contents)) {
1790+ contents->SetUserData(UserDataKey(), new CertificateErrorDispatcher());
1791+ }
1792+}
1793+
1794+// static
1795+void CertificateErrorDispatcher::AllowCertificateError(
1796+ int render_process_id,
1797+ int render_frame_id,
1798+ int cert_error,
1799+ const net::SSLInfo& ssl_info,
1800+ const GURL& request_url,
1801+ content::ResourceType resource_type,
1802+ bool overridable,
1803+ bool strict_enforcement,
1804+ const base::Callback<void(bool)>& callback,
1805+ content::CertificateRequestResultType* result) {
1806+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1807+ DCHECK_IMPLIES(strict_enforcement, !overridable);
1808+
1809+ // Note, CANCEL will stop the resource load associated with the error, and
1810+ // DENY will fail it, resulting in an error page being loaded if it's
1811+ // for the document request
1812+
1813+ content::RenderFrameHost* rfh =
1814+ content::RenderFrameHost::FromID(render_process_id, render_frame_id);
1815+ if (!rfh) {
1816+ *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
1817+ return;
1818+ }
1819+
1820+ content::WebContents* contents =
1821+ content::WebContents::FromRenderFrameHost(rfh);
1822+ if (!contents) {
1823+ *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
1824+ return;
1825+ }
1826+
1827+ CertificateErrorDispatcher* dispatcher = FromWebContents(contents);
1828+
1829+ if (!dispatcher->CanDispatch()) {
1830+ *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
1831+ return;
1832+ }
1833+
1834+ if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
1835+ // Only errors for main frame document resources are overridable, as it's
1836+ // the only case where we can guarantee that the security status for the
1837+ // webview is correct (see https://launchpad.net/bugs/1368385), and it's
1838+ // the only case where we trust the application to be able to display a
1839+ // meaningful UI
1840+ overridable = false;
1841+ *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
1842+ } else if (!overridable) {
1843+ // Don't load an error page for main frame document errors, as we're going
1844+ // to load a placeholder transient page
1845+ *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
1846+ }
1847+
1848+
1849+ scoped_refptr<CertificateErrorProxy> proxy =
1850+ new CertificateErrorProxy(
1851+ overridable ? callback : base::Callback<void(bool)>());
1852+ scoped_ptr<CertificateError> error(
1853+ new CertificateError(!rfh->GetParent(),
1854+ !content::IsResourceTypeFrame(resource_type),
1855+ ToCertError(cert_error, ssl_info.cert.get()),
1856+ ssl_info.cert.get(),
1857+ request_url,
1858+ strict_enforcement,
1859+ overridable,
1860+ proxy.get()));
1861+
1862+ dispatcher->Dispatch(error.Pass());
1863+
1864+ if (proxy->did_respond()) {
1865+ // If the application responded explicitly or by CertificateError being
1866+ // destroyed, there's nothing more to do
1867+ return;
1868+ }
1869+
1870+ if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
1871+ // If this error isn't for a main frame document resource, there's nothing
1872+ // more to do
1873+ return;
1874+ }
1875+
1876+ // For main frame document resources, we insert a placeholder transient page
1877+ // as long as CertificateError is alive and not responded to. This is
1878+ // intended to help the embedder when it displays a certificate error UI by
1879+ // ensuring the visible URL is correct, navigation history is consistent, the
1880+ // webview is marked as not loading and the back button behaves correctly
1881+ // (should dismiss the error via the cancel callback and go back to the last
1882+ // committed page)
1883+
1884+ // This gets owned by the |contents|
1885+ new CertificateErrorPlaceholderPage(contents,
1886+ request_url,
1887+ proxy.get());
1888+}
1889+
1890+} // namespace oxide
1891
1892=== added file 'shared/browser/ssl/oxide_certificate_error_dispatcher.h'
1893--- shared/browser/ssl/oxide_certificate_error_dispatcher.h 1970-01-01 00:00:00 +0000
1894+++ shared/browser/ssl/oxide_certificate_error_dispatcher.h 2015-10-21 20:26:37 +0000
1895@@ -0,0 +1,77 @@
1896+// vim:expandtab:shiftwidth=2:tabstop=2:
1897+// Copyright (C) 2015 Canonical Ltd.
1898+
1899+// This library is free software; you can redistribute it and/or
1900+// modify it under the terms of the GNU Lesser General Public
1901+// License as published by the Free Software Foundation; either
1902+// version 2.1 of the License, or (at your option) any later version.
1903+
1904+// This library is distributed in the hope that it will be useful,
1905+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1906+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1907+// Lesser General Public License for more details.
1908+
1909+// You should have received a copy of the GNU Lesser General Public
1910+// License along with this library; if not, write to the Free Software
1911+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1912+
1913+#ifndef _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_H_
1914+#define _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_H_
1915+
1916+#include "base/callback.h"
1917+#include "base/macros.h"
1918+#include "content/public/browser/certificate_request_result_type.h"
1919+#include "content/public/browser/web_contents_user_data.h"
1920+#include "content/public/common/resource_type.h"
1921+
1922+class GURL;
1923+
1924+namespace net {
1925+class SSLInfo;
1926+}
1927+
1928+namespace oxide {
1929+
1930+class CertificateError;
1931+class CertificateErrorDispatcherClient;
1932+
1933+// A helper class for dispatching certificate errors from Chromium to
1934+// CertificateErrorDispatcherClient
1935+class CertificateErrorDispatcher
1936+ : public content::WebContentsUserData<CertificateErrorDispatcher> {
1937+ public:
1938+ ~CertificateErrorDispatcher();
1939+
1940+ static void CreateForWebContents(content::WebContents* contents);
1941+
1942+ // Entry point from Chromium
1943+ static void AllowCertificateError(
1944+ int render_process_id,
1945+ int render_frame_id,
1946+ int cert_error,
1947+ const net::SSLInfo& ssl_info,
1948+ const GURL& request_url,
1949+ content::ResourceType resource_type,
1950+ bool overridable,
1951+ bool strict_enforcement,
1952+ const base::Callback<void(bool)>& callback,
1953+ content::CertificateRequestResultType* result);
1954+
1955+ void set_client(CertificateErrorDispatcherClient* client) {
1956+ client_ = client;
1957+ }
1958+
1959+ private:
1960+ CertificateErrorDispatcher();
1961+
1962+ bool CanDispatch() const;
1963+ void Dispatch(scoped_ptr<CertificateError> error);
1964+
1965+ CertificateErrorDispatcherClient* client_;
1966+
1967+ DISALLOW_COPY_AND_ASSIGN(CertificateErrorDispatcher);
1968+};
1969+
1970+} // namespace oxide
1971+
1972+#endif // _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_H_
1973
1974=== added file 'shared/browser/ssl/oxide_certificate_error_dispatcher_client.h'
1975--- shared/browser/ssl/oxide_certificate_error_dispatcher_client.h 1970-01-01 00:00:00 +0000
1976+++ shared/browser/ssl/oxide_certificate_error_dispatcher_client.h 2015-10-21 20:26:37 +0000
1977@@ -0,0 +1,36 @@
1978+// vim:expandtab:shiftwidth=2:tabstop=2:
1979+// Copyright (C) 2015 Canonical Ltd.
1980+
1981+// This library is free software; you can redistribute it and/or
1982+// modify it under the terms of the GNU Lesser General Public
1983+// License as published by the Free Software Foundation; either
1984+// version 2.1 of the License, or (at your option) any later version.
1985+
1986+// This library is distributed in the hope that it will be useful,
1987+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1988+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1989+// Lesser General Public License for more details.
1990+
1991+// You should have received a copy of the GNU Lesser General Public
1992+// License along with this library; if not, write to the Free Software
1993+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1994+
1995+#ifndef _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_CLIENT_H_
1996+#define _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_CLIENT_H_
1997+
1998+#include "base/memory/scoped_ptr.h"
1999+
2000+namespace oxide {
2001+
2002+class CertificateError;
2003+
2004+class CertificateErrorDispatcherClient {
2005+ public:
2006+ virtual ~CertificateErrorDispatcherClient() {}
2007+
2008+ virtual void OnCertificateError(scoped_ptr<CertificateError> error) = 0;
2009+};
2010+
2011+} // namespace oxide
2012+
2013+#endif // _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_DISPATCHER_CLIENT_H_
2014
2015=== added file 'shared/browser/ssl/oxide_certificate_error_placeholder_page.cc'
2016--- shared/browser/ssl/oxide_certificate_error_placeholder_page.cc 1970-01-01 00:00:00 +0000
2017+++ shared/browser/ssl/oxide_certificate_error_placeholder_page.cc 2015-10-21 20:26:37 +0000
2018@@ -0,0 +1,58 @@
2019+// vim:expandtab:shiftwidth=2:tabstop=2:
2020+// Copyright (C) 2015 Canonical Ltd.
2021+
2022+// This library is free software; you can redistribute it and/or
2023+// modify it under the terms of the GNU Lesser General Public
2024+// License as published by the Free Software Foundation; either
2025+// version 2.1 of the License, or (at your option) any later version.
2026+
2027+// This library is distributed in the hope that it will be useful,
2028+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2029+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2030+// Lesser General Public License for more details.
2031+
2032+// You should have received a copy of the GNU Lesser General Public
2033+// License along with this library; if not, write to the Free Software
2034+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2035+
2036+#include "oxide_certificate_error_placeholder_page.h"
2037+
2038+#include "base/logging.h"
2039+#include "content/public/browser/interstitial_page.h"
2040+
2041+#include "oxide_certificate_error_proxy.h"
2042+
2043+namespace oxide {
2044+
2045+CertificateErrorPlaceholderPage::~CertificateErrorPlaceholderPage() {}
2046+
2047+std::string CertificateErrorPlaceholderPage::GetHTMLContents() {
2048+ return "<html></html>";
2049+}
2050+
2051+void CertificateErrorPlaceholderPage::OnDontProceed() {
2052+ error_->Cancel();
2053+}
2054+
2055+CertificateErrorPlaceholderPage::CertificateErrorPlaceholderPage(
2056+ content::WebContents* contents,
2057+ const GURL& request_url,
2058+ CertificateErrorProxy* error)
2059+ : interstitial_(content::InterstitialPage::Create(contents,
2060+ true,
2061+ request_url,
2062+ this)),
2063+ error_(error) {
2064+ error_->SetPlaceholderPage(this);
2065+ interstitial_->Show();
2066+}
2067+
2068+void CertificateErrorPlaceholderPage::Proceed() {
2069+ interstitial_->Proceed();
2070+}
2071+
2072+void CertificateErrorPlaceholderPage::DontProceed() {
2073+ interstitial_->DontProceed();
2074+}
2075+
2076+} // namespace oxide
2077
2078=== added file 'shared/browser/ssl/oxide_certificate_error_placeholder_page.h'
2079--- shared/browser/ssl/oxide_certificate_error_placeholder_page.h 1970-01-01 00:00:00 +0000
2080+++ shared/browser/ssl/oxide_certificate_error_placeholder_page.h 2015-10-21 20:26:37 +0000
2081@@ -0,0 +1,64 @@
2082+// vim:expandtab:shiftwidth=2:tabstop=2:
2083+// Copyright (C) 2015 Canonical Ltd.
2084+
2085+// This library is free software; you can redistribute it and/or
2086+// modify it under the terms of the GNU Lesser General Public
2087+// License as published by the Free Software Foundation; either
2088+// version 2.1 of the License, or (at your option) any later version.
2089+
2090+// This library is distributed in the hope that it will be useful,
2091+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2092+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2093+// Lesser General Public License for more details.
2094+
2095+// You should have received a copy of the GNU Lesser General Public
2096+// License along with this library; if not, write to the Free Software
2097+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2098+
2099+#ifndef _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PLACEHOLDER_PAGE_H_
2100+#define _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PLACEHOLDER_PAGE_H_
2101+
2102+#include "base/macros.h"
2103+#include "base/memory/ref_counted.h"
2104+#include "content/public/browser/interstitial_page_delegate.h"
2105+
2106+class GURL;
2107+
2108+namespace content {
2109+class InterstitialPage;
2110+class WebContents;
2111+}
2112+
2113+namespace oxide {
2114+
2115+class CertificateErrorProxy;
2116+
2117+// This class inserts a placeholder transient page in to a WebContents'
2118+// navigation list whilst an application displays a certificate error UI
2119+class CertificateErrorPlaceholderPage
2120+ : public content::InterstitialPageDelegate {
2121+ public:
2122+ CertificateErrorPlaceholderPage(content::WebContents* contents,
2123+ const GURL& request_url,
2124+ CertificateErrorProxy* error);
2125+
2126+ void Proceed();
2127+ void DontProceed();
2128+
2129+ private:
2130+ ~CertificateErrorPlaceholderPage() override;
2131+
2132+ // content::InterstitialPageDelegate implementation
2133+ std::string GetHTMLContents() override;
2134+ void OnDontProceed() override;
2135+
2136+ content::InterstitialPage* interstitial_; // This owns us
2137+
2138+ scoped_refptr<CertificateErrorProxy> error_;
2139+
2140+ DISALLOW_COPY_AND_ASSIGN(CertificateErrorPlaceholderPage);
2141+};
2142+
2143+} // namespace oxide
2144+
2145+#endif // _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PLACEHOLDER_PAGE_H_
2146
2147=== added file 'shared/browser/ssl/oxide_certificate_error_proxy.cc'
2148--- shared/browser/ssl/oxide_certificate_error_proxy.cc 1970-01-01 00:00:00 +0000
2149+++ shared/browser/ssl/oxide_certificate_error_proxy.cc 2015-10-21 20:26:37 +0000
2150@@ -0,0 +1,105 @@
2151+// vim:expandtab:shiftwidth=2:tabstop=2:
2152+// Copyright (C) 2015 Canonical Ltd.
2153+
2154+// This library is free software; you can redistribute it and/or
2155+// modify it under the terms of the GNU Lesser General Public
2156+// License as published by the Free Software Foundation; either
2157+// version 2.1 of the License, or (at your option) any later version.
2158+
2159+// This library is distributed in the hope that it will be useful,
2160+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2161+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2162+// Lesser General Public License for more details.
2163+
2164+// You should have received a copy of the GNU Lesser General Public
2165+// License along with this library; if not, write to the Free Software
2166+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2167+
2168+#include "oxide_certificate_error_proxy.h"
2169+
2170+#include "base/logging.h"
2171+
2172+#include "oxide_certificate_error_placeholder_page.h"
2173+
2174+namespace oxide {
2175+
2176+CertificateErrorProxy::~CertificateErrorProxy() {
2177+ DCHECK(did_respond_ || is_cancelled_);
2178+}
2179+
2180+CertificateErrorProxy::CertificateErrorProxy(
2181+ const base::Callback<void(bool)>& callback)
2182+ : callback_(callback),
2183+ is_cancelled_(false),
2184+ did_respond_(false),
2185+ placeholder_page_(nullptr) {}
2186+
2187+void CertificateErrorProxy::Allow() {
2188+ DCHECK(!did_respond_);
2189+ DCHECK(!is_cancelled_);
2190+ DCHECK(!callback_.is_null());
2191+
2192+ did_respond_ = true;
2193+
2194+ callback_.Run(true);
2195+ callback_.Reset();
2196+
2197+ if (placeholder_page_) {
2198+ placeholder_page_->Proceed();
2199+ placeholder_page_ = nullptr;
2200+ }
2201+}
2202+
2203+void CertificateErrorProxy::Deny() {
2204+ DCHECK(!did_respond_);
2205+ DCHECK(!is_cancelled_);
2206+
2207+ did_respond_ = true;
2208+
2209+ if (!callback_.is_null()) {
2210+ callback_.Run(false);
2211+ callback_.Reset();
2212+ }
2213+
2214+ if (placeholder_page_) {
2215+ placeholder_page_->DontProceed();
2216+ placeholder_page_ = nullptr;
2217+ }
2218+}
2219+
2220+void CertificateErrorProxy::Cancel() {
2221+ DCHECK(!is_cancelled_);
2222+
2223+ if (did_respond_) {
2224+ // Calling Deny() ends up re-entering here via
2225+ // InterstitialPageDelegate::OnDontProceed
2226+ return;
2227+ }
2228+
2229+ // Chromium can call in to us after we've responded, if we responded
2230+ // before the interstitial navigation was committed. This is why this check
2231+ // is here, and not higher up
2232+ DCHECK(placeholder_page_);
2233+
2234+ is_cancelled_ = true;
2235+ placeholder_page_ = nullptr;
2236+
2237+ if (!callback_.is_null()) {
2238+ callback_.Run(false);
2239+ callback_.Reset();
2240+ }
2241+
2242+ if (!cancel_callback_.is_null()) {
2243+ cancel_callback_.Run();
2244+ cancel_callback_.Reset();
2245+ }
2246+}
2247+
2248+void CertificateErrorProxy::SetPlaceholderPage(
2249+ CertificateErrorPlaceholderPage* placeholder) {
2250+ DCHECK(!did_respond_);
2251+ DCHECK(!is_cancelled_);
2252+ placeholder_page_ = placeholder;
2253+}
2254+
2255+} // namespace oxide
2256
2257=== added file 'shared/browser/ssl/oxide_certificate_error_proxy.h'
2258--- shared/browser/ssl/oxide_certificate_error_proxy.h 1970-01-01 00:00:00 +0000
2259+++ shared/browser/ssl/oxide_certificate_error_proxy.h 2015-10-21 20:26:37 +0000
2260@@ -0,0 +1,65 @@
2261+// vim:expandtab:shiftwidth=2:tabstop=2:
2262+// Copyright (C) 2015 Canonical Ltd.
2263+
2264+// This library is free software; you can redistribute it and/or
2265+// modify it under the terms of the GNU Lesser General Public
2266+// License as published by the Free Software Foundation; either
2267+// version 2.1 of the License, or (at your option) any later version.
2268+
2269+// This library is distributed in the hope that it will be useful,
2270+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2271+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2272+// Lesser General Public License for more details.
2273+
2274+// You should have received a copy of the GNU Lesser General Public
2275+// License along with this library; if not, write to the Free Software
2276+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2277+
2278+#ifndef _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PROXY_H_
2279+#define _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PROXY_H_
2280+
2281+#include "base/callback.h"
2282+#include "base/macros.h"
2283+#include "base/memory/ref_counted.h"
2284+
2285+namespace oxide {
2286+
2287+class CertificateErrorPlaceholderPage;
2288+
2289+// This class sits between CertificateError and CertificateErrorPlaceholderPage
2290+class CertificateErrorProxy : public base::RefCounted<CertificateErrorProxy> {
2291+ public:
2292+ CertificateErrorProxy(const base::Callback<void(bool)>& callback);
2293+
2294+ bool is_cancelled() const { return is_cancelled_; }
2295+ bool did_respond() const { return did_respond_; }
2296+
2297+ void set_cancel_callback(const base::Closure& cancel_callback) {
2298+ cancel_callback_ = cancel_callback;
2299+ }
2300+
2301+ void Allow();
2302+ void Deny();
2303+
2304+ void Cancel();
2305+
2306+ void SetPlaceholderPage(CertificateErrorPlaceholderPage* placeholder);
2307+
2308+ private:
2309+ friend class base::RefCounted<CertificateErrorProxy>;
2310+ ~CertificateErrorProxy();
2311+
2312+ base::Callback<void(bool)> callback_;
2313+
2314+ bool is_cancelled_;
2315+ bool did_respond_;
2316+ base::Closure cancel_callback_;
2317+
2318+ CertificateErrorPlaceholderPage* placeholder_page_;
2319+
2320+ DISALLOW_COPY_AND_ASSIGN(CertificateErrorProxy);
2321+};
2322+
2323+} // namespace oxide
2324+
2325+#endif // _OXIDE_SHARED_BROWSER_SSL_CERTIFICATE_ERROR_PROXY_H_
2326
2327=== modified file 'shared/shared.gyp'
2328--- shared/shared.gyp 2015-10-21 17:07:17 +0000
2329+++ shared/shared.gyp 2015-10-21 20:26:37 +0000
2330@@ -352,8 +352,6 @@
2331 'browser/oxide_browser_platform_integration_observer.h',
2332 'browser/oxide_browser_process_main.cc',
2333 'browser/oxide_browser_process_main.h',
2334- 'browser/oxide_certificate_error.cc',
2335- 'browser/oxide_certificate_error.h',
2336 'browser/oxide_content_browser_client.cc',
2337 'browser/oxide_content_browser_client.h',
2338 'browser/oxide_content_types.h',
2339@@ -475,6 +473,15 @@
2340 'browser/permissions/oxide_permission_request_response.h',
2341 'browser/permissions/oxide_temporary_saved_permission_context.cc',
2342 'browser/permissions/oxide_temporary_saved_permission_context.h',
2343+ 'browser/ssl/oxide_certificate_error.cc',
2344+ 'browser/ssl/oxide_certificate_error.h',
2345+ 'browser/ssl/oxide_certificate_error_dispatcher.cc',
2346+ 'browser/ssl/oxide_certificate_error_dispatcher.h',
2347+ 'browser/ssl/oxide_certificate_error_dispatcher_client.h',
2348+ 'browser/ssl/oxide_certificate_error_placeholder_page.cc',
2349+ 'browser/ssl/oxide_certificate_error_placeholder_page.h',
2350+ 'browser/ssl/oxide_certificate_error_proxy.cc',
2351+ 'browser/ssl/oxide_certificate_error_proxy.h',
2352 'common/oxide_constants.cc',
2353 'common/oxide_constants.h',
2354 'common/oxide_content_client.cc',

Subscribers

People subscribed via source and target branches