Merge lp:~abreu-alexandre/webbrowser-app/container-handle-context-menu into lp:webbrowser-app
- container-handle-context-menu
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Alberto Mardegan |
Approved revision: | 1298 |
Merged at revision: | 1318 |
Proposed branch: | lp:~abreu-alexandre/webbrowser-app/container-handle-context-menu |
Merge into: | lp:webbrowser-app |
Diff against target: |
904 lines (+764/-3) 9 files modified
src/app/actions/OpenLinkInWebBrowser.qml (+23/-0) src/app/webcontainer/ContextMenuMobile.qml (+157/-0) src/app/webcontainer/ContextMenuWide.qml (+142/-0) src/app/webcontainer/WebApp.qml (+1/-0) src/app/webcontainer/WebViewImplOxide.qml (+56/-2) src/app/webcontainer/WebappContainerWebview.qml (+5/-1) src/app/webcontainer/assets/stock_link.svg (+164/-0) tests/autopilot/webapp_container/tests/fake_servers.py (+27/-0) tests/autopilot/webapp_container/tests/test_context_menu.py (+189/-0) |
To merge this branch: | bzr merge lp:~abreu-alexandre/webbrowser-app/container-handle-context-menu |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alberto Mardegan (community) | Approve | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+274636@code.launchpad.net |
Commit message
Limited handling of custom context menu for the container
Description of the change
Limited handling of custom context menu for the container.
I duplicated the mobile context menu w/o the asset usage so that the webbrowser-app is not touched and the changes are limited. This is of course not a definite dialog,
PS Jenkins bot (ps-jenkins) wrote : | # |
- 1236. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
Olivier Tilloy (osomon) wrote : | # |
This fixes the issue for the webapp container indeed, but it doesn’t for the general Ubuntu WebView case: apps embedding a WebView and using the default context menu will still get the crash, as you remarked in https:/
I have submitted https:/
- 1237. By Arthur Mello
-
Add bookmarks view to top level menu
Approved by: Ugo Riboni, Olivier Tilloy - 1238. By Olivier Tilloy
-
Ensure that the default context menu cannot be dismissed several times, causing a crash in oxide.
The issue in oxide remains, it should have a safeguard against this kind of behaviour. Fixes: #1501330
Approved by: Alexandre Abreu - 1239. By Olivier Tilloy
-
Update a localized error string, per design. Fixes: #1493466
Approved by: Bartosz Kosiorek - 1240. By Olivier Tilloy
-
Fixes for minor UX issues with the preview grid:
- Make the highlight follow the item selected for deletion in the preview grid.
- Do not show a highlight in the narrow version of the new tab view, as it doesn’t support keyboard navigation.
- Grab dismiss area events so that they are not propagated to the view below when dismissing a context menu. Fixes: #1506579 - 1241. By Olivier Tilloy
-
Fix a couple of autopilot failures on desktop in narrow mode. Fixes: #1506879
- 1242. By CI Train Bot Account
-
Releasing 0.23+15.
10.20151016- 0ubuntu1 - 1243. By CI Train Bot Account
-
Resync trunk.
- 1244. By Olivier Tilloy
-
Update translation template.
- 1245. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1246. By Ugo Riboni
-
Implement support for allowing or denying access to media input devices and for setting default media input devices. Fixes: #1410996
Approved by: PS Jenkins bot, Olivier Tilloy - 1247. By Ugo Riboni
-
Refactor the BookmarksModel to be a singleton.
Approved by: PS Jenkins bot - 1248. By Ugo Riboni
-
Fix inability to drag the map to pan in Google maps, on desktop. Fixes: #1503506
Approved by: PS Jenkins bot, Olivier Tilloy - 1249. By Olivier Tilloy
-
Add an exception to the generated apparmor profile to allow reading HERE’s TOS in the browser. Fixes: #1507667
Approved by: PS Jenkins bot, Olivier Tilloy - 1250. By Olivier Tilloy
-
Modify the generated apparmor profile to allow rw access to /dev/shm/
.org.chromium. Chromium. * too. Fixes: #1508054
Approved by: PS Jenkins bot - 1251. By CI Train Bot Account
-
Releasing 0.23+15.
10.20151022. 1-0ubuntu1 - 1252. By CI Train Bot Account
-
Resync trunk.
- 1253. By Olivier Tilloy
-
Update translation template.
- 1254. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1255. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1256. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1257. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1258. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1259. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1260. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1261. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1262. By Ugo Riboni
-
Focus the page when opening links with target="_blank". Fixes: #1505724
Approved by: Olivier Tilloy, PS Jenkins bot - 1263. By Ugo Riboni
-
Use AbstractButton to handle some tab interactions so that haptics are used on touch. Fixes: #1505725
Approved by: Olivier Tilloy, PS Jenkins bot - 1264. By Ugo Riboni
-
Fix a bug preventing in some cases the address bar from getting focus when entering find in page mode. Also correctly hide the left hand side icons when in find in page mode. Fixes: #1508130
Approved by: Olivier Tilloy, PS Jenkins bot - 1265. By Ugo Riboni
-
Prevent the address bar from being cleared when the actual url changes and the user has already started typing. Fixes: #1487713
Approved by: Olivier Tilloy - 1266. By Ugo Riboni
-
Update the user script to remove the Facebook app banner. Fixes: #1352783
Approved by: Olivier Tilloy, PS Jenkins bot - 1267. By CI Train Bot Account
-
Releasing 0.23+16.
04.20151103- 0ubuntu1 - 1268. By CI Train Bot Account
-
Resync trunk.
- 1269. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1270. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1271. By Ugo Riboni
-
Add keyboard shortcuts to undo closing tabs (Ctrl+Shift+T and Ctrl+Shift+W). Fixes: #1499767
Approved by: PS Jenkins bot, Olivier Tilloy - 1272. By Ugo Riboni
-
Hide webviews created via onNewViewRequested until the tab they belong to becomes current. Fixes: #1464436
Approved by: PS Jenkins bot - 1273. By Olivier Tilloy
-
Ship empty apparmor hardware profile directories to avoid adding a runtime dependency on apparmor-
easyprof- ubuntu. Fixes: #1511439
Approved by: PS Jenkins bot, Jamie Strandboge - 1274. By Ugo Riboni
-
Use lowercase letters for keyboard shortcut invokation in autopilot tests.
Autopilot tries to be too clever and automatically issues a Shift when an uppercase letter is used in a keypress combo. Fix our tests to adjust to this behavior.
Approved by: PS Jenkins bot, Olivier Tilloy - 1275. By Olivier Tilloy
-
Add missing unit test cleanup.
Approved by: PS Jenkins bot - 1276. By Ugo Riboni
-
Create the webview in a safer way, by keeping the incubator around and monitoring the progress, and by using sync creation if there is a pending request. Fixes: #1514701
Approved by: PS Jenkins bot - 1277. By CI Train Bot Account
-
Releasing 0.23+16.
04.20151111. 2-0ubuntu1 - 1278. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1279. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1280. By Olivier Tilloy
-
Multiple changes to improve the tab switching animation.
The biggest remaining issue is bug #1502675, which is worked around here until it is properly addressed in oxide.
Approved by: PS Jenkins bot - 1281. By CI Train Bot Account
-
Releasing 0.23+16.
04.20151124- 0ubuntu1 - 1282. By CI Train Bot Account
-
Resync trunk.
- 1283. By Olivier Tilloy
-
Add missing import statements, and add missing unit tests for BookmarksView.qml and BookmarksViewWi
de.qml. Fixes: #1515631
Approved by: Ugo Riboni - 1284. By Olivier Tilloy
-
Code cleanup: remove unused include statements and forward declarations, and convert unnecessary include statements to forward declarations.
- 1285. By Olivier Tilloy
-
Prevent click events from propagating through the expanded history view to the view below. Fixes: #1518904
Approved by: Ugo Riboni, PS Jenkins bot - 1286. By Olivier Tilloy
-
Use the capture device display names instead of their unique ID. Fixes: #1518931
Approved by: Ugo Riboni, PS Jenkins bot - 1287. By Olivier Tilloy
-
Make the drawer menu flickable so that all its actions can be accessed even on a small mobile screen in landscape orientation. Fixes: #1513348
- 1288. By CI Train Bot Account
-
Releasing 0.23+16.
04.20151126- 0ubuntu1 - 1289. By CI Train Bot Account
-
Resync trunk.
- 1290. By Olivier Tilloy
-
Update translation template.
- 1291. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1292. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1293. By CI Train Bot Account
-
Rebuild against Qt 5.5.1.
- 1294. By CI Train Bot Account
-
Releasing 0.23+16.
04.20151130- 0ubuntu1 - 1295. By CI Train Bot Account
-
Resync trunk.
- 1296. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 1297. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1233
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Alberto Mardegan (mardy) wrote : | # |
Looks good, just please revert the change to src/app/
- 1298. By Alexandre Abreu
-
Handle context menu
- 1299. By Alexandre Abreu
-
fix small flake8 nit
Preview Diff
1 | === added file 'src/app/actions/OpenLinkInWebBrowser.qml' |
2 | --- src/app/actions/OpenLinkInWebBrowser.qml 1970-01-01 00:00:00 +0000 |
3 | +++ src/app/actions/OpenLinkInWebBrowser.qml 2015-12-18 18:01:09 +0000 |
4 | @@ -0,0 +1,23 @@ |
5 | +/* |
6 | + * Copyright 2015 Canonical Ltd. |
7 | + * |
8 | + * This file is part of webbrowser-app. |
9 | + * |
10 | + * webbrowser-app is free software; you can redistribute it and/or modify |
11 | + * it under the terms of the GNU General Public License as published by |
12 | + * the Free Software Foundation; version 3. |
13 | + * |
14 | + * webbrowser-app is distributed in the hope that it will be useful, |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | + * GNU General Public License for more details. |
18 | + * |
19 | + * You should have received a copy of the GNU General Public License |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | + */ |
22 | + |
23 | +import Ubuntu.Components 1.3 |
24 | + |
25 | +Action { |
26 | + text: i18n.tr("Open link in WebBrowser") |
27 | +} |
28 | |
29 | === added file 'src/app/webcontainer/ContextMenuMobile.qml' |
30 | --- src/app/webcontainer/ContextMenuMobile.qml 1970-01-01 00:00:00 +0000 |
31 | +++ src/app/webcontainer/ContextMenuMobile.qml 2015-12-18 18:01:09 +0000 |
32 | @@ -0,0 +1,157 @@ |
33 | +/* |
34 | + * Copyright 2015 Canonical Ltd. |
35 | + * |
36 | + * This file is part of webbrowser-app. |
37 | + * |
38 | + * webbrowser-app is free software; you can redistribute it and/or modify |
39 | + * it under the terms of the GNU General Public License as published by |
40 | + * the Free Software Foundation; version 3. |
41 | + * |
42 | + * webbrowser-app is distributed in the hope that it will be useful, |
43 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
44 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
45 | + * GNU General Public License for more details. |
46 | + * |
47 | + * You should have received a copy of the GNU General Public License |
48 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
49 | + */ |
50 | + |
51 | +import QtQuick 2.4 |
52 | +import Ubuntu.Components 1.3 |
53 | +import Ubuntu.Components.ListItems 1.3 as ListItems |
54 | +import Ubuntu.Components.Popups 1.3 as Popups |
55 | +import com.canonical.Oxide 1.8 as Oxide |
56 | + |
57 | +Popups.Dialog { |
58 | + property QtObject contextModel: model |
59 | + property ActionList actions: null |
60 | + |
61 | + objectName: "contextMenuMobile" |
62 | + |
63 | + QtObject { |
64 | + id: internal |
65 | + readonly property bool isImage: (contextModel.mediaType === Oxide.WebView.MediaTypeImage) || |
66 | + (contextModel.mediaType === Oxide.WebView.MediaTypeCanvas) |
67 | + } |
68 | + |
69 | + Row { |
70 | + id: header |
71 | + spacing: units.gu(2) |
72 | + anchors { |
73 | + left: parent.left |
74 | + leftMargin: units.gu(2) |
75 | + right: parent.right |
76 | + rightMargin: units.gu(2) |
77 | + } |
78 | + height: units.gu(2 * title.lineCount + 3) |
79 | + visible: title.text |
80 | + |
81 | + Icon { |
82 | + width: units.gu(2) |
83 | + height: units.gu(2) |
84 | + anchors { |
85 | + top: parent.top |
86 | + topMargin: units.gu(2) |
87 | + } |
88 | + name: internal.isImage ? "stock_image" : "" |
89 | + // work around the lack of a standard stock_link symbolic icon in the theme |
90 | + Component.onCompleted: { |
91 | + if (!name) { |
92 | + source = "assets/stock_link.svg" |
93 | + } |
94 | + } |
95 | + } |
96 | + |
97 | + Label { |
98 | + id: title |
99 | + objectName: "titleLabel" |
100 | + text: contextModel.srcUrl.toString() ? contextModel.srcUrl : contextModel.linkUrl |
101 | + width: parent.width - units.gu(4) |
102 | + anchors { |
103 | + top: parent.top |
104 | + topMargin: units.gu(2) |
105 | + bottom: parent.bottom |
106 | + } |
107 | + fontSize: "x-small" |
108 | + maximumLineCount: 2 |
109 | + wrapMode: Text.Wrap |
110 | + height: contentHeight |
111 | + } |
112 | + } |
113 | + |
114 | + ListItems.ThinDivider { |
115 | + anchors { |
116 | + left: parent.left |
117 | + leftMargin: units.gu(2) |
118 | + right: parent.right |
119 | + rightMargin: units.gu(2) |
120 | + } |
121 | + visible: header.visible |
122 | + } |
123 | + |
124 | + Repeater { |
125 | + model: actions.actions |
126 | + delegate: ListItems.Empty { |
127 | + action: actions.actions[index] |
128 | + objectName: action.objectName + "_item" |
129 | + visible: action.enabled |
130 | + showDivider: false |
131 | + |
132 | + height: units.gu(5) |
133 | + |
134 | + Label { |
135 | + anchors { |
136 | + left: parent.left |
137 | + leftMargin: units.gu(2) |
138 | + right: parent.right |
139 | + rightMargin: units.gu(2) |
140 | + verticalCenter: parent.verticalCenter |
141 | + } |
142 | + fontSize: "x-small" |
143 | + text: action.text |
144 | + } |
145 | + |
146 | + ListItems.ThinDivider { |
147 | + anchors { |
148 | + left: parent.left |
149 | + leftMargin: units.gu(2) |
150 | + right: parent.right |
151 | + rightMargin: units.gu(2) |
152 | + bottom: parent.bottom |
153 | + } |
154 | + } |
155 | + |
156 | + onTriggered: contextModel.close() |
157 | + } |
158 | + } |
159 | + |
160 | + ListItems.Empty { |
161 | + objectName: "cancelAction" |
162 | + height: units.gu(5) |
163 | + showDivider: false |
164 | + Label { |
165 | + anchors { |
166 | + left: parent.left |
167 | + leftMargin: units.gu(2) |
168 | + right: parent.right |
169 | + rightMargin: units.gu(2) |
170 | + verticalCenter: parent.verticalCenter |
171 | + } |
172 | + fontSize: "x-small" |
173 | + text: i18n.tr("Cancel") |
174 | + } |
175 | + onTriggered: contextModel.close() |
176 | + } |
177 | + |
178 | + // adjust default dialog visuals to custom requirements for the context menu |
179 | + Binding { |
180 | + target: __foreground |
181 | + property: "margins" |
182 | + value: 0 |
183 | + } |
184 | + Binding { |
185 | + target: __foreground |
186 | + property: "itemSpacing" |
187 | + value: 0 |
188 | + } |
189 | +} |
190 | |
191 | === added file 'src/app/webcontainer/ContextMenuWide.qml' |
192 | --- src/app/webcontainer/ContextMenuWide.qml 1970-01-01 00:00:00 +0000 |
193 | +++ src/app/webcontainer/ContextMenuWide.qml 2015-12-18 18:01:09 +0000 |
194 | @@ -0,0 +1,142 @@ |
195 | +/* |
196 | + * Copyright 2015 Canonical Ltd. |
197 | + * |
198 | + * This file is part of webbrowser-app. |
199 | + * |
200 | + * webbrowser-app is free software; you can redistribute it and/or modify |
201 | + * it under the terms of the GNU General Public License as published by |
202 | + * the Free Software Foundation; version 3. |
203 | + * |
204 | + * webbrowser-app is distributed in the hope that it will be useful, |
205 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
206 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
207 | + * GNU General Public License for more details. |
208 | + * |
209 | + * You should have received a copy of the GNU General Public License |
210 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
211 | + */ |
212 | + |
213 | +import QtQuick 2.4 |
214 | +import Ubuntu.Components 1.3 |
215 | +import Ubuntu.Components.ListItems 1.3 as ListItems |
216 | +import Ubuntu.Components.Popups 1.3 as Popups |
217 | +import com.canonical.Oxide 1.8 as Oxide |
218 | + |
219 | +Popups.Popover { |
220 | + id: contextMenu |
221 | + |
222 | + objectName: "contextMenuWide" |
223 | + |
224 | + property QtObject contextModel: model |
225 | + property ActionList actions: null |
226 | + property var associatedWebview: null |
227 | + |
228 | + QtObject { |
229 | + id: internal |
230 | + |
231 | + readonly property int lastEnabledActionIndex: { |
232 | + var last = -1 |
233 | + for (var i in actions.actions) { |
234 | + if (actions.actions[i].enabled) { |
235 | + last = i |
236 | + } |
237 | + } |
238 | + return last |
239 | + } |
240 | + |
241 | + readonly property real locationBarOffset: contextMenu.associatedWebview.locationBarController.height |
242 | + + contextMenu.associatedWebview.locationBarController.offset |
243 | + } |
244 | + |
245 | + Rectangle { |
246 | + anchors.fill: parent |
247 | + color: "#ececec" |
248 | + } |
249 | + |
250 | + Column { |
251 | + anchors { |
252 | + left: parent.left |
253 | + right: parent.right |
254 | + } |
255 | + |
256 | + Label { |
257 | + id: titleLabel |
258 | + objectName: "titleLabel" |
259 | + text: contextModel.srcUrl.toString() ? contextModel.srcUrl : contextModel.linkUrl |
260 | + anchors { |
261 | + left: parent.left |
262 | + leftMargin: units.gu(2) |
263 | + right: parent.right |
264 | + rightMargin: units.gu(2) |
265 | + } |
266 | + height: units.gu(5) |
267 | + visible: text |
268 | + fontSize: "x-small" |
269 | + color: "#888888" |
270 | + elide: Text.ElideRight |
271 | + verticalAlignment: Text.AlignVCenter |
272 | + } |
273 | + |
274 | + ListItems.ThinDivider { |
275 | + anchors { |
276 | + left: parent.left |
277 | + leftMargin: units.gu(2) |
278 | + right: parent.right |
279 | + rightMargin: units.gu(2) |
280 | + } |
281 | + visible: titleLabel.visible |
282 | + } |
283 | + |
284 | + Repeater { |
285 | + model: actions.actions |
286 | + delegate: ListItems.Empty { |
287 | + action: actions.actions[index] |
288 | + objectName: action.objectName + "_item" |
289 | + visible: action.enabled |
290 | + showDivider: false |
291 | + |
292 | + height: units.gu(5) |
293 | + |
294 | + Label { |
295 | + anchors { |
296 | + left: parent.left |
297 | + leftMargin: units.gu(2) |
298 | + right: parent.right |
299 | + rightMargin: units.gu(2) |
300 | + verticalCenter: parent.verticalCenter |
301 | + } |
302 | + fontSize: "small" |
303 | + text: action.text |
304 | + } |
305 | + |
306 | + ListItems.ThinDivider { |
307 | + visible: index < internal.lastEnabledActionIndex |
308 | + anchors { |
309 | + left: parent.left |
310 | + leftMargin: units.gu(2) |
311 | + right: parent.right |
312 | + rightMargin: units.gu(2) |
313 | + bottom: parent.bottom |
314 | + } |
315 | + } |
316 | + |
317 | + onTriggered: contextMenu.hide() |
318 | + } |
319 | + } |
320 | + } |
321 | + |
322 | + Item { |
323 | + id: positioner |
324 | + visible: false |
325 | + parent: contextMenu.associatedWebview |
326 | + x: contextModel.position.x |
327 | + y: contextModel.position.y + internal.locationBarOffset |
328 | + } |
329 | + caller: positioner |
330 | + |
331 | + onVisibleChanged: { |
332 | + if (!visible) { |
333 | + contextModel.close() |
334 | + } |
335 | + } |
336 | +} |
337 | |
338 | === modified file 'src/app/webcontainer/WebApp.qml' |
339 | --- src/app/webcontainer/WebApp.qml 2015-09-29 17:02:25 +0000 |
340 | +++ src/app/webcontainer/WebApp.qml 2015-12-18 18:01:09 +0000 |
341 | @@ -124,6 +124,7 @@ |
342 | id: containerWebView |
343 | objectName: "webview" |
344 | |
345 | + wide: webapp.wide |
346 | anchors { |
347 | left: parent.left |
348 | right: parent.right |
349 | |
350 | === modified file 'src/app/webcontainer/WebViewImplOxide.qml' |
351 | --- src/app/webcontainer/WebViewImplOxide.qml 2015-08-20 10:42:09 +0000 |
352 | +++ src/app/webcontainer/WebViewImplOxide.qml 2015-12-18 18:01:09 +0000 |
353 | @@ -37,6 +37,7 @@ |
354 | property url dataPath |
355 | property var popupController |
356 | property var overlayViewsParent: webview.parent |
357 | + property bool wide: false |
358 | |
359 | // Mostly used for testing & avoid external urls to |
360 | // "leak" in the default browser. External URLs corresponds |
361 | @@ -66,53 +67,106 @@ |
362 | |
363 | onNewViewRequested: popupController.createPopupView(overlayViewsParent, request, true, context) |
364 | |
365 | + property QtObject contextModel: null |
366 | contextualActions: ActionList { |
367 | + Actions.OpenLinkInWebBrowser { |
368 | + objectName: "OpenLinkInWebBrowser" |
369 | + enabled: contextModel && contextModel.linkUrl.toString() |
370 | + onTriggered: openUrlExternally(contextModel.linkUrl) |
371 | + } |
372 | Actions.CopyLink { |
373 | enabled: webview.contextModel && webview.contextModel.linkUrl.toString() |
374 | onTriggered: Clipboard.push(["text/plain", contextModel.linkUrl.toString()]) |
375 | + objectName: "CopyLinkContextualAction" |
376 | } |
377 | Actions.CopyImage { |
378 | enabled: webview.contextModel && |
379 | (webview.contextModel.mediaType === Oxide.WebView.MediaTypeImage) && |
380 | webview.contextModel.srcUrl.toString() |
381 | onTriggered: Clipboard.push(["text/plain", contextModel.srcUrl.toString()]) |
382 | + objectName: "CopyImageContextualAction" |
383 | } |
384 | Actions.Undo { |
385 | enabled: webview.contextModel && webview.contextModel.isEditable && |
386 | (webview.contextModel.editFlags & Oxide.WebView.UndoCapability) |
387 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandUndo) |
388 | + objectName: "UndoContextualAction" |
389 | } |
390 | Actions.Redo { |
391 | enabled: webview.contextModel && webview.contextModel.isEditable && |
392 | (webview.contextModel.editFlags & Oxide.WebView.RedoCapability) |
393 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandRedo) |
394 | + objectName: "RedoContextualAction" |
395 | } |
396 | Actions.Cut { |
397 | enabled: webview.contextModel && webview.contextModel.isEditable && |
398 | (webview.contextModel.editFlags & Oxide.WebView.CutCapability) |
399 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandCut) |
400 | + objectName: "CutContextualAction" |
401 | } |
402 | Actions.Copy { |
403 | enabled: webview.contextModel && webview.contextModel.isEditable && |
404 | (webview.contextModel.editFlags & Oxide.WebView.CopyCapability) |
405 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandCopy) |
406 | + objectName: "CopyContextualAction" |
407 | } |
408 | Actions.Paste { |
409 | enabled: webview.contextModel && webview.contextModel.isEditable && |
410 | (webview.contextModel.editFlags & Oxide.WebView.PasteCapability) |
411 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandPaste) |
412 | + objectName: "PasteContextualAction" |
413 | } |
414 | Actions.Erase { |
415 | enabled: webview.contextModel && webview.contextModel.isEditable && |
416 | (webview.contextModel.editFlags & Oxide.WebView.EraseCapability) |
417 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandErase) |
418 | + objectName: "EraseContextualAction" |
419 | } |
420 | Actions.SelectAll { |
421 | enabled: webview.contextModel && webview.contextModel.isEditable && |
422 | (webview.contextModel.editFlags & Oxide.WebView.SelectAllCapability) |
423 | onTriggered: webview.executeEditingCommand(Oxide.WebView.EditingCommandSelectAll) |
424 | - } |
425 | - } |
426 | + objectName: "SelectAllContextualAction" |
427 | + } |
428 | + } |
429 | + function contextMenuOnCompleted(menu) { |
430 | + if (!menu || !menu.contextModel) { |
431 | + return |
432 | + } |
433 | + contextModel = menu.contextModel |
434 | + |
435 | + var isImageMediaType = |
436 | + ((contextModel.mediaType === Oxide.WebView.MediaTypeImage) || |
437 | + (contextModel.mediaType === Oxide.WebView.MediaTypeCanvas)) |
438 | + && contextModel.hasImageContents; |
439 | + |
440 | + if (contextModel.linkUrl.toString() || |
441 | + contextModel.srcUrl.toString() || |
442 | + contextModel.selectionText || |
443 | + (contextModel.isEditable && contextModel.editFlags) || |
444 | + isImageMediaType) { |
445 | + menu.show() |
446 | + } else { |
447 | + contextModel.close() |
448 | + } |
449 | + } |
450 | + Component { |
451 | + id: contextMenuNarrowComponent |
452 | + ContextMenuMobile { |
453 | + actions: contextualActions |
454 | + Component.onCompleted: webview.contextMenuOnCompleted(this) |
455 | + } |
456 | + } |
457 | + Component { |
458 | + id: contextMenuWideComponent |
459 | + ContextMenuWide { |
460 | + associatedWebview: webview |
461 | + parent: browser |
462 | + actions: contextualActions |
463 | + Component.onCompleted: webview.contextMenuOnCompleted(this) |
464 | + } |
465 | + } |
466 | + contextMenu: webview.wide ? contextMenuWideComponent : contextMenuNarrowComponent |
467 | |
468 | StateSaver.properties: "url" |
469 | StateSaver.enabled: !runningLocalApplication |
470 | |
471 | === modified file 'src/app/webcontainer/WebappContainerWebview.qml' |
472 | --- src/app/webcontainer/WebappContainerWebview.qml 2015-08-10 15:22:00 +0000 |
473 | +++ src/app/webcontainer/WebappContainerWebview.qml 2015-12-18 18:01:09 +0000 |
474 | @@ -39,9 +39,12 @@ |
475 | property url webviewOverrideFile: "" |
476 | property bool blockOpenExternalUrls: false |
477 | property bool runningLocalApplication: false |
478 | + property bool wide: false |
479 | |
480 | signal samlRequestUrlPatternReceived(string urlPattern) |
481 | |
482 | + onWideChanged: if (webappContainerWebViewLoader.item) webappContainerWebViewLoader.item.wide = wide |
483 | + |
484 | PopupWindowController { |
485 | id: popupController |
486 | objectName: "popupController" |
487 | @@ -87,7 +90,8 @@ |
488 | , blockOpenExternalUrls: containerWebview.blockOpenExternalUrls |
489 | , runningLocalApplication: containerWebview.runningLocalApplication |
490 | , popupController: popupController |
491 | - , overlayViewsParent: containerWebview.parent}) |
492 | + , overlayViewsParent: containerWebview.parent |
493 | + , wide: containerWebview.wide}) |
494 | } |
495 | } |
496 | |
497 | |
498 | === added file 'src/app/webcontainer/assets/stock_link.svg' |
499 | --- src/app/webcontainer/assets/stock_link.svg 1970-01-01 00:00:00 +0000 |
500 | +++ src/app/webcontainer/assets/stock_link.svg 2015-12-18 18:01:09 +0000 |
501 | @@ -0,0 +1,164 @@ |
502 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
503 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
504 | + |
505 | +<svg |
506 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
507 | + xmlns:cc="http://creativecommons.org/ns#" |
508 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
509 | + xmlns:svg="http://www.w3.org/2000/svg" |
510 | + xmlns="http://www.w3.org/2000/svg" |
511 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
512 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
513 | + width="90" |
514 | + height="90" |
515 | + id="svg4874" |
516 | + version="1.1" |
517 | + inkscape:version="0.48+devel r" |
518 | + viewBox="0 0 90 90.000001" |
519 | + sodipodi:docname="insert-link02b.svg"> |
520 | + <defs |
521 | + id="defs4876" /> |
522 | + <sodipodi:namedview |
523 | + id="base" |
524 | + pagecolor="#ffffff" |
525 | + bordercolor="#666666" |
526 | + borderopacity="1.0" |
527 | + inkscape:pageopacity="0.0" |
528 | + inkscape:pageshadow="2" |
529 | + inkscape:zoom="5.0931704" |
530 | + inkscape:cx="51.019301" |
531 | + inkscape:cy="39.641321" |
532 | + inkscape:document-units="px" |
533 | + inkscape:current-layer="g4978" |
534 | + showgrid="true" |
535 | + showborder="true" |
536 | + fit-margin-top="0" |
537 | + fit-margin-left="0" |
538 | + fit-margin-right="0" |
539 | + fit-margin-bottom="0" |
540 | + inkscape:snap-bbox="true" |
541 | + inkscape:bbox-paths="true" |
542 | + inkscape:bbox-nodes="true" |
543 | + inkscape:snap-bbox-edge-midpoints="true" |
544 | + inkscape:snap-bbox-midpoints="true" |
545 | + inkscape:object-paths="true" |
546 | + inkscape:snap-intersection-paths="true" |
547 | + inkscape:object-nodes="true" |
548 | + inkscape:snap-smooth-nodes="true" |
549 | + inkscape:snap-midpoints="true" |
550 | + inkscape:snap-object-midpoints="true" |
551 | + inkscape:snap-center="true" |
552 | + showguides="true" |
553 | + inkscape:guide-bbox="true"> |
554 | + <inkscape:grid |
555 | + type="xygrid" |
556 | + id="grid5451" |
557 | + empspacing="6" /> |
558 | + <sodipodi:guide |
559 | + orientation="1,0" |
560 | + position="6,77" |
561 | + id="guide4063" /> |
562 | + <sodipodi:guide |
563 | + orientation="1,0" |
564 | + position="3,78" |
565 | + id="guide4065" /> |
566 | + <sodipodi:guide |
567 | + orientation="0,1" |
568 | + position="55,84" |
569 | + id="guide4067" /> |
570 | + <sodipodi:guide |
571 | + orientation="0,1" |
572 | + position="53,87" |
573 | + id="guide4069" /> |
574 | + <sodipodi:guide |
575 | + orientation="0,1" |
576 | + position="20,3" |
577 | + id="guide4071" /> |
578 | + <sodipodi:guide |
579 | + orientation="0,1" |
580 | + position="20,6" |
581 | + id="guide4073" /> |
582 | + <sodipodi:guide |
583 | + orientation="1,0" |
584 | + position="87,7" |
585 | + id="guide4075" /> |
586 | + <sodipodi:guide |
587 | + orientation="1,0" |
588 | + position="84,7" |
589 | + id="guide4077" /> |
590 | + <sodipodi:guide |
591 | + orientation="0,1" |
592 | + position="58,81" |
593 | + id="guide4074" /> |
594 | + <sodipodi:guide |
595 | + orientation="1,0" |
596 | + position="9,74" |
597 | + id="guide4076" /> |
598 | + <sodipodi:guide |
599 | + orientation="0,1" |
600 | + position="21,9" |
601 | + id="guide4078" /> |
602 | + <sodipodi:guide |
603 | + orientation="1,0" |
604 | + position="81,4" |
605 | + id="guide4080" /> |
606 | + </sodipodi:namedview> |
607 | + <metadata |
608 | + id="metadata4879"> |
609 | + <rdf:RDF> |
610 | + <cc:Work |
611 | + rdf:about=""> |
612 | + <dc:format>image/svg+xml</dc:format> |
613 | + <dc:type |
614 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
615 | + <dc:title></dc:title> |
616 | + </cc:Work> |
617 | + </rdf:RDF> |
618 | + </metadata> |
619 | + <g |
620 | + inkscape:label="Layer 1" |
621 | + inkscape:groupmode="layer" |
622 | + id="layer1" |
623 | + transform="translate(67.857146,-84.50504)"> |
624 | + <g |
625 | + transform="matrix(0,-1,-1,0,373.50506,516.50504)" |
626 | + id="g4845" |
627 | + style="display:inline"> |
628 | + <g |
629 | + inkscape:label="Layer 1" |
630 | + id="layer1-8" |
631 | + transform="matrix(0,-1,-1,0,1394.3622,441.36221)"> |
632 | + <rect |
633 | + style="color:#000000;fill:none;stroke:none;stroke-width:7.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
634 | + id="rect4198" |
635 | + width="90" |
636 | + height="90" |
637 | + x="0" |
638 | + y="962.36218" /> |
639 | + <g |
640 | + id="g4978" |
641 | + transform="translate(-60,548.00002)"> |
642 | + <rect |
643 | + style="color:#000000;fill:none;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
644 | + id="rect3038" |
645 | + width="90" |
646 | + height="90" |
647 | + x="0" |
648 | + y="1.7382814e-05" |
649 | + transform="translate(60,414.36216)" /> |
650 | + <path |
651 | + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" |
652 | + d="M 92.075086,472.28711 117.92492,446.43727" |
653 | + id="path4188" |
654 | + inkscape:connector-curvature="0" |
655 | + sodipodi:nodetypes="cc" /> |
656 | + <path |
657 | + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.99999952;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" |
658 | + d="M 63.667969 9.0371094 C 63.165875 9.0539444 62.671019 9.1114844 62.183594 9.2089844 C 58.284224 9.9890744 55.804541 12.722793 53.650391 14.876953 L 47.1875 21.339844 C 45.03334 23.493994 42.301574 25.973667 41.521484 29.873047 C 41.188085 31.539603 41.327146 33.294372 41.955078 35.121094 L 49.910156 27.164062 C 50.372184 26.657905 50.880803 26.130913 51.429688 25.582031 L 57.892578 19.119141 C 60.046728 16.964991 61.875558 15.389037 63.361328 15.091797 C 63.547048 15.054647 63.742359 15.027806 63.949219 15.017578 C 64.156079 15.007351 64.374492 15.013756 64.607422 15.041016 C 66.005022 15.204646 67.917154 16.153481 70.882812 19.119141 C 74.837032 23.073351 75.205443 25.154865 74.908203 26.640625 C 74.610973 28.126395 73.035009 29.953262 70.880859 32.107422 L 64.419922 38.570312 C 63.865878 39.124359 63.33492 39.635932 62.824219 40.101562 L 54.878906 48.046875 C 56.706268 48.675332 58.461808 48.813981 60.128906 48.480469 C 64.028276 47.700379 66.507959 44.96665 68.662109 42.8125 L 75.125 36.349609 C 77.27915 34.195449 80.010926 31.715786 80.791016 27.816406 C 81.571096 23.917036 79.78641 19.5364 75.125 14.875 C 71.62895 11.37895 68.290852 9.500825 65.195312 9.109375 C 64.679394 9.044135 64.170062 9.0202744 63.667969 9.0371094 z M 31.355469 41.349609 C 30.853375 41.366444 30.358515 41.423984 29.871094 41.521484 C 25.971725 42.301574 23.492043 45.035303 21.337891 47.189453 L 14.875 53.650391 C 12.720847 55.804541 9.9890734 58.286177 9.2089844 62.185547 C 8.4288954 66.084907 10.213595 70.465553 14.875 75.126953 C 19.536407 79.788363 23.917035 81.573059 27.816406 80.792969 C 31.715777 80.012879 34.195456 77.27915 36.349609 75.125 L 42.8125 68.662109 C 44.96665 66.507949 47.698426 64.028286 48.478516 60.128906 C 48.812028 58.461808 48.673379 56.706268 48.044922 54.878906 L 40.109375 62.814453 C 39.641569 63.32819 39.12796 63.862274 38.570312 64.419922 L 32.107422 70.882812 C 29.953269 73.036972 28.124437 74.610973 26.638672 74.908203 C 25.152907 75.205443 23.071405 74.837002 19.117188 70.882812 C 15.162971 66.928594 14.794562 64.847088 15.091797 63.361328 C 15.389032 61.875558 16.964989 60.048681 19.119141 57.894531 L 25.580078 51.431641 C 26.132543 50.879177 26.662506 50.368883 27.171875 49.904297 L 35.119141 41.957031 C 34.361083 41.696439 33.61486 41.514447 32.882812 41.421875 C 32.366891 41.356635 31.857562 41.332774 31.355469 41.349609 z " |
659 | + transform="translate(60.000003,414.36218)" |
660 | + id="path4190" /> |
661 | + </g> |
662 | + </g> |
663 | + </g> |
664 | + </g> |
665 | +</svg> |
666 | |
667 | === modified file 'tests/autopilot/webapp_container/tests/fake_servers.py' |
668 | --- tests/autopilot/webapp_container/tests/fake_servers.py 2015-05-27 16:19:45 +0000 |
669 | +++ tests/autopilot/webapp_container/tests/fake_servers.py 2015-12-18 18:01:09 +0000 |
670 | @@ -138,6 +138,11 @@ |
671 | </html> |
672 | """ |
673 | |
674 | + base64_png_data = \ |
675 | + "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAACXBIWXMAAAsTAAALEwE" \ |
676 | + "AmpwYAAAAOUlEQVRYw+3OAQ0AAAgDoGv/zlpDN0hATS7qaGlpaWlpaWlpaWlpaWlpaW" \ |
677 | + "lpaWlpaWlpaWlpab1qLUGqAWNyFWTYAAAAAElFTkSuQmCC" |
678 | + |
679 | def do_GET(self): |
680 | if self.path == '/': |
681 | self.send_response(200) |
682 | @@ -151,6 +156,28 @@ |
683 | elif self.path == '/with-external-link': |
684 | self.send_response(200) |
685 | self.serve_content(self.external_click_content()) |
686 | + elif self.path == "/image": |
687 | + self.send_response(200) |
688 | + html = '<html><body>' |
689 | + html += '<img src="data:image/png;base64,' + self.base64_png_data |
690 | + html += '" style="position: fixed; top: 50%; left: 50%; ' |
691 | + html += 'transform: translate(-50%, -50%)" />' |
692 | + html += '</body></html>' |
693 | + self.serve_content(html) |
694 | + elif self.path == "/imagelink": |
695 | + self.send_response(200) |
696 | + html = '<html><body><a href="http://www.ubuntu.com">' |
697 | + html += '<img src="data:image/png;base64,' + self.base64_png_data |
698 | + html += '" style="position: fixed; top: 50%; left: 50%; ' |
699 | + html += 'transform: translate(-50%, -50%)" />' |
700 | + html += '</a></body></html>' |
701 | + self.serve_content(html) |
702 | + elif self.path == "/textarea": |
703 | + self.send_response(200) |
704 | + html = '<html><body style="margin: 0">' |
705 | + html += '<textarea style="width: 100%; height: 100%">some text' |
706 | + html += '</textarea></body></html>' |
707 | + self.serve_content(html) |
708 | elif self.path == '/with-targetted-link': |
709 | self.send_response(200) |
710 | self.serve_content(self.targetted_click_content()) |
711 | |
712 | === added file 'tests/autopilot/webapp_container/tests/test_context_menu.py' |
713 | --- tests/autopilot/webapp_container/tests/test_context_menu.py 1970-01-01 00:00:00 +0000 |
714 | +++ tests/autopilot/webapp_container/tests/test_context_menu.py 2015-12-18 18:01:09 +0000 |
715 | @@ -0,0 +1,189 @@ |
716 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
717 | +# |
718 | +# Copyright 2015 Canonical |
719 | +# |
720 | +# This program is free software: you can redistribute it and/or modify it |
721 | +# under the terms of the GNU General Public License version 3, as published |
722 | +# by the Free Software Foundation. |
723 | +# |
724 | +# This program is distributed in the hope that it will be useful, |
725 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
726 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
727 | +# GNU General Public License for more details. |
728 | +# |
729 | +# You should have received a copy of the GNU General Public License |
730 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
731 | + |
732 | +import time |
733 | + |
734 | +from autopilot.platform import model |
735 | +from autopilot.matchers import Eventually |
736 | +from testtools.matchers import Equals, StartsWith |
737 | + |
738 | +from webapp_container.tests import WebappContainerTestCaseWithLocalContentBase |
739 | + |
740 | +import ubuntuuitoolkit as uitk |
741 | + |
742 | + |
743 | +class ContextMenuBase(uitk.UbuntuUIToolkitCustomProxyObjectBase): |
744 | + def get_title_label(self): |
745 | + return self.select_single(objectName="titleLabel") |
746 | + |
747 | + def get_visible_actions(self): |
748 | + return self.select_many("Empty", visible=True) |
749 | + |
750 | + def get_action(self, objectName): |
751 | + name = objectName + "_item" |
752 | + return self.select_single("Empty", objectName=name) |
753 | + |
754 | + def click_action(self, objectName): |
755 | + name = objectName + "_item" |
756 | + action = self.select_single("Empty", visible=True, |
757 | + enabled=True, objectName=name) |
758 | + self.pointing_device.click_object(action) |
759 | + self.wait_until_destroyed() |
760 | + |
761 | + |
762 | +class ContextMenuWide(ContextMenuBase): |
763 | + pass |
764 | + |
765 | + |
766 | +class ContextMenuMobile(ContextMenuBase): |
767 | + def click_cancel_action(self): |
768 | + action = self.select_single("Empty", objectName="cancelAction") |
769 | + self.pointing_device.click_object(action) |
770 | + |
771 | + |
772 | +class TestContextMenuBase(WebappContainerTestCaseWithLocalContentBase): |
773 | + data_uri_prefix = "data:image/png;base64," |
774 | + |
775 | + def _get_context_menu(self): |
776 | + if self.get_webcontainer_webview().wide: |
777 | + return self.app.wait_select_single( |
778 | + ContextMenuWide, |
779 | + objectName="contextMenuWide") |
780 | + else: |
781 | + return self.app.wait_select_single( |
782 | + ContextMenuMobile, |
783 | + objectName="contextMenuMobile") |
784 | + |
785 | + def _open_context_menu(self): |
786 | + webview = self.get_webview() |
787 | + x = webview.globalRect.x + webview.globalRect.width // 2 |
788 | + y = webview.globalRect.y + webview.globalRect.height // 2 |
789 | + self.pointing_device.move(x, y) |
790 | + if model() == 'Desktop': |
791 | + self.pointing_device.click(button=3) |
792 | + else: |
793 | + self.pointing_device.press() |
794 | + time.sleep(1.5) |
795 | + self.pointing_device.release() |
796 | + return self._get_context_menu() |
797 | + |
798 | + def _dismiss_context_menu(self, menu): |
799 | + if self.get_webcontainer_webview().wide: |
800 | + # Dismiss by clicking outside of the menu |
801 | + webview_rect = self.get_webview().globalRect |
802 | + actions = menu.get_visible_actions() |
803 | + outside_x = (webview_rect.x + actions[0].globalRect.x) // 2 |
804 | + outside_y = webview_rect.y + webview_rect.height // 2 |
805 | + self.pointing_device.move(outside_x, outside_y) |
806 | + self.pointing_device.click() |
807 | + else: |
808 | + # Dismiss by clicking the cancel action |
809 | + menu.click_cancel_action() |
810 | + menu.wait_until_destroyed() |
811 | + |
812 | + def setUp(self, path): |
813 | + super(TestContextMenuBase, self).setUp() |
814 | + args = [] |
815 | + self.launch_webcontainer_app_with_local_http_server( |
816 | + args, |
817 | + path, |
818 | + {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1'}) |
819 | + self.get_webcontainer_window().visible.wait_for(True) |
820 | + self.menu = self._open_context_menu() |
821 | + |
822 | + |
823 | +class TestContextMenuLink(TestContextMenuBase): |
824 | + |
825 | + def setUp(self): |
826 | + super(TestContextMenuLink, self).setUp(path="/with-external-link") |
827 | + self.assertThat(self.menu.get_title_label().text, |
828 | + Equals("http://www.ubuntu.com/")) |
829 | + |
830 | + def test_open_link_(self): |
831 | + main_webview = self.get_oxide_webview() |
832 | + signal = main_webview.watch_signal( |
833 | + 'openExternalUrlTriggered(QString)') |
834 | + self.assertThat(signal.was_emitted, Equals(False)) |
835 | + |
836 | + self.menu.click_action("OpenLinkInWebBrowser") |
837 | + |
838 | + self.assertThat(lambda: signal.was_emitted, Eventually(Equals(True))) |
839 | + self.assertThat(signal.num_emissions, Equals(1)) |
840 | + |
841 | + def test_copy_link(self): |
842 | + self.menu.click_action("CopyLinkContextualAction") |
843 | + |
844 | + |
845 | +class TestContextMenuImage(TestContextMenuBase): |
846 | + |
847 | + def setUp(self): |
848 | + super(TestContextMenuImage, self).setUp(path="/image") |
849 | + self.assertThat(self.menu.get_title_label().text, |
850 | + StartsWith(self.data_uri_prefix)) |
851 | + |
852 | + def test_copy_image(self): |
853 | + # There is no easy way to test the contents of the clipboard, |
854 | + # but we can at least verify that the context menu was dismissed. |
855 | + self.menu.click_action("CopyImageContextualAction") |
856 | + |
857 | + |
858 | +class TestContextMenuImageAndLink(TestContextMenuBase): |
859 | + |
860 | + def setUp(self): |
861 | + super(TestContextMenuImageAndLink, self).setUp(path="/imagelink") |
862 | + self.assertThat(self.menu.get_title_label().text, |
863 | + StartsWith(self.data_uri_prefix)) |
864 | + |
865 | + def test_open_link_in_webbrowser(self): |
866 | + main_webview = self.get_oxide_webview() |
867 | + signal = main_webview.watch_signal( |
868 | + 'openExternalUrlTriggered(QString)') |
869 | + self.assertThat(signal.was_emitted, Equals(False)) |
870 | + |
871 | + self.menu.click_action("OpenLinkInWebBrowser") |
872 | + |
873 | + self.assertThat(lambda: signal.was_emitted, Eventually(Equals(True))) |
874 | + self.assertThat(signal.num_emissions, Equals(1)) |
875 | + |
876 | + def test_copy_link(self): |
877 | + # There is no easy way to test the contents of the clipboard, |
878 | + # but we can at least verify that the context menu was dismissed. |
879 | + self.menu.click_action("CopyLinkContextualAction") |
880 | + |
881 | + def test_copy_image(self): |
882 | + # There is no easy way to test the contents of the clipboard, |
883 | + # but we can at least verify that the context menu was dismissed. |
884 | + self.menu.click_action("CopyImageContextualAction") |
885 | + |
886 | + |
887 | +class TestContextMenuTextArea(TestContextMenuBase): |
888 | + |
889 | + def setUp(self): |
890 | + super(TestContextMenuTextArea, self).setUp(path="/textarea") |
891 | + self.assertThat(self.menu.get_title_label().visible, Equals(False)) |
892 | + |
893 | + def test_actions(self): |
894 | + actions = ["SelectAll", |
895 | + "Cut", |
896 | + "Undo", |
897 | + "Redo", |
898 | + "Paste", |
899 | + "SelectAll", |
900 | + "Copy", |
901 | + "Erase"] |
902 | + for action in actions: |
903 | + self.menu.click_action("{}ContextualAction".format(action)) |
904 | + self.menu = self._open_context_menu() |
FAILED: Continuous integration, rev:1231 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 2359/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 4667 jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- amd64-ci/ 1113/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 1113 jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 1113/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- i386-ci/ 1113 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- vivid-mako/ 3765 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4664 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4664/artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 24255
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 2359/rebuild
http://