Merge lp:~uriboni/webbrowser-app/basic-auth into lp:webbrowser-app

Proposed by Ugo Riboni
Status: Rejected
Rejected by: Olivier Tilloy
Proposed branch: lp:~uriboni/webbrowser-app/basic-auth
Merge into: lp:webbrowser-app
Diff against target: 292 lines (+181/-5)
7 files modified
debian/control (+4/-4)
src/Ubuntu/Web/UbuntuWebView02.qml (+1/-1)
src/app/BasicAuthenticationDialog.qml (+76/-0)
src/app/WebViewImpl.qml (+5/-0)
tests/autopilot/webbrowser_app/emulators/browser.py (+18/-0)
tests/autopilot/webbrowser_app/tests/http_server.py (+20/-0)
tests/autopilot/webbrowser_app/tests/test_basic_authentication.py (+57/-0)
To merge this branch: bzr merge lp:~uriboni/webbrowser-app/basic-auth
Reviewer Review Type Date Requested Status
Olivier Tilloy Disapprove
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+261491@code.launchpad.net

Description of the change

Handle basic authentication requests by showing an authentication dialog

Depends on https://code.launchpad.net/~uriboni/oxide/basic-authentication/+merge/260922

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1000. By Ugo Riboni

Add missing AP test file

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

263 + def tearDown(self):
264 + super(TestBasicAuthentication, self).tearDown()

This is useless.

Revision history for this message
Olivier Tilloy (osomon) wrote :

flake8 test fails.

review: Needs Fixing
1001. By Ugo Riboni

Fix flake8 and clarify the purpose of some test code

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :
review: Disapprove

Unmerged revisions

994. By Launchpad Translations on behalf of phablet-team

Launchpad automatic translations update.

993. By Launchpad Translations on behalf of phablet-team

Launchpad automatic translations update.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-05-27 05:31:12 +0000
3+++ debian/control 2015-06-17 11:31:36 +0000
4@@ -6,7 +6,7 @@
5 debhelper (>= 9),
6 dh-translations,
7 hardening-wrapper,
8- liboxideqt-qmlplugin (>= 1.6),
9+ liboxideqt-qmlplugin (>= 1.9),
10 libqt5sql5-sqlite,
11 python3-all,
12 python3-flake8,
13@@ -34,7 +34,7 @@
14 Depends: ${misc:Depends},
15 ${shlibs:Depends},
16 fonts-liberation,
17- liboxideqt-qmlplugin (>= 1.7),
18+ liboxideqt-qmlplugin (>= 1.9),
19 libqt5sql5-sqlite,
20 qml-module-qt-labs-folderlistmodel,
21 qml-module-qt-labs-settings,
22@@ -59,7 +59,7 @@
23 Depends: ${misc:Depends},
24 ${shlibs:Depends},
25 fonts-liberation,
26- liboxideqt-qmlplugin (>= 1.5),
27+ liboxideqt-qmlplugin (>= 1.9),
28 libqt5sql5-sqlite,
29 qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin,
30 qml-module-qtquick-window2 | qtdeclarative5-window-plugin,
31@@ -96,7 +96,7 @@
32 Pre-Depends: ${misc:Pre-Depends}
33 Depends: ${misc:Depends},
34 ${shlibs:Depends},
35- liboxideqt-qmlplugin (>= 1.6),
36+ liboxideqt-qmlplugin (>= 1.9),
37 qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin,
38 qml-module-qtquick-window2 | qtdeclarative5-window-plugin,
39 qtdeclarative5-ubuntu-ui-toolkit-plugin,
40
41=== modified file 'src/Ubuntu/Web/UbuntuWebView02.qml'
42--- src/Ubuntu/Web/UbuntuWebView02.qml 2015-05-13 15:07:34 +0000
43+++ src/Ubuntu/Web/UbuntuWebView02.qml 2015-06-17 11:31:36 +0000
44@@ -18,7 +18,7 @@
45
46 import QtQuick 2.0
47 import QtQuick.Window 2.0
48-import com.canonical.Oxide 1.5 as Oxide
49+import com.canonical.Oxide 1.9 as Oxide
50 import Ubuntu.Components 1.1
51 import Ubuntu.Components.Popups 1.0
52 import "." // QTBUG-34418
53
54=== added file 'src/app/BasicAuthenticationDialog.qml'
55--- src/app/BasicAuthenticationDialog.qml 1970-01-01 00:00:00 +0000
56+++ src/app/BasicAuthenticationDialog.qml 2015-06-17 11:31:36 +0000
57@@ -0,0 +1,76 @@
58+/*
59+ * Copyright 2015 Canonical Ltd.
60+ *
61+ * This file is part of webbrowser-app.
62+ *
63+ * webbrowser-app is free software; you can redistribute it and/or modify
64+ * it under the terms of the GNU General Public License as published by
65+ * the Free Software Foundation; version 3.
66+ *
67+ * webbrowser-app is distributed in the hope that it will be useful,
68+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
69+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70+ * GNU General Public License for more details.
71+ *
72+ * You should have received a copy of the GNU General Public License
73+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
74+ */
75+
76+import QtQuick 2.0
77+import Ubuntu.Components 1.1
78+import Ubuntu.Components.Popups 1.0 as Popups
79+
80+Popups.Dialog {
81+ id: dialog
82+ title: i18n.tr("Authentication required.")
83+ // TRANSLATORS: %1 refers to the URL of the current website and %2 is a string that the website sends with more information about the authentication challenge (technically called "realm")
84+ text: request ? i18n.tr('The website at %1 requires authentication. The website says "%2"').arg(request.host).arg(request.realm) : ""
85+
86+ property QtObject request: null
87+
88+ Connections {
89+ target: request
90+ onCancelled: PopupUtils.close(dialog)
91+ }
92+
93+ TextField {
94+ id: usernameInput
95+ objectName: "username"
96+ placeholderText: i18n.tr("Username")
97+ onAccepted: {
98+ request.allow(usernameInput.text, passwordInput.text)
99+ PopupUtils.close(dialog)
100+ }
101+ }
102+
103+ TextField {
104+ id: passwordInput
105+ objectName: "password"
106+ placeholderText: i18n.tr("Password")
107+ echoMode: TextInput.Password
108+ onAccepted: {
109+ request.allow(usernameInput.text, passwordInput.text)
110+ PopupUtils.close(dialog)
111+ }
112+ }
113+
114+ Button {
115+ objectName: "allow"
116+ text: i18n.tr("OK")
117+ color: "green"
118+ onClicked: {
119+ request.allow(usernameInput.text, passwordInput.text)
120+ PopupUtils.close(dialog)
121+ }
122+ }
123+
124+ Button {
125+ objectName: "deny"
126+ text: i18n.tr("Cancel")
127+ color: UbuntuColors.coolGrey
128+ onClicked: {
129+ request.deny()
130+ PopupUtils.close(dialog)
131+ }
132+ }
133+}
134
135=== modified file 'src/app/WebViewImpl.qml'
136--- src/app/WebViewImpl.qml 2015-05-29 14:37:05 +0000
137+++ src/app/WebViewImpl.qml 2015-06-17 11:31:36 +0000
138@@ -66,6 +66,11 @@
139 }
140 }
141
142+ onBasicAuthenticationRequested: {
143+ PopupUtils.open(Qt.resolvedUrl("BasicAuthenticationDialog.qml"),
144+ webview.currentWebview, {"request": request})
145+ }
146+
147 Loader {
148 id: filePickerLoader
149 source: formFactor == "desktop" ? "FilePickerDialog.qml" : "ContentPickerDialog.qml"
150
151=== modified file 'tests/autopilot/webbrowser_app/emulators/browser.py'
152--- tests/autopilot/webbrowser_app/emulators/browser.py 2015-05-28 13:56:52 +0000
153+++ tests/autopilot/webbrowser_app/emulators/browser.py 2015-06-17 11:31:36 +0000
154@@ -114,6 +114,9 @@
155 def get_geolocation_dialog(self):
156 return self.wait_select_single(GeolocationPermissionRequest)
157
158+ def get_basic_auth_dialog(self):
159+ return self.wait_select_single(BasicAuthenticationDialog)
160+
161 def get_selection(self):
162 return self.wait_select_single(Selection)
163
164@@ -255,6 +258,21 @@
165 return self.select_single("Button", objectName="allow")
166
167
168+class BasicAuthenticationDialog(uitk.UbuntuUIToolkitCustomProxyObjectBase):
169+
170+ def get_deny_button(self):
171+ return self.select_single("Button", objectName="deny")
172+
173+ def get_allow_button(self):
174+ return self.select_single("Button", objectName="allow")
175+
176+ def get_username_field(self):
177+ return self.select_single("TextField", objectName="username")
178+
179+ def get_password_field(self):
180+ return self.select_single("TextField", objectName="password")
181+
182+
183 class Selection(uitk.UbuntuUIToolkitCustomProxyObjectBase):
184
185 def get_rectangle(self):
186
187=== modified file 'tests/autopilot/webbrowser_app/tests/http_server.py'
188--- tests/autopilot/webbrowser_app/tests/http_server.py 2015-04-23 15:34:16 +0000
189+++ tests/autopilot/webbrowser_app/tests/http_server.py 2015-06-17 11:31:36 +0000
190@@ -6,6 +6,7 @@
191 # under the terms of the GNU General Public License version 3, as published
192 # by the Free Software Foundation.
193
194+from base64 import b64decode
195 import http.server as http
196 import json
197 import logging
198@@ -31,6 +32,12 @@
199 self.end_headers()
200 self.wfile.write(html.encode())
201
202+ def send_auth_request(self):
203+ self.send_response(401)
204+ self.send_header("WWW-Authenticate", "Basic realm=\"Enter Password\"")
205+ self.end_headers()
206+ self.send_html("Not Authorized")
207+
208 def do_GET(self):
209 if self.path == "/ping":
210 self.send_response(200)
211@@ -140,6 +147,19 @@
212 if query in self.suggestions_data:
213 suggestions = self.suggestions_data[query]
214 self.wfile.write(json.dumps(suggestions).encode())
215+ elif self.path.startswith("/basic_auth"):
216+ login = "user"
217+ password = "pass"
218+ if "Authorization" in self.headers:
219+ header = self.headers.get("Authorization")
220+ credentials = str(b64decode(header[len("Basic "):])).split(":")
221+ if credentials[0] == login and credentials[1] == password:
222+ self.send_response(200)
223+ self.send_html("Authentication Successful !")
224+ else:
225+ self.send_auth_request()
226+ else:
227+ self.send_auth_request()
228 else:
229 self.send_error(404)
230
231
232=== added file 'tests/autopilot/webbrowser_app/tests/test_basic_authentication.py'
233--- tests/autopilot/webbrowser_app/tests/test_basic_authentication.py 1970-01-01 00:00:00 +0000
234+++ tests/autopilot/webbrowser_app/tests/test_basic_authentication.py 2015-06-17 11:31:36 +0000
235@@ -0,0 +1,57 @@
236+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
237+#
238+# Copyright 2015 Canonical
239+#
240+# This program is free software: you can redistribute it and/or modify it
241+# under the terms of the GNU General Public License version 3, as published
242+# by the Free Software Foundation.
243+#
244+# This program is distributed in the hope that it will be useful,
245+# but WITHOUT ANY WARRANTY; without even the implied warranty of
246+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
247+# GNU General Public License for more details.
248+#
249+# You should have received a copy of the GNU General Public License
250+# along with this program. If not, see <http://www.gnu.org/licenses/>.
251+
252+from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
253+
254+
255+class TestBasicAuthentication(StartOpenRemotePageTestCaseBase):
256+
257+ def setUp(self):
258+ super(TestBasicAuthentication, self).setUp()
259+ self.username = "user"
260+ self.password = "pass"
261+ self.url = self.base_url + "/basic_auth"
262+
263+ def tearDown(self):
264+ super(TestBasicAuthentication, self).tearDown()
265+
266+ def test_cancel(self):
267+ self.main_window.go_to_url(self.url)
268+ dialog = self.main_window.get_basic_auth_dialog()
269+ self.pointing_device.click_object(dialog.get_deny_button())
270+ dialog.wait_until_destroyed()
271+
272+ def test_right_credentials(self):
273+ self.main_window.go_to_url(self.url)
274+ dialog = self.main_window.get_basic_auth_dialog()
275+ username = dialog.get_username_field()
276+ username.write(self.username)
277+ password = dialog.get_password_field()
278+ password.write(self.password)
279+ self.pointing_device.click_object(dialog.get_allow_button())
280+ dialog.wait_until_destroyed()
281+
282+ def test_wrong_credentials(self):
283+ self.main_window.go_to_url(self.url)
284+ dialog = self.main_window.get_basic_auth_dialog()
285+ username = dialog.get_username_field()
286+ username.write("x")
287+ password = dialog.get_password_field()
288+ password.write("x")
289+ self.pointing_device.click_object(dialog.get_allow_button())
290+ dialog.wait_until_destroyed()
291+ # verify that a new dialog has been displayed
292+ self.main_window.get_basic_auth_dialog()

Subscribers

People subscribed via source and target branches

to status/vote changes: