Merge lp:~michael-sheldon/webbrowser-app/ssl-status into lp:webbrowser-app
- ssl-status
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Olivier Tilloy |
Approved revision: | 731 |
Merged at revision: | 718 |
Proposed branch: | lp:~michael-sheldon/webbrowser-app/ssl-status |
Merge into: | lp:webbrowser-app |
Diff against target: |
874 lines (+658/-70) 6 files modified
po/webbrowser-app.pot (+168/-11) src/app/InvalidCertificateErrorSheet.qml (+215/-0) src/app/WebViewImpl.qml (+11/-0) src/app/webbrowser/AddressBar.qml (+245/-59) src/app/webbrowser/Browser.qml (+18/-0) src/app/webbrowser/Chrome.qml (+1/-0) |
To merge this branch: | bzr merge lp:~michael-sheldon/webbrowser-app/ssl-status |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Olivier Tilloy | Approve | ||
Review via email: mp+235309@code.launchpad.net |
Commit message
* Display padlock when viewing pages over HTTPS.
* Provide certificate details when padlock is clicked.
* Display error pages when invalid SSL certificates are presented and allow users to override these warnings.
* Display warning symbol when insecure content is loaded over HTTPS (currently incorrect icon, should be updated when dialog-
Description of the change
* Display padlock when viewing pages over HTTPS.
* Provide certificate details when padlock is clicked.
* Display error pages when invalid SSL certificates are presented and allow users to override these warnings.
* Display warning symbol when insecure content is loaded over HTTPS (currently incorrect icon, should be updated when dialog-
PS Jenkins bot (ps-jenkins) wrote : | # |
Olivier Tilloy (osomon) wrote : | # |
I don’t see changes to the translation template, despite the new strings. Is that on purpose (i.e. planning to update the file and push to trunk directly after landing)?
So far we’ve been merging translation template updates along with the corresponding code changes, and dealing with conflicts on a case-by-case basis, but I’m open to revising this approach.
Olivier Tilloy (osomon) wrote : | # |
6 + * Copyright 2013-2014 Canonical Ltd.
This should probably be only copyright 2014.
- 722. By Michael Sheldon
-
Fix copyright statement
- 723. By Michael Sheldon
-
Update translation template
Michael Sheldon (michael-sheldon) wrote : | # |
Here are a few sites that can be used to test some different SSL failure conditions:
Expired certificate: https:/
Bad Identity (only valid for https:/
Mix of secure/insecure content: https:/
Dynamic mix of secure/insecure content (secure until play is pressed on a track): https:/
Revoked EV certificate (will cause a crash due to bug 1371569 until the next oxide release): https:/
Olivier Tilloy (osomon) wrote : | # |
I don’t think this is explicitly mentioned in the spec, but I think it would be nice to enable tap on the certificate details popover to dismiss it.
Olivier Tilloy (osomon) wrote : | # |
There seems to be a regression in what the address bar displays, probably not introduced by this MR (maybe by http://
We might want to address this issue as part of this MR, considering that it makes it much more visible to the user.
Olivier Tilloy (osomon) wrote : | # |
If I browse to a site with an invalid security certificate (e.g. https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:723
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
On the invalid security certificate warning page, the "proceed anyway" and "back to safety" button are pretty narrow, translations in many languages that are more verbose than English won’t fit, and they will end up ellipsized. E.g. in French:
"Poursuivre quand même" → "Poursuivre qu…"
"Retour à la sécurité" → "Retour à la séc…"
And the buttons are not resized when changing the orientation of the device to landscape, even though there is more space available. Let’s request design to comment, and in the meantime I would put the two buttons in a column and not constrain their width to ensure the text fits.
Olivier Tilloy (osomon) wrote : | # |
It looks like the dates in the details of the security certificate warning page are incorrectly formatted (or maybe incorrectly exposed by oxide?). For https:/
Olivier Tilloy (osomon) wrote : | # |
> On the invalid security certificate warning page, the "proceed anyway" and
> "back to safety" button are pretty narrow, translations in many languages that
> are more verbose than English won’t fit, and they will end up ellipsized. E.g.
> in French:
A screenshot taken on my krillin to illustrate the issue: http://
Olivier Tilloy (osomon) wrote : | # |
408 + // TRANSLATORS: %1 refers to the SSL certificate's start date
Copy/paste error, this should read "expiry date".
Olivier Tilloy (osomon) wrote : | # |
Some sentences in the invalid certificate warning page are missing a full stop at the end:
"This site security certificate is not trusted"
"You should not proceed, especially if you have never seen this warning before for this site"
Olivier Tilloy (osomon) wrote : | # |
"This site security certificate is not trusted\n…"
The above is repeated in a number of situations, would it be worth making it a separate string in its own label, to save translators some work?
Olivier Tilloy (osomon) wrote : | # |
486 + console.log("Switch failed")
is this really needed?
Olivier Tilloy (osomon) wrote : | # |
285 + target: certificateError ? certificateError : null
isn’t this equivalent to:
target: certificateError
- 724. By Michael Sheldon
-
Place buttons in column and don't restrict their width
- 725. By Michael Sheldon
-
Add missing full stops from certificate error
- 726. By Michael Sheldon
-
Remove stray debug statement
- 727. By Michael Sheldon
-
Fix incorrect translator hint
Olivier Tilloy (osomon) wrote : | # |
365 + onTextChanged: {
366 + // Remove any blank lines caused by missing entries
367 + while(subjectAd
368 + subjectAddress.text = subjectAddress.
369 + }
370 + }
Wouldn’t it be much easier to just do that where 'text' is assigned:
text: i18n.tr(
- 728. By Michael Sheldon
-
Use locale based date display in certificate errors
- 729. By Michael Sheldon
-
Dismiss certificate popover when clicked
Michael Sheldon (michael-sheldon) wrote : | # |
> 285 + target: certificateError ? certificateError : null
>
> isn’t this equivalent to:
>
> target: certificateError
This would cause a warning due to the certificateError being undefined on start up (whereas explicitly setting a null target won't).
Olivier Tilloy (osomon) wrote : | # |
> > 285 + target: certificateError ? certificateError : null
> >
> > isn’t this equivalent to:
> >
> > target: certificateError
>
> This would cause a warning due to the certificateError being undefined on
> start up (whereas explicitly setting a null target won't).
Ah, ok. I would have expected it to be 'null' rather than 'undefined'. The conditional makes sense then.
Michael Sheldon (michael-sheldon) wrote : | # |
I've switched the dates to using the locale date, the incorrect year is a bug in oxide which is being tracked here: https:/
- 730. By Michael Sheldon
-
Simplify removal of extra whitespace in certificate addresses
Michael Sheldon (michael-sheldon) wrote : | # |
> 365 + onTextChanged: {
> 366 + // Remove any blank lines caused by missing
> entries
> 367 + while(subjectAd
> -1) {
> 368 + subjectAddress.text =
> subjectAddress.
> 369 + }
> 370 + }
>
> Wouldn’t it be much easier to just do that where 'text' is assigned:
>
> text: i18n.tr(
Yeah, the problem with that was that since it was only a single pass it could leave extra white space when there'd been three blank lines. But I just realised I could match against /\n+/g to fix that, so I've committed a tidier implementation now.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:727
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 731. By Michael Sheldon
-
Avoid duplication of string on SSL certificate error page
Olivier Tilloy (osomon) wrote : | # |
It all looks good to me now. Thanks!
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:731
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:731
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'po/webbrowser-app.pot' | |||
2 | --- po/webbrowser-app.pot 2014-08-21 11:28:58 +0000 | |||
3 | +++ po/webbrowser-app.pot 2014-09-22 14:01:07 +0000 | |||
4 | @@ -8,7 +8,7 @@ | |||
5 | 8 | msgstr "" | 8 | msgstr "" |
6 | 9 | "Project-Id-Version: webbrowser-app\n" | 9 | "Project-Id-Version: webbrowser-app\n" |
7 | 10 | "Report-Msgid-Bugs-To: \n" | 10 | "Report-Msgid-Bugs-To: \n" |
9 | 11 | "POT-Creation-Date: 2014-08-21 13:27+0200\n" | 11 | "POT-Creation-Date: 2014-09-22 14:59+0100\n" |
10 | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
11 | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
12 | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" |
13 | @@ -75,10 +75,12 @@ | |||
14 | 75 | msgstr "" | 75 | msgstr "" |
15 | 76 | 76 | ||
16 | 77 | #: src/app/CertificateVerificationDialog.qml:29 | 77 | #: src/app/CertificateVerificationDialog.qml:29 |
17 | 78 | #: src/app/InvalidCertificateErrorSheet.qml:162 | ||
18 | 78 | msgid "Proceed anyway" | 79 | msgid "Proceed anyway" |
19 | 79 | msgstr "" | 80 | msgstr "" |
20 | 80 | 81 | ||
21 | 81 | #: src/app/CertificateVerificationDialog.qml:35 | 82 | #: src/app/CertificateVerificationDialog.qml:35 |
22 | 83 | #: src/app/InvalidCertificateErrorSheet.qml:175 | ||
23 | 82 | msgid "Back to safety" | 84 | msgid "Back to safety" |
24 | 83 | msgstr "" | 85 | msgstr "" |
25 | 84 | 86 | ||
26 | @@ -129,6 +131,149 @@ | |||
27 | 129 | msgid "Allow" | 131 | msgid "Allow" |
28 | 130 | msgstr "" | 132 | msgstr "" |
29 | 131 | 133 | ||
30 | 134 | #: src/app/InvalidCertificateErrorSheet.qml:58 | ||
31 | 135 | msgid "This site security certificate is not trusted.\n" | ||
32 | 136 | msgstr "" | ||
33 | 137 | |||
34 | 138 | #: src/app/InvalidCertificateErrorSheet.qml:66 | ||
35 | 139 | msgid "Learn more" | ||
36 | 140 | msgstr "" | ||
37 | 141 | |||
38 | 142 | #. TRANSLATORS: %1 refers to the SSL certificate's serial number | ||
39 | 143 | #: src/app/InvalidCertificateErrorSheet.qml:90 | ||
40 | 144 | #, qt-format | ||
41 | 145 | msgid "" | ||
42 | 146 | "Serial number:\n" | ||
43 | 147 | "%1" | ||
44 | 148 | msgstr "" | ||
45 | 149 | |||
46 | 150 | #. TRANSLATORS: %1 refers to the SSL certificate's subject display name | ||
47 | 151 | #: src/app/InvalidCertificateErrorSheet.qml:97 | ||
48 | 152 | #, qt-format | ||
49 | 153 | msgid "" | ||
50 | 154 | "Subject:\n" | ||
51 | 155 | "%1" | ||
52 | 156 | msgstr "" | ||
53 | 157 | |||
54 | 158 | #. TRANSLATORS: %1 refers to the SSL certificate's subject's address | ||
55 | 159 | #: src/app/InvalidCertificateErrorSheet.qml:105 | ||
56 | 160 | #, qt-format | ||
57 | 161 | msgid "" | ||
58 | 162 | "Subject address:\n" | ||
59 | 163 | "%1" | ||
60 | 164 | msgstr "" | ||
61 | 165 | |||
62 | 166 | #. TRANSLATORS: %1 refers to the SSL certificate's issuer display name | ||
63 | 167 | #: src/app/InvalidCertificateErrorSheet.qml:116 | ||
64 | 168 | #, qt-format | ||
65 | 169 | msgid "" | ||
66 | 170 | "Issuer:\n" | ||
67 | 171 | "%1" | ||
68 | 172 | msgstr "" | ||
69 | 173 | |||
70 | 174 | #. TRANSLATORS: %1 refers to the SSL certificate's issuer's address | ||
71 | 175 | #: src/app/InvalidCertificateErrorSheet.qml:124 | ||
72 | 176 | #, qt-format | ||
73 | 177 | msgid "" | ||
74 | 178 | "Issuer address:\n" | ||
75 | 179 | "%1" | ||
76 | 180 | msgstr "" | ||
77 | 181 | |||
78 | 182 | #. TRANSLATORS: %1 refers to the SSL certificate's start date | ||
79 | 183 | #: src/app/InvalidCertificateErrorSheet.qml:135 | ||
80 | 184 | #, qt-format | ||
81 | 185 | msgid "" | ||
82 | 186 | "Valid from:\n" | ||
83 | 187 | "%1" | ||
84 | 188 | msgstr "" | ||
85 | 189 | |||
86 | 190 | #. TRANSLATORS: %1 refers to the SSL certificate's expiry date | ||
87 | 191 | #: src/app/InvalidCertificateErrorSheet.qml:142 | ||
88 | 192 | #, qt-format | ||
89 | 193 | msgid "" | ||
90 | 194 | "Valid until:\n" | ||
91 | 195 | "%1" | ||
92 | 196 | msgstr "" | ||
93 | 197 | |||
94 | 198 | #. TRANSLATORS: %1 refers to the SSL certificate's SHA1 fingerprint | ||
95 | 199 | #: src/app/InvalidCertificateErrorSheet.qml:149 | ||
96 | 200 | #, qt-format | ||
97 | 201 | msgid "" | ||
98 | 202 | "Fingerprint (SHA1):\n" | ||
99 | 203 | "%1" | ||
100 | 204 | msgstr "" | ||
101 | 205 | |||
102 | 206 | #: src/app/InvalidCertificateErrorSheet.qml:155 | ||
103 | 207 | msgid "" | ||
104 | 208 | "You should not proceed, especially if you have never seen this warning " | ||
105 | 209 | "before for this site." | ||
106 | 210 | msgstr "" | ||
107 | 211 | |||
108 | 212 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
109 | 213 | #: src/app/InvalidCertificateErrorSheet.qml:190 | ||
110 | 214 | #, qt-format | ||
111 | 215 | msgid "" | ||
112 | 216 | "You attempted to reach %1 but the server presented a security certificate " | ||
113 | 217 | "which does not match the identity of the site." | ||
114 | 218 | msgstr "" | ||
115 | 219 | |||
116 | 220 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
117 | 221 | #: src/app/InvalidCertificateErrorSheet.qml:193 | ||
118 | 222 | #, qt-format | ||
119 | 223 | msgid "" | ||
120 | 224 | "You attempted to reach %1 but the server presented a security certificate " | ||
121 | 225 | "which has expired." | ||
122 | 226 | msgstr "" | ||
123 | 227 | |||
124 | 228 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
125 | 229 | #: src/app/InvalidCertificateErrorSheet.qml:196 | ||
126 | 230 | #, qt-format | ||
127 | 231 | msgid "" | ||
128 | 232 | "You attempted to reach %1 but the server presented a security certificate " | ||
129 | 233 | "which contains invalid dates." | ||
130 | 234 | msgstr "" | ||
131 | 235 | |||
132 | 236 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
133 | 237 | #: src/app/InvalidCertificateErrorSheet.qml:199 | ||
134 | 238 | #, qt-format | ||
135 | 239 | msgid "" | ||
136 | 240 | "You attempted to reach %1 but the server presented a security certificate " | ||
137 | 241 | "issued by an entity that is not trusted." | ||
138 | 242 | msgstr "" | ||
139 | 243 | |||
140 | 244 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
141 | 245 | #: src/app/InvalidCertificateErrorSheet.qml:202 | ||
142 | 246 | #, qt-format | ||
143 | 247 | msgid "" | ||
144 | 248 | "You attempted to reach %1 but the server presented a security certificate " | ||
145 | 249 | "that has been revoked." | ||
146 | 250 | msgstr "" | ||
147 | 251 | |||
148 | 252 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
149 | 253 | #: src/app/InvalidCertificateErrorSheet.qml:205 | ||
150 | 254 | #, qt-format | ||
151 | 255 | msgid "" | ||
152 | 256 | "You attempted to reach %1 but the server presented an invalid security " | ||
153 | 257 | "certificate." | ||
154 | 258 | msgstr "" | ||
155 | 259 | |||
156 | 260 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
157 | 261 | #: src/app/InvalidCertificateErrorSheet.qml:208 | ||
158 | 262 | #, qt-format | ||
159 | 263 | msgid "" | ||
160 | 264 | "You attempted to reach %1 but the server presented an insecure security " | ||
161 | 265 | "certificate." | ||
162 | 266 | msgstr "" | ||
163 | 267 | |||
164 | 268 | #. TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
165 | 269 | #: src/app/InvalidCertificateErrorSheet.qml:211 | ||
166 | 270 | #, qt-format | ||
167 | 271 | msgid "" | ||
168 | 272 | "This site security certificate is not trusted\n" | ||
169 | 273 | "You attempted to reach %1 but the server presented a security certificate " | ||
170 | 274 | "which failed our security checks for an unknown reason." | ||
171 | 275 | msgstr "" | ||
172 | 276 | |||
173 | 132 | #: src/app/PromptDialog.qml:23 | 277 | #: src/app/PromptDialog.qml:23 |
174 | 133 | msgid "JavaScript Prompt" | 278 | msgid "JavaScript Prompt" |
175 | 134 | msgstr "" | 279 | msgstr "" |
176 | @@ -245,23 +390,35 @@ | |||
177 | 245 | msgid "Share…" | 390 | msgid "Share…" |
178 | 246 | msgstr "" | 391 | msgstr "" |
179 | 247 | 392 | ||
181 | 248 | #: src/app/webbrowser/AddressBar.qml:148 | 393 | #: src/app/webbrowser/AddressBar.qml:214 |
182 | 394 | msgid "This site has insecure content" | ||
183 | 395 | msgstr "" | ||
184 | 396 | |||
185 | 397 | #: src/app/webbrowser/AddressBar.qml:229 | ||
186 | 398 | msgid "You are connected to" | ||
187 | 399 | msgstr "" | ||
188 | 400 | |||
189 | 401 | #: src/app/webbrowser/AddressBar.qml:251 | ||
190 | 402 | msgid "Which is run by" | ||
191 | 403 | msgstr "" | ||
192 | 404 | |||
193 | 405 | #: src/app/webbrowser/AddressBar.qml:335 | ||
194 | 249 | msgid "search or enter an address" | 406 | msgid "search or enter an address" |
195 | 250 | msgstr "" | 407 | msgstr "" |
196 | 251 | 408 | ||
198 | 252 | #: src/app/webbrowser/Browser.qml:154 | 409 | #: src/app/webbrowser/Browser.qml:179 |
199 | 253 | msgid "Share" | 410 | msgid "Share" |
200 | 254 | msgstr "" | 411 | msgstr "" |
201 | 255 | 412 | ||
203 | 256 | #: src/app/webbrowser/Browser.qml:168 | 413 | #: src/app/webbrowser/Browser.qml:193 |
204 | 257 | msgid "History" | 414 | msgid "History" |
205 | 258 | msgstr "" | 415 | msgstr "" |
206 | 259 | 416 | ||
208 | 260 | #: src/app/webbrowser/Browser.qml:174 | 417 | #: src/app/webbrowser/Browser.qml:200 |
209 | 261 | msgid "Open tabs" | 418 | msgid "Open tabs" |
210 | 262 | msgstr "" | 419 | msgstr "" |
211 | 263 | 420 | ||
213 | 264 | #: src/app/webbrowser/Browser.qml:180 src/app/webbrowser/TabsView.qml:57 | 421 | #: src/app/webbrowser/Browser.qml:206 src/app/webbrowser/TabsView.qml:57 |
214 | 265 | msgid "New tab" | 422 | msgid "New tab" |
215 | 266 | msgstr "" | 423 | msgstr "" |
216 | 267 | 424 | ||
217 | @@ -330,25 +487,25 @@ | |||
218 | 330 | 487 | ||
219 | 331 | #. TRANSLATORS: %1 refers to the current page’s title | 488 | #. TRANSLATORS: %1 refers to the current page’s title |
220 | 332 | #: src/app/webbrowser/webbrowser-app.qml:39 | 489 | #: src/app/webbrowser/webbrowser-app.qml:39 |
222 | 333 | #: src/app/webcontainer/webapp-container.qml:57 | 490 | #: src/app/webcontainer/webapp-container.qml:60 |
223 | 334 | #, qt-format | 491 | #, qt-format |
224 | 335 | msgid "%1 - Ubuntu Web Browser" | 492 | msgid "%1 - Ubuntu Web Browser" |
225 | 336 | msgstr "" | 493 | msgstr "" |
226 | 337 | 494 | ||
227 | 338 | #: src/app/webbrowser/webbrowser-app.qml:41 | 495 | #: src/app/webbrowser/webbrowser-app.qml:41 |
229 | 339 | #: src/app/webcontainer/webapp-container.qml:59 | 496 | #: src/app/webcontainer/webapp-container.qml:62 |
230 | 340 | msgid "Ubuntu Web Browser" | 497 | msgid "Ubuntu Web Browser" |
231 | 341 | msgstr "" | 498 | msgstr "" |
232 | 342 | 499 | ||
234 | 343 | #: src/app/webcontainer/AccountsLoginPage.qml:70 | 500 | #: src/app/webcontainer/AccountsLoginPage.qml:87 |
235 | 344 | msgid "No local account found for " | 501 | msgid "No local account found for " |
236 | 345 | msgstr "" | 502 | msgstr "" |
237 | 346 | 503 | ||
239 | 347 | #: src/app/webcontainer/AccountsLoginPage.qml:75 | 504 | #: src/app/webcontainer/AccountsLoginPage.qml:92 |
240 | 348 | msgid "Skip account creation step" | 505 | msgid "Skip account creation step" |
241 | 349 | msgstr "" | 506 | msgstr "" |
242 | 350 | 507 | ||
244 | 351 | #: src/app/webcontainer/AccountsLoginPage.qml:124 | 508 | #: src/app/webcontainer/AccountsLoginPage.qml:141 |
245 | 352 | msgid "Add account" | 509 | msgid "Add account" |
246 | 353 | msgstr "" | 510 | msgstr "" |
247 | 354 | 511 | ||
248 | 355 | 512 | ||
249 | === added file 'src/app/InvalidCertificateErrorSheet.qml' | |||
250 | --- src/app/InvalidCertificateErrorSheet.qml 1970-01-01 00:00:00 +0000 | |||
251 | +++ src/app/InvalidCertificateErrorSheet.qml 2014-09-22 14:01:07 +0000 | |||
252 | @@ -0,0 +1,215 @@ | |||
253 | 1 | /* | ||
254 | 2 | * Copyright 2014 Canonical Ltd. | ||
255 | 3 | * | ||
256 | 4 | * This file is part of webbrowser-app. | ||
257 | 5 | * | ||
258 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
259 | 7 | * it under the terms of the GNU General Public License as published by | ||
260 | 8 | * the Free Software Foundation; version 3. | ||
261 | 9 | * | ||
262 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
263 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
264 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
265 | 13 | * GNU General Public License for more details. | ||
266 | 14 | * | ||
267 | 15 | * You should have received a copy of the GNU General Public License | ||
268 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
269 | 17 | */ | ||
270 | 18 | |||
271 | 19 | import QtQuick 2.0 | ||
272 | 20 | import Ubuntu.Components 1.1 | ||
273 | 21 | import com.canonical.Oxide 1.0 as Oxide | ||
274 | 22 | |||
275 | 23 | Rectangle { | ||
276 | 24 | property var certificateError | ||
277 | 25 | |||
278 | 26 | signal allowed() | ||
279 | 27 | signal denied() | ||
280 | 28 | |||
281 | 29 | Connections { | ||
282 | 30 | target: certificateError ? certificateError : null | ||
283 | 31 | onCancelled: { | ||
284 | 32 | moreInfo.visible = false | ||
285 | 33 | denied() | ||
286 | 34 | } | ||
287 | 35 | } | ||
288 | 36 | |||
289 | 37 | Flickable { | ||
290 | 38 | anchors.fill: parent | ||
291 | 39 | anchors.margins: units.gu(4) | ||
292 | 40 | contentHeight: errorCol.height | ||
293 | 41 | |||
294 | 42 | Column { | ||
295 | 43 | id: errorCol | ||
296 | 44 | anchors.centerIn: parent | ||
297 | 45 | width: parent.width | ||
298 | 46 | |||
299 | 47 | spacing: units.gu(3) | ||
300 | 48 | |||
301 | 49 | Icon { | ||
302 | 50 | anchors.horizontalCenter: parent.horizontalCenter | ||
303 | 51 | name: "security-alert" | ||
304 | 52 | width: units.gu(4) | ||
305 | 53 | height: width | ||
306 | 54 | } | ||
307 | 55 | |||
308 | 56 | Label { | ||
309 | 57 | width: parent.width | ||
310 | 58 | text: certificateError ? i18n.tr("This site security certificate is not trusted.\n") + textForError(certificateError.certError) : "" | ||
311 | 59 | wrapMode: Text.Wrap | ||
312 | 60 | horizontalAlignment: Text.AlignHCenter | ||
313 | 61 | fontSize: "x-small" | ||
314 | 62 | } | ||
315 | 63 | |||
316 | 64 | Label { | ||
317 | 65 | width: parent.width | ||
318 | 66 | text: i18n.tr("Learn more") | ||
319 | 67 | font.underline: true | ||
320 | 68 | fontSize: "x-small" | ||
321 | 69 | horizontalAlignment: Text.AlignHCenter | ||
322 | 70 | visible: !moreInfo.visible | ||
323 | 71 | MouseArea { | ||
324 | 72 | anchors.fill: parent | ||
325 | 73 | onClicked: { | ||
326 | 74 | moreInfo.visible = true | ||
327 | 75 | } | ||
328 | 76 | } | ||
329 | 77 | } | ||
330 | 78 | |||
331 | 79 | Column { | ||
332 | 80 | id: moreInfo | ||
333 | 81 | width: parent.width | ||
334 | 82 | visible: false | ||
335 | 83 | spacing: units.gu(1) | ||
336 | 84 | |||
337 | 85 | Label { | ||
338 | 86 | fontSize: "x-small" | ||
339 | 87 | width: parent.width | ||
340 | 88 | wrapMode: Text.Wrap | ||
341 | 89 | // TRANSLATORS: %1 refers to the SSL certificate's serial number | ||
342 | 90 | text: i18n.tr("Serial number:\n%1").arg(certificateError ? certificateError.certificate.serialNumber : "") | ||
343 | 91 | } | ||
344 | 92 | Label { | ||
345 | 93 | fontSize: "x-small" | ||
346 | 94 | width: parent.width | ||
347 | 95 | wrapMode: Text.Wrap | ||
348 | 96 | // TRANSLATORS: %1 refers to the SSL certificate's subject display name | ||
349 | 97 | text: i18n.tr("Subject:\n%1").arg(certificateError ? certificateError.certificate.subjectDisplayName : "") | ||
350 | 98 | } | ||
351 | 99 | Label { | ||
352 | 100 | id: subjectAddress | ||
353 | 101 | fontSize: "x-small" | ||
354 | 102 | width: parent.width | ||
355 | 103 | wrapMode: Text.Wrap | ||
356 | 104 | // TRANSLATORS: %1 refers to the SSL certificate's subject's address | ||
357 | 105 | text: i18n.tr("Subject address:\n%1").arg(certificateError ? | ||
358 | 106 | (certificateError.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrOrganizationName).join(", ") + "\n" + | ||
359 | 107 | certificateError.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrLocalityName).join(", ") + "\n" + | ||
360 | 108 | certificateError.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrStateOrProvinceName).join(", ") + "\n" + | ||
361 | 109 | certificateError.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrCountryName).join(", ")).replace(/\n+/g, "\n") : "") | ||
362 | 110 | } | ||
363 | 111 | Label { | ||
364 | 112 | fontSize: "x-small" | ||
365 | 113 | width: parent.width | ||
366 | 114 | wrapMode: Text.Wrap | ||
367 | 115 | // TRANSLATORS: %1 refers to the SSL certificate's issuer display name | ||
368 | 116 | text: i18n.tr("Issuer:\n%1").arg(certificateError ? certificateError.certificate.issuerDisplayName : "") | ||
369 | 117 | } | ||
370 | 118 | Label { | ||
371 | 119 | id: issuerAddress | ||
372 | 120 | fontSize: "x-small" | ||
373 | 121 | width: parent.width | ||
374 | 122 | wrapMode: Text.Wrap | ||
375 | 123 | // TRANSLATORS: %1 refers to the SSL certificate's issuer's address | ||
376 | 124 | text: i18n.tr("Issuer address:\n%1").arg(certificateError ? | ||
377 | 125 | (certificateError.certificate.getIssuerInfo(Oxide.SslCertificate.PrincipalAttrOrganizationName).join(", ") + "\n" + | ||
378 | 126 | certificateError.certificate.getIssuerInfo(Oxide.SslCertificate.PrincipalAttrLocalityName).join(", ") + "\n" + | ||
379 | 127 | certificateError.certificate.getIssuerInfo(Oxide.SslCertificate.PrincipalAttrStateOrProvinceName).join(", ") + "\n" + | ||
380 | 128 | certificateError.certificate.getIssuerInfo(Oxide.SslCertificate.PrincipalAttrCountryName).join(", ")).replace(/\n+/g, "\n") : "") | ||
381 | 129 | } | ||
382 | 130 | Label { | ||
383 | 131 | fontSize: "x-small" | ||
384 | 132 | width: parent.width | ||
385 | 133 | wrapMode: Text.Wrap | ||
386 | 134 | // TRANSLATORS: %1 refers to the SSL certificate's start date | ||
387 | 135 | text: i18n.tr("Valid from:\n%1").arg(certificateError ? certificateError.certificate.effectiveDate.toLocaleString() : "") | ||
388 | 136 | } | ||
389 | 137 | Label { | ||
390 | 138 | fontSize: "x-small" | ||
391 | 139 | width: parent.width | ||
392 | 140 | wrapMode: Text.Wrap | ||
393 | 141 | // TRANSLATORS: %1 refers to the SSL certificate's expiry date | ||
394 | 142 | text: i18n.tr("Valid until:\n%1").arg(certificateError ? certificateError.certificate.expiryDate.toLocaleString() : "") | ||
395 | 143 | } | ||
396 | 144 | Label { | ||
397 | 145 | fontSize: "x-small" | ||
398 | 146 | width: parent.width | ||
399 | 147 | wrapMode: Text.Wrap | ||
400 | 148 | // TRANSLATORS: %1 refers to the SSL certificate's SHA1 fingerprint | ||
401 | 149 | text: i18n.tr("Fingerprint (SHA1):\n%1").arg(certificateError ? certificateError.certificate.fingerprintSHA1 : "") | ||
402 | 150 | } | ||
403 | 151 | } | ||
404 | 152 | |||
405 | 153 | Label { | ||
406 | 154 | width: parent.width | ||
407 | 155 | text: i18n.tr("You should not proceed, especially if you have never seen this warning before for this site.") | ||
408 | 156 | wrapMode: Text.Wrap | ||
409 | 157 | fontSize: "x-small" | ||
410 | 158 | horizontalAlignment: Text.AlignHCenter | ||
411 | 159 | } | ||
412 | 160 | |||
413 | 161 | Button { | ||
414 | 162 | text: i18n.tr("Proceed anyway") | ||
415 | 163 | anchors.horizontalCenter: parent.horizontalCenter | ||
416 | 164 | visible: certificateError ? certificateError.overridable : false | ||
417 | 165 | onClicked: { | ||
418 | 166 | moreInfo.visible = false | ||
419 | 167 | certificateError.allow() | ||
420 | 168 | allowed() | ||
421 | 169 | } | ||
422 | 170 | } | ||
423 | 171 | |||
424 | 172 | Button { | ||
425 | 173 | id: backButton | ||
426 | 174 | anchors.horizontalCenter: parent.horizontalCenter | ||
427 | 175 | text: i18n.tr("Back to safety") | ||
428 | 176 | onClicked: { | ||
429 | 177 | moreInfo.visible = false | ||
430 | 178 | certificateError.deny() | ||
431 | 179 | denied() | ||
432 | 180 | } | ||
433 | 181 | color: UbuntuColors.orange | ||
434 | 182 | } | ||
435 | 183 | } | ||
436 | 184 | } | ||
437 | 185 | |||
438 | 186 | function textForError(error) { | ||
439 | 187 | switch(error) { | ||
440 | 188 | case Oxide.CertificateError.ErrorBadIdentity: | ||
441 | 189 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
442 | 190 | return i18n.tr("You attempted to reach %1 but the server presented a security certificate which does not match the identity of the site.").arg(certificateError ? certificateError.url : "") | ||
443 | 191 | case Oxide.CertificateError.ErrorExpired: | ||
444 | 192 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
445 | 193 | return i18n.tr("You attempted to reach %1 but the server presented a security certificate which has expired.").arg(certificateError ? certificateError.url : "") | ||
446 | 194 | case Oxide.CertificateError.ErrorDateInvalid: | ||
447 | 195 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
448 | 196 | return i18n.tr("You attempted to reach %1 but the server presented a security certificate which contains invalid dates.").arg(certificateError ? certificateError.url : "") | ||
449 | 197 | case Oxide.CertificateError.ErrorAuthorityInvalid: | ||
450 | 198 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
451 | 199 | return i18n.tr("You attempted to reach %1 but the server presented a security certificate issued by an entity that is not trusted.").arg(certificateError ? certificateError.url : "") | ||
452 | 200 | case Oxide.CertificateError.ErrorRevoked: | ||
453 | 201 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
454 | 202 | return i18n.tr("You attempted to reach %1 but the server presented a security certificate that has been revoked.").arg(certificateError ? certificateError.url : "") | ||
455 | 203 | case Oxide.CertificateError.ErrorInvalid: | ||
456 | 204 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
457 | 205 | return i18n.tr("You attempted to reach %1 but the server presented an invalid security certificate.").arg(certificateError ? certificateError.url : "") | ||
458 | 206 | case Oxide.CertificateError.ErrorInsecure: | ||
459 | 207 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
460 | 208 | return i18n.tr("You attempted to reach %1 but the server presented an insecure security certificate.").arg(certificateError ? certificateError.url : "") | ||
461 | 209 | default: | ||
462 | 210 | // TRANSLATORS: %1 refers to the domain name of the SSL certificate | ||
463 | 211 | return i18n.tr("This site security certificate is not trusted\nYou attempted to reach %1 but the server presented a security certificate which failed our security checks for an unknown reason.").arg(certificateError ? certificateError.url : "") | ||
464 | 212 | } | ||
465 | 213 | } | ||
466 | 214 | |||
467 | 215 | } | ||
468 | 0 | 216 | ||
469 | === modified file 'src/app/WebViewImpl.qml' | |||
470 | --- src/app/WebViewImpl.qml 2014-08-21 16:45:23 +0000 | |||
471 | +++ src/app/WebViewImpl.qml 2014-09-22 14:01:07 +0000 | |||
472 | @@ -26,6 +26,9 @@ | |||
473 | 26 | id: webview | 26 | id: webview |
474 | 27 | 27 | ||
475 | 28 | property var currentWebview: webview | 28 | property var currentWebview: webview |
476 | 29 | property var certificateError | ||
477 | 30 | // Invalid certificates the user has explicitly allowed for this session | ||
478 | 31 | property var allowedCertificates: [] | ||
479 | 29 | 32 | ||
480 | 30 | /*experimental.certificateVerificationDialog: CertificateVerificationDialog {} | 33 | /*experimental.certificateVerificationDialog: CertificateVerificationDialog {} |
481 | 31 | experimental.authenticationDialog: AuthenticationDialog {} | 34 | experimental.authenticationDialog: AuthenticationDialog {} |
482 | @@ -74,4 +77,12 @@ | |||
483 | 74 | // TODO: we might want to store the answer to avoid requesting | 77 | // TODO: we might want to store the answer to avoid requesting |
484 | 75 | // the permission everytime the user visits this site. | 78 | // the permission everytime the user visits this site. |
485 | 76 | } | 79 | } |
486 | 80 | |||
487 | 81 | onCertificateError: { | ||
488 | 82 | if(webview.allowedCertificates.indexOf(error.certificate.fingerprintSHA1) != -1) { | ||
489 | 83 | error.allow() | ||
490 | 84 | } else { | ||
491 | 85 | certificateError = error | ||
492 | 86 | } | ||
493 | 87 | } | ||
494 | 77 | } | 88 | } |
495 | 78 | 89 | ||
496 | === modified file 'src/app/webbrowser/AddressBar.qml' | |||
497 | --- src/app/webbrowser/AddressBar.qml 2014-09-08 10:10:48 +0000 | |||
498 | +++ src/app/webbrowser/AddressBar.qml 2014-09-22 14:01:07 +0000 | |||
499 | @@ -18,6 +18,9 @@ | |||
500 | 18 | 18 | ||
501 | 19 | import QtQuick 2.0 | 19 | import QtQuick 2.0 |
502 | 20 | import Ubuntu.Components 1.1 | 20 | import Ubuntu.Components 1.1 |
503 | 21 | import Ubuntu.Components.Popups 1.0 | ||
504 | 22 | import Ubuntu.Components.ListItems 1.0 | ||
505 | 23 | import com.canonical.Oxide 1.0 as Oxide | ||
506 | 21 | import ".." | 24 | import ".." |
507 | 22 | 25 | ||
508 | 23 | FocusScope { | 26 | FocusScope { |
509 | @@ -28,6 +31,7 @@ | |||
510 | 28 | property bool bookmarked: false | 31 | property bool bookmarked: false |
511 | 29 | property url requestedUrl | 32 | property url requestedUrl |
512 | 30 | property url actualUrl | 33 | property url actualUrl |
513 | 34 | property var securityStatus | ||
514 | 31 | signal validated() | 35 | signal validated() |
515 | 32 | property bool loading | 36 | property bool loading |
516 | 33 | signal requestReload() | 37 | signal requestReload() |
517 | @@ -55,68 +59,250 @@ | |||
518 | 55 | anchors.fill: parent | 59 | anchors.fill: parent |
519 | 56 | 60 | ||
520 | 57 | primaryItem: Item { | 61 | primaryItem: Item { |
540 | 58 | height: textField.height | 62 | width: iconsRow.width |
541 | 59 | width: height | 63 | height: iconsRow.height |
542 | 60 | 64 | Row { | |
543 | 61 | Favicon { | 65 | id: iconsRow |
544 | 62 | id: favicon | 66 | Item { |
545 | 63 | anchors.centerIn: parent | 67 | height: textField.height |
527 | 64 | visible: (addressbar.state == "") && addressbar.actualUrl.toString() | ||
528 | 65 | } | ||
529 | 66 | |||
530 | 67 | MouseArea { | ||
531 | 68 | id: actionButton | ||
532 | 69 | objectName: "actionButton" | ||
533 | 70 | anchors.fill: parent | ||
534 | 71 | enabled: addressbar.text | ||
535 | 72 | opacity: enabled ? 1.0 : 0.3 | ||
536 | 73 | |||
537 | 74 | Icon { | ||
538 | 75 | id: actionIcon | ||
539 | 76 | height: parent.height - units.gu(2) | ||
546 | 77 | width: height | 68 | width: height |
566 | 78 | anchors.centerIn: parent | 69 | visible: securityStatus ? securityStatus.securityLevel != Oxide.SecurityStatus.SecurityLevelWarning || addressbar.state != "" : true |
567 | 79 | name: { | 70 | |
568 | 80 | switch (addressbar.state) { | 71 | Favicon { |
569 | 81 | case "loading": | 72 | id: favicon |
570 | 82 | return "stop" | 73 | anchors.centerIn: parent |
571 | 83 | case "editing": | 74 | visible: securityStatus ? (securityStatus.securityLevel != Oxide.SecurityStatus.SecurityLevelWarning) && (addressbar.state == "") && addressbar.actualUrl.toString() : (addressbar.state == "") && addressbar.actualUrl.toString() |
572 | 84 | if (addressbar.text && (addressbar.text == addressbar.actualUrl)) { | 75 | } |
573 | 85 | return "reload" | 76 | |
574 | 86 | } else if (looksLikeAUrl(addressbar.text.trim())) { | 77 | Item { |
575 | 87 | return "stock_website" | 78 | id: certificatePopoverPositioner |
576 | 88 | } else { | 79 | anchors.bottom: favicon.bottom |
577 | 89 | return "search" | 80 | anchors.horizontalCenter: favicon.horizontalCenter |
578 | 90 | } | 81 | } |
579 | 91 | default: | 82 | |
580 | 92 | if (!favicon.visible) { | 83 | MouseArea { |
581 | 93 | if (looksLikeAUrl(addressbar.text.trim())) { | 84 | id: actionButton |
582 | 94 | return "stock_website" | 85 | objectName: "actionButton" |
583 | 95 | } else { | 86 | anchors.fill: parent |
584 | 96 | return "search" | 87 | enabled: addressbar.text |
585 | 88 | opacity: enabled ? 1.0 : 0.3 | ||
586 | 89 | |||
587 | 90 | Icon { | ||
588 | 91 | id: actionIcon | ||
589 | 92 | height: parent.height - units.gu(2) | ||
590 | 93 | width: height | ||
591 | 94 | anchors.centerIn: parent | ||
592 | 95 | name: { | ||
593 | 96 | switch (addressbar.state) { | ||
594 | 97 | case "loading": | ||
595 | 98 | return "stop" | ||
596 | 99 | case "editing": | ||
597 | 100 | if (addressbar.text && (addressbar.text == addressbar.actualUrl)) { | ||
598 | 101 | return "reload" | ||
599 | 102 | } else if (looksLikeAUrl(addressbar.text.trim())) { | ||
600 | 103 | return "stock_website" | ||
601 | 104 | } else { | ||
602 | 105 | return "search" | ||
603 | 106 | } | ||
604 | 107 | default: | ||
605 | 108 | if (!favicon.visible) { | ||
606 | 109 | if (looksLikeAUrl(addressbar.text.trim())) { | ||
607 | 110 | return "stock_website" | ||
608 | 111 | } else { | ||
609 | 112 | return "search" | ||
610 | 113 | } | ||
611 | 114 | } else { | ||
612 | 115 | return "" | ||
613 | 116 | } | ||
614 | 97 | } | 117 | } |
621 | 98 | } else { | 118 | } |
622 | 99 | return "" | 119 | } |
623 | 100 | } | 120 | |
624 | 101 | } | 121 | onClicked: { |
625 | 102 | } | 122 | switch (actionIcon.name) { |
626 | 103 | } | 123 | case "": |
627 | 124 | break; | ||
628 | 125 | case "stop": | ||
629 | 126 | addressbar.requestStop() | ||
630 | 127 | break | ||
631 | 128 | case "reload": | ||
632 | 129 | addressbar.requestReload() | ||
633 | 130 | break | ||
634 | 131 | default: | ||
635 | 132 | textField.accepted() | ||
636 | 133 | } | ||
637 | 134 | } | ||
638 | 135 | } | ||
639 | 136 | |||
640 | 137 | } | ||
641 | 138 | |||
642 | 139 | Item { | ||
643 | 140 | id: securityDisplay | ||
644 | 141 | height: textField.height | ||
645 | 142 | width: securityIcon.width | ||
646 | 143 | visible: securityStatus ? (securityStatus.securityLevel == Oxide.SecurityStatus.SecurityLevelSecure || securityStatus.securityLevel == Oxide.SecurityStatus.SecurityLevelSecureEV || securityStatus.securityLevel == Oxide.SecurityStatus.SecurityLevelWarning) && addressbar.state == "" : false | ||
647 | 144 | |||
648 | 145 | Icon { | ||
649 | 146 | id: securityIcon | ||
650 | 147 | anchors.centerIn: parent | ||
651 | 148 | height: parent.height - units.gu(2) | ||
652 | 149 | width: height | ||
653 | 150 | name: "network-secure" | ||
654 | 151 | } | ||
655 | 152 | } | ||
656 | 153 | |||
657 | 154 | Item { | ||
658 | 155 | id: securityWarning | ||
659 | 156 | height: textField.height | ||
660 | 157 | width: warningIcon.width | ||
661 | 158 | visible: securityStatus ? securityStatus.securityLevel == Oxide.SecurityStatus.SecurityLevelWarning && addressbar.state == "" : false | ||
662 | 159 | |||
663 | 160 | Icon { | ||
664 | 161 | id: warningIcon | ||
665 | 162 | anchors.centerIn: parent | ||
666 | 163 | height: parent.height - units.gu(2) | ||
667 | 164 | width: height | ||
668 | 165 | name: "security-alert" | ||
669 | 166 | } | ||
670 | 167 | } | ||
671 | 168 | |||
672 | 169 | } | ||
673 | 170 | |||
674 | 171 | MouseArea { | ||
675 | 172 | enabled: securityDisplay.visible && addressbar.state != "editing" && addressbar.state != "loading" | ||
676 | 173 | anchors.fill: parent | ||
677 | 104 | 174 | ||
678 | 105 | onClicked: { | 175 | onClicked: { |
693 | 106 | switch (actionIcon.name) { | 176 | PopupUtils.open(certificatePopoverComponent, certificatePopoverPositioner) |
694 | 107 | case "": | 177 | } |
695 | 108 | break; | 178 | } |
696 | 109 | case "stop": | 179 | |
697 | 110 | addressbar.requestStop() | 180 | |
698 | 111 | break | 181 | Component { |
699 | 112 | case "reload": | 182 | id: certificatePopoverComponent |
700 | 113 | addressbar.requestReload() | 183 | Popover { |
701 | 114 | break | 184 | id: certificatePopover |
702 | 115 | default: | 185 | Column { |
703 | 116 | textField.accepted() | 186 | id: certificateDetails |
704 | 117 | } | 187 | width: parent.width - units.gu(4) |
705 | 118 | } | 188 | anchors.horizontalCenter: parent.horizontalCenter |
706 | 119 | } | 189 | spacing: units.gu(0.5) |
707 | 190 | |||
708 | 191 | Item { | ||
709 | 192 | height: units.gu(1.5) | ||
710 | 193 | width: parent.width | ||
711 | 194 | } | ||
712 | 195 | |||
713 | 196 | Column { | ||
714 | 197 | width: parent.width | ||
715 | 198 | visible: securityStatus.securityLevel == Oxide.SecurityStatus.SecurityLevelWarning | ||
716 | 199 | spacing: units.gu(0.5) | ||
717 | 200 | |||
718 | 201 | Row { | ||
719 | 202 | width: parent.width | ||
720 | 203 | spacing: units.gu(0.5) | ||
721 | 204 | |||
722 | 205 | Icon { | ||
723 | 206 | name: "security-alert" | ||
724 | 207 | height: units.gu(2) | ||
725 | 208 | width: height | ||
726 | 209 | } | ||
727 | 210 | |||
728 | 211 | Label { | ||
729 | 212 | width: parent.width | ||
730 | 213 | wrapMode: Text.WordWrap | ||
731 | 214 | text: i18n.tr("This site has insecure content") | ||
732 | 215 | fontSize: "x-small" | ||
733 | 216 | } | ||
734 | 217 | } | ||
735 | 218 | |||
736 | 219 | ThinDivider { | ||
737 | 220 | width: parent.width | ||
738 | 221 | anchors.leftMargin: 0 | ||
739 | 222 | anchors.rightMargin: 0 | ||
740 | 223 | } | ||
741 | 224 | } | ||
742 | 225 | |||
743 | 226 | Label { | ||
744 | 227 | width: parent.width | ||
745 | 228 | wrapMode: Text.WordWrap | ||
746 | 229 | text: i18n.tr("You are connected to") | ||
747 | 230 | fontSize: "x-small" | ||
748 | 231 | } | ||
749 | 232 | |||
750 | 233 | Label { | ||
751 | 234 | width: parent.width | ||
752 | 235 | wrapMode: Text.WordWrap | ||
753 | 236 | text: securityStatus.certificate.subjectDisplayName | ||
754 | 237 | fontSize: "x-small" | ||
755 | 238 | } | ||
756 | 239 | |||
757 | 240 | ThinDivider { | ||
758 | 241 | width: parent.width | ||
759 | 242 | anchors.leftMargin: 0 | ||
760 | 243 | anchors.rightMargin: 0 | ||
761 | 244 | visible: orgName.visible || localityName.visible || stateName.visible || countryName.visible | ||
762 | 245 | } | ||
763 | 246 | |||
764 | 247 | Label { | ||
765 | 248 | width: parent.width | ||
766 | 249 | wrapMode: Text.WordWrap | ||
767 | 250 | visible: orgName.visible | ||
768 | 251 | text: i18n.tr("Which is run by") | ||
769 | 252 | fontSize: "x-small" | ||
770 | 253 | } | ||
771 | 254 | |||
772 | 255 | Label { | ||
773 | 256 | id: orgName | ||
774 | 257 | width: parent.width | ||
775 | 258 | wrapMode: Text.WordWrap | ||
776 | 259 | visible: text.length > 0 | ||
777 | 260 | text: securityStatus.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrOrganizationName).join(", ") | ||
778 | 261 | fontSize: "x-small" | ||
779 | 262 | } | ||
780 | 263 | |||
781 | 264 | Label { | ||
782 | 265 | id: localityName | ||
783 | 266 | width: parent.width | ||
784 | 267 | wrapMode: Text.WordWrap | ||
785 | 268 | visible: text.length > 0 | ||
786 | 269 | text: securityStatus.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrLocalityName).join(", ") | ||
787 | 270 | fontSize: "x-small" | ||
788 | 271 | } | ||
789 | 272 | |||
790 | 273 | Label { | ||
791 | 274 | id: stateName | ||
792 | 275 | width: parent.width | ||
793 | 276 | wrapMode: Text.WordWrap | ||
794 | 277 | visible: text.length > 0 | ||
795 | 278 | text: securityStatus.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrStateOrProvinceName).join(", ") | ||
796 | 279 | fontSize: "x-small" | ||
797 | 280 | } | ||
798 | 281 | |||
799 | 282 | Label { | ||
800 | 283 | id: countryName | ||
801 | 284 | width: parent.width | ||
802 | 285 | wrapMode: Text.WordWrap | ||
803 | 286 | visible: text.length > 0 | ||
804 | 287 | text: securityStatus.certificate.getSubjectInfo(Oxide.SslCertificate.PrincipalAttrCountryName).join(", ") | ||
805 | 288 | fontSize: "x-small" | ||
806 | 289 | } | ||
807 | 290 | |||
808 | 291 | Item { | ||
809 | 292 | height: units.gu(1.5) | ||
810 | 293 | width: parent.width | ||
811 | 294 | } | ||
812 | 295 | |||
813 | 296 | } | ||
814 | 297 | |||
815 | 298 | MouseArea { | ||
816 | 299 | anchors.fill: parent | ||
817 | 300 | onClicked: PopupUtils.close(certificatePopover) | ||
818 | 301 | } | ||
819 | 302 | |||
820 | 303 | } | ||
821 | 304 | } | ||
822 | 305 | |||
823 | 120 | } | 306 | } |
824 | 121 | 307 | ||
825 | 122 | secondaryItem: Item { | 308 | secondaryItem: Item { |
826 | @@ -174,7 +360,7 @@ | |||
827 | 174 | MouseArea { | 360 | MouseArea { |
828 | 175 | anchors { | 361 | anchors { |
829 | 176 | fill: parent | 362 | fill: parent |
831 | 177 | leftMargin: actionButton.width | 363 | leftMargin: iconsRow.width |
832 | 178 | rightMargin: bookmarkButton.width | 364 | rightMargin: bookmarkButton.width |
833 | 179 | } | 365 | } |
834 | 180 | visible: !textField.activeFocus | 366 | visible: !textField.activeFocus |
835 | 181 | 367 | ||
836 | === modified file 'src/app/webbrowser/Browser.qml' | |||
837 | --- src/app/webbrowser/Browser.qml 2014-08-25 16:56:58 +0000 | |||
838 | +++ src/app/webbrowser/Browser.qml 2014-09-22 14:01:07 +0000 | |||
839 | @@ -121,6 +121,24 @@ | |||
840 | 121 | asynchronous: true | 121 | asynchronous: true |
841 | 122 | } | 122 | } |
842 | 123 | 123 | ||
843 | 124 | Loader { | ||
844 | 125 | anchors.fill: tabContainer | ||
845 | 126 | sourceComponent: InvalidCertificateErrorSheet { | ||
846 | 127 | visible: currentWebview && currentWebview.certificateError != null | ||
847 | 128 | certificateError: currentWebview ? currentWebview.certificateError : null | ||
848 | 129 | onAllowed: { | ||
849 | 130 | // Automatically allow future requests involving this | ||
850 | 131 | // certificate for the duration of the session. | ||
851 | 132 | currentWebview.allowedCertificates.push(currentWebview.certificateError.certificate.fingerprintSHA1) | ||
852 | 133 | currentWebview.certificateError = null | ||
853 | 134 | } | ||
854 | 135 | onDenied: { | ||
855 | 136 | currentWebview.certificateError = null | ||
856 | 137 | } | ||
857 | 138 | } | ||
858 | 139 | asynchronous: true | ||
859 | 140 | } | ||
860 | 141 | |||
861 | 124 | Chrome { | 142 | Chrome { |
862 | 125 | id: chrome | 143 | id: chrome |
863 | 126 | 144 | ||
864 | 127 | 145 | ||
865 | === modified file 'src/app/webbrowser/Chrome.qml' | |||
866 | --- src/app/webbrowser/Chrome.qml 2014-08-22 12:22:37 +0000 | |||
867 | +++ src/app/webbrowser/Chrome.qml 2014-09-22 14:01:07 +0000 | |||
868 | @@ -152,6 +152,7 @@ | |||
869 | 152 | onWebviewChanged: { | 152 | onWebviewChanged: { |
870 | 153 | if (webview) { | 153 | if (webview) { |
871 | 154 | addressbar.actualUrl = webview.url | 154 | addressbar.actualUrl = webview.url |
872 | 155 | addressbar.securityStatus = webview.securityStatus | ||
873 | 155 | } | 156 | } |
874 | 156 | } | 157 | } |
875 | 157 | 158 |
PASSED: Continuous integration, rev:721 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 1091/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/5008 jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 3652 jenkins. qa.ubuntu. com/job/ webbrowser- app-utopic- amd64-ci/ 290 jenkins. qa.ubuntu. com/job/ webbrowser- app-utopic- armhf-ci/ 290 jenkins. qa.ubuntu. com/job/ webbrowser- app-utopic- armhf-ci/ 290/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ webbrowser- app-utopic- i386-ci/ 290 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- mako/4758 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/6260 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/6260/ artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 13476 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-utopic/ 3039 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/3961 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/3961/ artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 1091/rebuild
http://