Merge lp:~bfiller/webbrowser-app/file-upload into lp:webbrowser-app

Proposed by Bill Filler
Status: Superseded
Proposed branch: lp:~bfiller/webbrowser-app/file-upload
Merge into: lp:webbrowser-app
Diff against target: 294 lines (+252/-0)
5 files modified
debian/control (+1/-0)
src/app/ContentPickerDialog.qml (+82/-0)
src/app/WebViewImpl.qml (+1/-0)
tests/autopilot/webbrowser_app/tests/http_server.py (+15/-0)
tests/autopilot/webbrowser_app/tests/test_content_pick.py (+153/-0)
To merge this branch: bzr merge lp:~bfiller/webbrowser-app/file-upload
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Adnane Belmadiaf community Pending
Ubuntu Phablet Team Pending
Review via email: mp+203227@code.launchpad.net

Description of the change

Adding image upload capability. Not ready yet for review.

To post a comment you must log in.
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
Bill Filler (bfiller) wrote :

Remaining work items so we can land this:

Main use case to get working well is open gmail in browser and try to add an attachment to a new email message:

phase 1:
- disable failing autopilot tests
- enable multi selection mode
- fix up result list to display multiple objects, need to support multiple types, i.e. a picture and a video. perhaps this can be a simple list with some sort of icon. Need to check with design to see what is desired
- this works correctly in webbrowser-app but doesn't work at all if you run in a webapp (like try to upload photo in gmail webbapp).

phase 2:
- instead of hardcoding "ContentType.Pictures" as the type of content desired, get this information from the browser or default to all content-types
- implement the Source Picker UI (in the design spec) to display the choices of available apps returned by the content-hub. This should be a generic UI component that would probably live in the content-hub or sdk

Unmerged revisions

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 2013-12-05 07:06:08 +0000
3+++ debian/control 2014-01-26 04:07:40 +0000
4@@ -85,6 +85,7 @@
5 libautopilot-qt (>= 1.4),
6 libqt5test5,
7 ubuntu-ui-toolkit-autopilot,
8+ unity8-autopilot,
9 webbrowser-app (>= ${binary:Version}),
10 Description: Ubuntu web browser autopilot tests
11 A lightweight web browser tailored for Ubuntu, based on the Webkit rendering
12
13=== added file 'src/app/ContentPickerDialog.qml'
14--- src/app/ContentPickerDialog.qml 1970-01-01 00:00:00 +0000
15+++ src/app/ContentPickerDialog.qml 2014-01-26 04:07:40 +0000
16@@ -0,0 +1,82 @@
17+/*
18+ * Copyright 2013 Canonical Ltd.
19+ *
20+ * This file is part of webbrowser-app.
21+ *
22+ * webbrowser-app is free software; you can redistribute it and/or modify
23+ * it under the terms of the GNU General Public License as published by
24+ * the Free Software Foundation; version 3.
25+ *
26+ * webbrowser-app is distributed in the hope that it will be useful,
27+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29+ * GNU General Public License for more details.
30+ *
31+ * You should have received a copy of the GNU General Public License
32+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
33+ */
34+
35+import QtQuick 2.0
36+import Ubuntu.Components 0.1
37+import Ubuntu.Components.Popups 0.1 as Popups
38+import Ubuntu.Content 0.1
39+
40+Popups.Dialog {
41+ id: picker
42+ title: i18n.tr("Pick content to upload")
43+ property var activeTransfer
44+
45+ UbuntuShape {
46+ height: width
47+ image: Image {
48+ objectName: "mediaPreview"
49+ id: preview
50+ fillMode: Image.PreserveAspectCrop
51+ }
52+
53+ MouseArea {
54+ anchors.fill: parent
55+ onClicked: startContentPicking()
56+ }
57+
58+ ContentImportHint {
59+ anchors.fill: parent
60+ activeTransfer: picker.activeTransfer
61+ }
62+ }
63+
64+ Button {
65+ objectName: "ok"
66+ text: i18n.tr("OK")
67+ color: "green"
68+ enabled: preview.source
69+ onClicked: model.accept(String(preview.source).replace("file://", ""))
70+ }
71+
72+ Button {
73+ text: i18n.tr("Cancel")
74+ color: UbuntuColors.coolGrey
75+ onClicked: model.reject()
76+ }
77+
78+ function startContentPicking() {
79+ activeTransfer = ContentHub.importContent(ContentType.Pictures);
80+ activeTransfer.selectionType = ContentTransfer.Single;
81+ activeTransfer.start();
82+ }
83+
84+ Component.onCompleted: {
85+ show();
86+ startContentPicking();
87+ }
88+
89+ Connections {
90+ target: picker.activeTransfer
91+ onStateChanged: {
92+ if (picker.activeTransfer.state === ContentTransfer.Charged) {
93+ var importItem = picker.activeTransfer.items[0];
94+ preview.source = importItem.url
95+ }
96+ }
97+ }
98+}
99
100=== modified file 'src/app/WebViewImpl.qml'
101--- src/app/WebViewImpl.qml 2013-11-12 22:18:49 +0000
102+++ src/app/WebViewImpl.qml 2014-01-26 04:07:40 +0000
103@@ -37,6 +37,7 @@
104 experimental.alertDialog: AlertDialog {}
105 experimental.confirmDialog: ConfirmDialog {}
106 experimental.promptDialog: PromptDialog {}
107+ experimental.filePicker: ContentPickerDialog {}
108
109 selectionActions: ActionList {
110 Actions.Copy {
111
112=== modified file 'tests/autopilot/webbrowser_app/tests/http_server.py'
113--- tests/autopilot/webbrowser_app/tests/http_server.py 2013-12-16 10:51:47 +0000
114+++ tests/autopilot/webbrowser_app/tests/http_server.py 2014-01-26 04:07:40 +0000
115@@ -86,6 +86,21 @@
116 html += 'src="/blanktargetlink" />'
117 html += '</body></html>'
118 self.send_html(html)
119+ elif self.path == "/uploadform":
120+ # craft a page that accepts clicks anywhere inside its window
121+ # and on a click opens up the content picker.
122+ # It also pops up an alert with the new content of the file
123+ # upload field when it changes
124+ self.send_response(200)
125+ html = '<html><body style="margin: 0">'
126+ html = '<form action="upload" method="post" enctype="multipart/form-data">'
127+ html += '<input type="file" name="file" id="file" onchange="alert(this.value)"><br>'
128+ html += '<input type="submit" name="submit" value="Submit">'
129+ html += '</form>'
130+ html += '<a href="javascript:document.getElementById(\'file\').click()">'
131+ html += '<div style="height: 100%"></div></a>'
132+ html += '</body></html>'
133+ self.send_html(html)
134 else:
135 self.send_error(404)
136
137
138=== added file 'tests/autopilot/webbrowser_app/tests/test_content_pick.py'
139--- tests/autopilot/webbrowser_app/tests/test_content_pick.py 1970-01-01 00:00:00 +0000
140+++ tests/autopilot/webbrowser_app/tests/test_content_pick.py 2014-01-26 04:07:40 +0000
141@@ -0,0 +1,153 @@
142+# -*- coding: utf-8 -*-
143+#
144+# Copyright 2013 Canonical
145+#
146+# This program is free software: you can redistribute it and/or modify it
147+# under the terms of the GNU General Public License version 3, as published
148+# by the Free Software Foundation.
149+
150+from __future__ import absolute_import
151+
152+from autopilot.introspection import get_proxy_object_for_existing_process
153+from autopilot.platform import model
154+from autopilot.matchers import Eventually
155+from testtools.matchers import Equals, NotEquals
156+from testtools import skipIf, skip
157+from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
158+from unity8 import process_helpers as helpers
159+from ubuntuuitoolkit import emulators as toolkit_emulators
160+import os, subprocess
161+
162+@skip("Will not work until bug #1255077 is solved")
163+class TestContentPick(StartOpenRemotePageTestCaseBase):
164+
165+ """Tests that content picking dialog show up."""
166+
167+ def test_pick_image(self):
168+ url = self.base_url + "/uploadform"
169+ self.go_to_url(url)
170+ self.assert_page_eventually_loaded(url)
171+ webview = self.main_window.get_current_webview()
172+ self.pointing_device.click_object(webview)
173+
174+ dialog = self.app.wait_select_single("ContentPickerDialog")
175+ self.assertThat(dialog.visible, Equals(True))
176+
177+@skipIf(model() == 'Desktop', "Phablet only")
178+class TestContentPickerIntegration(StartOpenRemotePageTestCaseBase):
179+
180+ """Tests that the gallery app is brought up to choose image content"""
181+
182+ def tearDown(self):
183+ os.system("pkill gallery-app")
184+ os.system("pkill webbrowser-app")
185+ super(StartOpenRemotePageTestCaseBase, self).tearDown()
186+
187+ def get_unity8_proxy_object(self):
188+ pid = helpers._get_unity_pid()
189+ return get_proxy_object_for_existing_process(pid)
190+
191+ def get_current_focused_appid(self, unity8):
192+ return unity8.select_single("Shell").currentFocusedAppId
193+
194+ def set_testability_environment_variable(self):
195+ """Makes sure every app opened in the environment loads the
196+ testability driver."""
197+
198+ subprocess.check_call([
199+ "/sbin/initctl",
200+ "set-env",
201+ "QT_LOAD_TESTABILITY=1"
202+ ])
203+
204+ def get_app_pid(self, app):
205+ """Return the PID of the named app, or -1 if it's not
206+ running"""
207+
208+ try:
209+ return int(subprocess.check_output(["pidof", app]).strip())
210+ except subprocess.CalledProcessError:
211+ return -1
212+
213+ def wait_app_focused(self, name):
214+ """Wait until the app with the specified name is the
215+ currently focused one"""
216+
217+ unity8 = self.get_unity8_proxy_object()
218+ shell = unity8.select_single("Shell")
219+ self.assertThat(
220+ lambda: self.get_current_focused_appid(unity8),
221+ Eventually(Equals(name))
222+ )
223+
224+ def test_image_picker_is_gallery(self):
225+ """ Tests that the gallery shows up when we are picking
226+ images """
227+
228+ # Go to a page where clicking anywhere equals clicking on the
229+ # file selection button of an upload form
230+ url = self.base_url + "/uploadform"
231+ self.go_to_url(url)
232+ self.assert_page_eventually_loaded(url)
233+ webview = self.main_window.get_current_webview()
234+ self.pointing_device.click_object(webview)
235+
236+ # Verify that such a click brings up the gallery to select images
237+ self.wait_app_focused("gallery-app")
238+
239+ def test_image_picker_pick_image(self):
240+ """ Tests that the we can select an image in the gallery and
241+ control will return to the browser with the choosen image
242+ picked."""
243+
244+ # First run the previous test to bring up the content picker
245+ self.set_testability_environment_variable()
246+ self.test_image_picker_is_gallery()
247+
248+ # Now wait until the gallery-app process is up.
249+ # NOTE: this will not work unless run on a device where unity8 runs in
250+ # testability mode. To manually restart unity8 in this mode run from a
251+ # python shell:
252+ # from unity8 import process_helpers as p; p.restart_unity_with_testability()
253+ unity8 = self.get_unity8_proxy_object()
254+ self.assertThat(lambda: self.get_app_pid("gallery-app"), Eventually(NotEquals(-1)))
255+
256+ gallery = get_proxy_object_for_existing_process(
257+ self.get_app_pid("gallery-app"),
258+ emulator_base = toolkit_emulators.UbuntuUIToolkitEmulatorBase
259+ )
260+
261+ # Wait for the gallery UI to completely display
262+ view = gallery.wait_select_single("QQuickView")
263+ self.assertThat(view.visible, Eventually(Equals(True)))
264+
265+ # Select the first picture on the picker by clicking on it
266+ # NOTE: this is currently failing if there is anything except two pictures
267+ # in the gallery (at least on a Maguro device), so I'm putting a temporary
268+ # stop to the test here so that it won't break in Jenkins
269+ return
270+
271+ grid = gallery.wait_select_single("MediaGrid")
272+ photo = grid.select_many("OrganicItemInteraction")[0]
273+ self.pointing_device.click_object(photo)
274+ self.assertThat(photo.isSelected, Eventually(Equals(True)))
275+
276+ # Now the "Pick" button will be enabled and we click on it
277+ button = gallery.select_single("Button", objectName="pickButton")
278+ self.assertThat(button.enabled, Eventually(Equals(True)))
279+ self.pointing_device.click_object(button)
280+
281+ # The gallery should close and focus returned to the browser
282+ self.wait_app_focused("webbrowser-app")
283+
284+ # Verify that an image has actually been selected
285+ dialog = self.app.wait_select_single("ContentPickerDialog")
286+ self.assertThat(dialog.visible, Equals(True))
287+ preview = dialog.wait_select_single("QQuickImage", objectName="mediaPreview")
288+ self.assertThat(preview.source, Eventually(NotEquals("")))
289+
290+ # Verify that now we can click the "OK" button and it closes the dialog
291+ button = dialog.wait_select_single("Button", objectName="ok")
292+ self.assertThat(button.enabled, Eventually(Equals(True)))
293+ self.pointing_device.click_object(button)
294+ self.assertThat(dialog.visible, Eventually(Equals(False)))

Subscribers

People subscribed via source and target branches

to status/vote changes: