Merge lp:~abreu-alexandre/webbrowser-app/window-open-overlay into lp:webbrowser-app
- window-open-overlay
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Olivier Tilloy |
Approved revision: | 989 |
Merged at revision: | 989 |
Proposed branch: | lp:~abreu-alexandre/webbrowser-app/window-open-overlay |
Merge into: | lp:webbrowser-app |
Diff against target: |
1006 lines (+612/-253) 9 files modified
src/app/webcontainer/PopupWindowController.qml (+181/-0) src/app/webcontainer/PopupWindowOverlay.qml (+199/-0) src/app/webcontainer/WebViewImplOxide.qml (+13/-130) src/app/webcontainer/WebappContainerWebview.qml (+11/-1) tests/autopilot/webapp_container/tests/__init__.py (+6/-0) tests/autopilot/webapp_container/tests/fake_servers.py (+32/-11) tests/autopilot/webapp_container/tests/test_popup_webview_overlay.py (+170/-0) tests/autopilot/webapp_container/tests/test_redirection_pattern.py (+0/-59) tests/autopilot/webapp_container/tests/test_url_patterns.py (+0/-52) |
To merge this branch: | bzr merge lp:~abreu-alexandre/webbrowser-app/window-open-overlay |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Olivier Tilloy | Approve | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+248000@code.launchpad.net |
Commit message
Add multi-window support for webapps
Description of the change
Add multi-window support for webapps
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:944
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:945
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:946
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
Not sure exactly what the intended UX behaviour is (the spec is a bit summary), this is what I’m seeing when testing on the desktop:
- The animation to open an overlay is quite fast, almost imperceptible (could we maybe make it a tad slower?)
- When dismissing an overlay (by dragging it downwards or clicking on the chevron), it’s destroyed, right? I’m thinking that in that case maybe a cross icon would be more appropriate than a chevron, but of course that’s for a visual designer to decide.
- When opening an overlay, the current webview seems to be hidden instantaneously, it should be hidden only once the animation has completed.
- Similarly, when dragging an overlay downwards, nothing is visible behind, I think the main webview (or the previous overlay if any) should be visible.
- After opening 3 overlays, the fourth external link gets open in my desktop browser (chromium) as expected, but then after closing one overlay and starting to re-open more external links, I got in a situation where blank chromium windows would open instead of a new tab in the current instance, this is weird (tested with initially opening the container on http://
qml: Maximum number of popup overlay opened, opening: about:blank in the browser
Olivier Tilloy (osomon) wrote : | # |
Also, I’m thinking that this behaviour makes sense on devices, but does it on desktop, where it’s much more visible when a new tab opens in a browser?
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:948
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 948. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
Alexandre Abreu (abreu-alexandre) wrote : | # |
> Not sure exactly what the intended UX behaviour is (the spec is a bit
> summary), this is what I’m seeing when testing on the desktop:
>
> - The animation to open an overlay is quite fast, almost imperceptible (could
> we maybe make it a tad slower?)
agree, done
> - When dismissing an overlay (by dragging it downwards or clicking on the
> chevron), it’s destroyed, right? I’m thinking that in that case maybe a cross
> icon would be more appropriate than a chevron, but of course that’s for a
> visual designer to decide.
yeah, those are the designs I had from "design", ... imo it is rather understandable,
> - When opening an overlay, the current webview seems to be hidden
> instantaneously, it should be hidden only once the animation has completed.
>
> - Similarly, when dragging an overlay downwards, nothing is visible behind, I
> think the main webview (or the previous overlay if any) should be visible.
I updated the behavior to be cleaner & slicker,
> - After opening 3 overlays, the fourth external link gets open in my desktop
> browser (chromium) as expected, but then after closing one overlay and
> starting to re-open more external links, I got in a situation where blank
> chromium windows would open instead of a new tab in the current instance, this
> is weird (tested with initially opening the container on
> http://
> on the console:
>
> qml: Maximum number of popup overlay opened, opening: about:blank in the
> browser
mmh I was not able to repro that ...
Alexandre Abreu (abreu-alexandre) wrote : | # |
> Also, I’m thinking that this behaviour makes sense on devices, but does it on
> desktop, where it’s much more visible when a new tab opens in a browser?
I would have to check with design, but I still does make sense on desktop too.
The behavior might be adjusted a bit but it does not feel too awkward.
We dont support tabs for webapps no matter what the environment is, and when thinking
about tabs+webapps on desktop it is not obvious to me how to have it work in a clean way
for the user. Adding tabs is somewhat out of the question (at least atm) I think,
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:949
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 949. By Olivier Tilloy
-
Use the new locationBarCont
roller API available in oxide 1.5 to control the position of the chrome. Fixes: #1365179, #1429132
Approved by: Alexandre Abreu - 950. By Olivier Tilloy
-
Rewrite URLs with an uppercase scheme. Fixes: #1436312
- 951. By Olivier Tilloy
-
Remove two broken symlinks.
- 952. By Olivier Tilloy
-
Always initialize member attribute at construction time.
Not really an issue here, but flagged by coverity (https:/
/scan.coverity. com/projects/ 4565), and easy enough to address. - 953. By CI Train Bot Account
-
Releasing 0.23+15.
04.20150331. 2-0ubuntu1 - 954. By CI Train Bot Account
-
Resync trunk.
- 955. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 956. By Riccardo Padovani
-
Add settings page, per design specification. This adds qml-module-
qt-labs- folderlistmodel and qml-module- qt-labs- settings as runtime dependencies for webbrowser-app. Fixes: #1351183
Approved by: Bill Filler, Olivier Tilloy - 957. By Olivier Tilloy
-
Autopilot tests for the settings UI.
- 958. By Olivier Tilloy
-
Add a "Clear Cache" entry under the privacy settings. Fixes: #1260014, #1296364
Approved by: PS Jenkins bot - 959. By CI Train Bot Account
-
Releasing 0.23+15.
04.20150408- 0ubuntu1 - 960. By Olivier Tilloy
-
Update translation template.
- 961. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 962. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 963. By Alexandre Abreu
-
remove qtwebkit deps (LP: #1362640) Fixes: #1362640
Approved by: Timo Jyrinki, PS Jenkins bot, Olivier Tilloy - 964. By Justin McPherson <justin@phablet-dev>
-
Command line options for media-hub use through Oxide.
Approved by: PS Jenkins bot - 965. By CI Train Bot Account
-
Releasing 0.23+15.
04.20150410- 0ubuntu1 - 966. By CI Train Bot Account
-
Resync trunk.
- 967. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
Olivier Tilloy (osomon) wrote : | # |
There’s a couple of trivial conflicts when merging into the latest trunk.
Olivier Tilloy (osomon) wrote : | # |
I’m seeing 3 failures when running the autopilot tests on my desktop:
webapp_
webapp_
webapp_
Alexandre Abreu (abreu-alexandre) wrote : | # |
updated
- 968. By Arthur Mello
-
Add model support to control which history entries will be displayed based on a blacklist database
Approved by: PS Jenkins bot, Olivier Tilloy - 969. By Arthur Mello
-
Make Top Sites format equal to Bookmarks on the New Tab view
Approved by: PS Jenkins bot - 970. By CI Train Bot Account
-
Releasing 0.23+15.
04.20150416- 0ubuntu1
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:970
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 971. By CI Train Bot Account
-
Resync trunk.
- 972. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
Olivier Tilloy (osomon) wrote : | # |
I’m still seeing autopilot test failures when run on my desktop (up-to-date vivid): http://
- 973. By Ugo Riboni
-
Include bookmark results in the suggestions list Fixes: #1351177
Approved by: Olivier Tilloy, PS Jenkins bot - 974. By Alexandre Abreu
-
Add missing reload button from the webapp container as specified in the design document.
Approved by: Olivier Tilloy, PS Jenkins bot - 975. By Ken VanDine
-
added ShareLink to contextualActions
Approved by: Olivier Tilloy, PS Jenkins bot
- 976. By Olivier Tilloy
-
Save the updated homepage when pressing return. Fixes: #1441874
Approved by: PS Jenkins bot, Riccardo Padovani - 977. By Leo Arias
-
In the autopilot tests, removed the extra focus step to write a URL. Fixes: #1441551
Approved by: Olivier Tilloy, PS Jenkins bot - 978. By Olivier Tilloy
-
Always exit fullscreen mode when the application becomes inactive. Fixes: #1331475
Approved by: PS Jenkins bot, Bill Filler - 979. By Olivier Tilloy
-
Recognize about:blank as a valid URL. Fixes: #1444139
Approved by: PS Jenkins bot - 980. By CI Train Bot Account
-
Releasing 0.23+15.
04.20150422. 1-0ubuntu1 - 981. By CI Train Bot Account
-
Resync trunk.
- 982. By Olivier Tilloy
-
Update translation template.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:970
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 983. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 984. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 985. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 986. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 987. By Launchpad Translations on behalf of phablet-team
-
Launchpad automatic translations update.
- 988. By Alexandre Abreu
-
Window overlay for popups
- 989. By Alexandre Abreu
-
Fix AP global coords used for the clicks
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:972
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:989
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
That looks good to me now, and the autopilot tests are all passing on my laptop.
- 990. By Alexandre Abreu
-
tweak to properly trigger elide
Preview Diff
1 | === added file 'src/app/webcontainer/PopupWindowController.qml' |
2 | --- src/app/webcontainer/PopupWindowController.qml 1970-01-01 00:00:00 +0000 |
3 | +++ src/app/webcontainer/PopupWindowController.qml 2015-04-30 16:33:24 +0000 |
4 | @@ -0,0 +1,181 @@ |
5 | +/* |
6 | + * Copyright 2014 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 QtQuick 2.0 |
24 | +import com.canonical.Oxide 1.0 as Oxide |
25 | +import Ubuntu.Components 1.1 |
26 | +import Ubuntu.Components.Popups 1.0 |
27 | + |
28 | +Item { |
29 | + id: controller |
30 | + |
31 | + property var webappUrlPatterns |
32 | + property var mainWebappView |
33 | + property var views: [] |
34 | + property bool blockOpenExternalUrls: false |
35 | + |
36 | + // Used to access runtime behavior during tests |
37 | + signal openExternalUrlTriggered(string url) |
38 | + signal newViewCreated(string url) |
39 | + signal windowOverlayOpenAnimationDone() |
40 | + |
41 | + readonly property int maxSimultaneousViews: 3 |
42 | + |
43 | + function openUrlExternally(url) { |
44 | + if (!blockOpenExternalUrls) { |
45 | + Qt.openUrlExternally(url) |
46 | + } |
47 | + openExternalUrlTriggered(url) |
48 | + } |
49 | + |
50 | + function onOverlayMoved(popup, diffY) { |
51 | + if ((popup.y + diffY) > 0) { |
52 | + popup.y += diffY |
53 | + } |
54 | + } |
55 | + function handleNewViewAdded(view) { |
56 | + if (views.length !== 0) { |
57 | + var topView = views[views.length-1] |
58 | + } |
59 | + views.push(view) |
60 | + } |
61 | + function handleOpenInUrlBrowserForView(url, view) { |
62 | + handleViewRemoved(view) |
63 | + openExternalUrlTriggered(url) |
64 | + openUrlExternally(url) |
65 | + } |
66 | + function createViewSlidingHandlerFor(newView, viewBelow) { |
67 | + var parentHeight = viewBelow.parent.height |
68 | + return function() { |
69 | + if (viewBelow && newView) { |
70 | + viewBelow.opacity = |
71 | + newView.y / parentHeight |
72 | + } |
73 | + } |
74 | + } |
75 | + function topViewOnStack() { |
76 | + if (views.length !== 0) { |
77 | + return views[views.length-1] |
78 | + } |
79 | + return mainWebappView |
80 | + } |
81 | + function handleViewRemoved(view) { |
82 | + if (views.length === 0) { |
83 | + return |
84 | + } |
85 | + |
86 | + var topMostView = views[views.length-1] |
87 | + if (topMostView !== view) { |
88 | + return |
89 | + } |
90 | + views.pop() |
91 | + |
92 | + var parentHeight = topMostView.parent.height |
93 | + var nextView = topViewOnStack() |
94 | + nextView.visible = true |
95 | + |
96 | + function onViewSlidingOut() { |
97 | + if (topMostView.y >= (topMostView.parent.height - 10)) { |
98 | + topMostView.yChanged.disconnect(onViewSlidingOut) |
99 | + topMostView.destroy() |
100 | + |
101 | + updateViewVisibility(nextView, true) |
102 | + } |
103 | + } |
104 | + topMostView.yChanged.connect(onViewSlidingOut) |
105 | + topMostView.y = topMostView.parent.height |
106 | + } |
107 | + function createPopupView(parentView, request, isRequestFromMainWebappWebview, context) { |
108 | + var view = popupWebOverlayFactory.createObject( |
109 | + parentView, |
110 | + { request: request, |
111 | + webContext: context, |
112 | + popupWindowController: controller }); |
113 | + |
114 | + var topMostView = topViewOnStack() |
115 | + |
116 | + // handle opacity updates of the view below this one |
117 | + // when the view is sliding |
118 | + view.yChanged.connect( |
119 | + createViewSlidingHandlerFor(view, topMostView)) |
120 | + |
121 | + function onViewSlidingIn() { |
122 | + var parentHeight = view.parent.height |
123 | + |
124 | + if (view.y <= 10) { |
125 | + view.yChanged.disconnect(onViewSlidingIn) |
126 | + |
127 | + updateViewVisibility(topMostView, false) |
128 | + } |
129 | + } |
130 | + view.yChanged.connect(onViewSlidingIn) |
131 | + |
132 | + view.y = 0 |
133 | + handleNewViewAdded(view) |
134 | + newViewCreated(view.url) |
135 | + } |
136 | + function updateViewVisibility(view, visible) { |
137 | + if (view) { |
138 | + view.opacity = visible ? 1.0 : 0.0 |
139 | + } |
140 | + } |
141 | + |
142 | + Component { |
143 | + id: popupWebOverlayFactory |
144 | + PopupWindowOverlay { |
145 | + id: overlay |
146 | + |
147 | + height: parent.height |
148 | + width: parent.width |
149 | + |
150 | + y: overlay.parent.height |
151 | + |
152 | + // Poor mans heuristic to know when an overlay has been |
153 | + // loaded and is in full view. We cannot rely on the |
154 | + // NumberAnimation running/started since they dont |
155 | + // work properly when inside a Behavior |
156 | + onYChanged: { |
157 | + if (y === 0) { |
158 | + windowOverlayOpenAnimationDone() |
159 | + } |
160 | + } |
161 | + |
162 | + Behavior on y { |
163 | + NumberAnimation { |
164 | + duration: 500 |
165 | + easing.type: Easing.InOutQuad |
166 | + } |
167 | + } |
168 | + } |
169 | + } |
170 | + |
171 | + function handleNewForegroundNavigationRequest( |
172 | + url, request, isRequestFromMainWebappWebview) { |
173 | + |
174 | + if (views.length >= maxSimultaneousViews) { |
175 | + request.action = Oxide.NavigationRequest.ActionReject |
176 | + // Default to open externally, maybe should present a dialog |
177 | + openUrlExternally(url.toString()) |
178 | + console.log("Maximum number of popup overlay opened, opening: " |
179 | + + url |
180 | + + " in the browser") |
181 | + return |
182 | + } |
183 | + request.action = Oxide.NavigationRequest.ActionAccept |
184 | + } |
185 | +} |
186 | |
187 | === added file 'src/app/webcontainer/PopupWindowOverlay.qml' |
188 | --- src/app/webcontainer/PopupWindowOverlay.qml 1970-01-01 00:00:00 +0000 |
189 | +++ src/app/webcontainer/PopupWindowOverlay.qml 2015-04-30 16:33:24 +0000 |
190 | @@ -0,0 +1,199 @@ |
191 | +/* |
192 | + * Copyright 2014 Canonical Ltd. |
193 | + * |
194 | + * This file is part of webbrowser-app. |
195 | + * |
196 | + * webbrowser-app is free software; you can redistribute it and/or modify |
197 | + * it under the terms of the GNU General Public License as published by |
198 | + * the Free Software Foundation; version 3. |
199 | + * |
200 | + * webbrowser-app is distributed in the hope that it will be useful, |
201 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
202 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
203 | + * GNU General Public License for more details. |
204 | + * |
205 | + * You should have received a copy of the GNU General Public License |
206 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
207 | + */ |
208 | + |
209 | +import QtQuick 2.0 |
210 | +import QtQuick.Window 2.0 |
211 | +import com.canonical.Oxide 1.4 as Oxide |
212 | +import Ubuntu.Components 1.1 |
213 | +import ".." |
214 | + |
215 | +Item { |
216 | + id: popup |
217 | + |
218 | + property var popupWindowController |
219 | + property var webContext |
220 | + property alias request: popupWebview.request |
221 | + property alias url: popupWebview.url |
222 | + |
223 | + Rectangle { |
224 | + color: "#F2F1F0" |
225 | + anchors.fill: parent |
226 | + } |
227 | + |
228 | + Item { |
229 | + id: menubar |
230 | + |
231 | + height: units.gu(6) |
232 | + width: parent.width |
233 | + |
234 | + anchors { |
235 | + top: parent.top |
236 | + horizontalCenter: parent.horizontalCenter |
237 | + } |
238 | + |
239 | + ChromeButton { |
240 | + id: closeButton |
241 | + objectName: "overlayCloseButton" |
242 | + anchors { |
243 | + left: parent.left |
244 | + verticalCenter: parent.verticalCenter |
245 | + } |
246 | + |
247 | + height: parent.height |
248 | + width: height |
249 | + |
250 | + iconName: "dropdown-menu" |
251 | + iconSize: 0.6 * height |
252 | + |
253 | + enabled: true |
254 | + visible: true |
255 | + |
256 | + MouseArea { |
257 | + anchors.fill: parent |
258 | + onClicked: { |
259 | + if (popupWindowController) { |
260 | + popupWindowController.handleViewRemoved(popup) |
261 | + } |
262 | + } |
263 | + } |
264 | + } |
265 | + |
266 | + Item { |
267 | + anchors { |
268 | + top: parent.top |
269 | + bottom: parent.bottom |
270 | + left: closeButton.right |
271 | + right: buttonOpenInBrowser.left |
272 | + } |
273 | + |
274 | + Label { |
275 | + anchors { |
276 | + rightMargin: units.gu(2) |
277 | + verticalCenter: parent.verticalCenter |
278 | + left: parent.left |
279 | + right: parent.right |
280 | + } |
281 | + |
282 | + text: popupWebview.title ? popupWebview.title : popupWebview.url |
283 | + elide: Text.ElideRight |
284 | + } |
285 | + |
286 | + MouseArea { |
287 | + anchors.fill: parent |
288 | + |
289 | + property int initMouseY: 0 |
290 | + property int prevMouseY: 0 |
291 | + |
292 | + onPressed: { |
293 | + initMouseY = mouse.y |
294 | + prevMouseY = initMouseY |
295 | + } |
296 | + onReleased: { |
297 | + if ((prevMouseY - initMouseY) > (popup.height / 8) || |
298 | + popup.y > popup.height/2) { |
299 | + if (popupWindowController) { |
300 | + popupWindowController.handleViewRemoved(popup) |
301 | + return |
302 | + } |
303 | + } |
304 | + popup.y = 0 |
305 | + } |
306 | + onMouseYChanged: { |
307 | + if (popupWindowController) { |
308 | + var diff = mouseY - initMouseY |
309 | + prevMouseY = mouseY |
310 | + popupWindowController.onOverlayMoved(popup, diff) |
311 | + } |
312 | + } |
313 | + } |
314 | + } |
315 | + |
316 | + ChromeButton { |
317 | + id: buttonOpenInBrowser |
318 | + objectName: "overlayButtonOpenInBrowser" |
319 | + anchors { |
320 | + right: parent.right |
321 | + verticalCenter: parent.verticalCenter |
322 | + rightMargin: units.gu(1) |
323 | + } |
324 | + |
325 | + height: parent.height |
326 | + width: height |
327 | + |
328 | + iconName: "external-link" |
329 | + iconSize: 0.6 * height |
330 | + |
331 | + enabled: true |
332 | + visible: true |
333 | + |
334 | + MouseArea { |
335 | + anchors.fill: parent |
336 | + onClicked: { |
337 | + if (popupWindowController) { |
338 | + popupWindowController.handleOpenInUrlBrowserForView( |
339 | + popupWebview.url, popup) |
340 | + } |
341 | + } |
342 | + } |
343 | + } |
344 | + } |
345 | + |
346 | + WebViewImpl { |
347 | + id: popupWebview |
348 | + |
349 | + objectName: "overlayWebview" |
350 | + |
351 | + context: webContext |
352 | + |
353 | + anchors { |
354 | + bottom: parent.bottom |
355 | + left: parent.left |
356 | + right: parent.right |
357 | + top: menubar.bottom |
358 | + } |
359 | + |
360 | + onNewViewRequested: { |
361 | + if (popupWindowController) { |
362 | + popupWindowController.createPopupView( |
363 | + popup.parent, request, false, context) |
364 | + } |
365 | + } |
366 | + |
367 | + function isNewForegroundWebViewDisposition(disposition) { |
368 | + return disposition === Oxide.NavigationRequest.DispositionNewPopup || |
369 | + disposition === Oxide.NavigationRequest.DispositionNewForegroundTab; |
370 | + } |
371 | + |
372 | + onNavigationRequested: { |
373 | + var url = request.url.toString() |
374 | + if (isNewForegroundWebViewDisposition(request.disposition)) { |
375 | + popupWindowController.handleNewForegroundNavigationRequest( |
376 | + url, request, false) |
377 | + return |
378 | + } |
379 | + request.action = Oxide.NavigationRequest.ActionAccept |
380 | + } |
381 | + |
382 | + onCloseRequested: { |
383 | + if (popupWindowController) { |
384 | + popupWindowController.handleViewRemoved(popup) |
385 | + } |
386 | + } |
387 | + } |
388 | + |
389 | +} |
390 | |
391 | === modified file 'src/app/webcontainer/WebViewImplOxide.qml' |
392 | --- src/app/webcontainer/WebViewImplOxide.qml 2015-02-19 11:50:21 +0000 |
393 | +++ src/app/webcontainer/WebViewImplOxide.qml 2015-04-30 16:33:24 +0000 |
394 | @@ -35,9 +35,13 @@ |
395 | property var webappUrlPatterns: null |
396 | property string popupRedirectionUrlPrefixPattern: "" |
397 | property url dataPath |
398 | + property var popupController |
399 | + property var overlayViewsParent: webview.parent |
400 | |
401 | // Mostly used for testing & avoid external urls to |
402 | - // "leak" in the default browser |
403 | + // "leak" in the default browser. External URLs corresponds |
404 | + // to URLs that are not included in the set defined by the url patterns |
405 | + // (if any) or navigations resulting in new windows being created. |
406 | property bool blockOpenExternalUrls: false |
407 | |
408 | // Those signals are used for testing purposes to externally |
409 | @@ -55,6 +59,10 @@ |
410 | |
411 | preferences.allowFileAccessFromFileUrls: runningLocalApplication |
412 | preferences.allowUniversalAccessFromFileUrls: runningLocalApplication |
413 | + preferences.localStorageEnabled: true |
414 | + preferences.appCacheEnabled: true |
415 | + |
416 | + onNewViewRequested: popupController.createPopupView(overlayViewsParent, request, true, context) |
417 | |
418 | contextualActions: ActionList { |
419 | Actions.CopyLink { |
420 | @@ -119,77 +127,17 @@ |
421 | } |
422 | |
423 | function navigationRequestedDelegate(request) { |
424 | - var newForegroundPageRequest = isNewForegroundWebViewDisposition(request.disposition) |
425 | var url = request.url.toString() |
426 | - |
427 | - console.log("navigationRequestedDelegate - newForegroundPageRequest: " |
428 | - + newForegroundPageRequest |
429 | - + ', url: ' + url) |
430 | - |
431 | if (runningLocalApplication && url.indexOf("file://") !== 0) { |
432 | request.action = Oxide.NavigationRequest.ActionReject |
433 | openUrlExternally(url) |
434 | return |
435 | } |
436 | |
437 | - // Covers some edge cases corresponding to the default window.open() behavior. |
438 | - // When it is being called, the targetted URL will not load right away but |
439 | - // will first round trip to an "about:blank". |
440 | - // See https://developer.mozilla.org/en-US/docs/Web/API/Window.open |
441 | - if (newForegroundPageRequest) { |
442 | - if (url == 'about:blank') { |
443 | - console.log('Accepting a new window request to navigate to "about:blank"') |
444 | - request.action = Oxide.NavigationRequest.ActionAccept |
445 | - return |
446 | - } |
447 | - |
448 | - var isRedirectionUrl = false; |
449 | - var targetUrl = url; |
450 | - if (popupRedirectionUrlPrefixPattern) { |
451 | - // NOTE: very nasty workaround to be backward compatibility, will be deleted as soon |
452 | - // as the FB webapp is updated. |
453 | - if (popupRedirectionUrlPrefixPattern.indexOf('(') === -1) { |
454 | - isRedirectionUrl = (url.indexOf(popupRedirectionUrlPrefixPattern) === 0); |
455 | - targetUrl = isRedirectionUrl ? |
456 | - url.slice(popupRedirectionUrlPrefixPattern.length) : url; |
457 | - |
458 | - // Quick fix for http://pad.lv/1358622 (trim trailing parameters). |
459 | - var extraParams = targetUrl.indexOf("&"); |
460 | - if (extraParams !== -1) { |
461 | - targetUrl = targetUrl.slice(0, extraParams); |
462 | - } |
463 | - } else { |
464 | - var redirectionPatternMatch = url.match(popupRedirectionUrlPrefixPattern); |
465 | - isRedirectionUrl = |
466 | - popupRedirectionUrlPrefixPattern |
467 | - && redirectionPatternMatch |
468 | - && redirectionPatternMatch.length >= 2; |
469 | - |
470 | - // Assume that the first group is the matching one |
471 | - targetUrl = isRedirectionUrl ? |
472 | - redirectionPatternMatch[1] : url; |
473 | - } |
474 | - } |
475 | - |
476 | - if (isRedirectionUrl) { |
477 | - console.debug("Got a redirection URL with target URL: " + targetUrl) |
478 | - targetUrl = decodeURIComponent(targetUrl) |
479 | - gotRedirectionUrl(targetUrl) |
480 | - } |
481 | - |
482 | - if (webview.shouldAllowNavigationTo(targetUrl)) { |
483 | - console.debug('Redirecting popup browsing ' + targetUrl + ' in the current container window.') |
484 | - request.action = Oxide.NavigationRequest.ActionReject |
485 | - webappContainerHelper.browseToUrlRequested(webview, targetUrl) |
486 | - return |
487 | - } |
488 | - |
489 | - if (shouldOpenPopupsInDefaultBrowser()) { |
490 | - console.debug('Opening popup window ' + targetUrl + ' in the browser window.') |
491 | - request.action = Oxide.NavigationRequest.ActionReject |
492 | - openUrlExternally(targetUrl) |
493 | - return; |
494 | - } |
495 | + request.action = Oxide.NavigationRequest.ActionReject |
496 | + if (isNewForegroundWebViewDisposition(request.disposition)) { |
497 | + request.action = Oxide.NavigationRequest.ActionAccept |
498 | + popupController.handleNewForegroundNavigationRequest(url, request, true) |
499 | return |
500 | } |
501 | |
502 | @@ -201,7 +149,6 @@ |
503 | return |
504 | } |
505 | |
506 | - request.action = Oxide.NavigationRequest.ActionReject |
507 | if (webview.shouldAllowNavigationTo(url)) |
508 | request.action = Oxide.NavigationRequest.ActionAccept |
509 | |
510 | @@ -228,70 +175,6 @@ |
511 | } |
512 | } |
513 | |
514 | - function createPopupWindow(request) { |
515 | - popupWebViewFactory.createObject(webview, { request: request, width: 500, height: 800 }); |
516 | - } |
517 | - |
518 | - Component { |
519 | - id: popupWebViewFactory |
520 | - Window { |
521 | - id: popup |
522 | - property alias request: popupBrowser.request |
523 | - WebView { |
524 | - id: popupBrowser |
525 | - anchors.fill: parent |
526 | - |
527 | - function navigationRequestedDelegate(request) { |
528 | - var url = request.url.toString() |
529 | - |
530 | - // If we are to browse in the popup to a place where we are not allows |
531 | - if ( ! isNewForegroundWebViewDisposition(request.disposition) && |
532 | - ! webview.shouldAllowNavigationTo(url)) { |
533 | - request.action = Oxide.NavigationRequest.ActionReject |
534 | - openUrlExternally(url); |
535 | - popup.close() |
536 | - return; |
537 | - } |
538 | - |
539 | - // Fallback to regulat checks (there is a bit of overlap) |
540 | - webview.navigationRequestedDelegate(request) |
541 | - } |
542 | - |
543 | - onNewViewRequested: webview.createPopupWindow(request) |
544 | - |
545 | - // Oxide (and Chromium) does not inform of non user |
546 | - // driven navigations (or more specifically redirects that |
547 | - // would be part of an popup/webview load (after its been |
548 | - // granted). Quite a few sites (e.g. Youtube), |
549 | - // create popups when clicking on links (or following a window.open()) |
550 | - // with proper youtube.com address but w/ redirection |
551 | - // params, e.g.: |
552 | - // http://www.youtube.com/redirect?q=http%3A%2F%2Fgodzillamovie.com%2F&redir_token=b8WPI1pq9FHXeHm2bN3KVLAJSfp8MTM5NzI2NDg3NEAxMzk3MTc4NDc0 |
553 | - // In this instance the popup & navigation is granted, but then |
554 | - // a redirect happens inside the popup to the real target url (here http://godzillamovie.com) |
555 | - // which is not trapped by a navigation requested and therefore not filtered. |
556 | - // The only way to do it atm is to listen to url changed in popups & also |
557 | - // filter there. |
558 | - onUrlChanged: { |
559 | - var _url = url.toString(); |
560 | - if (_url.trim().length === 0) |
561 | - return; |
562 | - |
563 | - if (_url != 'about:blank' && ! webview.shouldAllowNavigationTo(_url)) { |
564 | - openUrlExternally(_url); |
565 | - popup.close() |
566 | - } |
567 | - } |
568 | - } |
569 | - Component.onCompleted: popup.show() |
570 | - } |
571 | - } |
572 | - |
573 | - onNewViewRequested: createPopupWindow(request) |
574 | - |
575 | - preferences.localStorageEnabled: true |
576 | - preferences.appCacheEnabled: true |
577 | - |
578 | // Small shim needed when running as a webapp to wire-up connections |
579 | // with the webview (message received, etc…). |
580 | // This is being called (and expected) internally by the webapps |
581 | |
582 | === modified file 'src/app/webcontainer/WebappContainerWebview.qml' |
583 | --- src/app/webcontainer/WebappContainerWebview.qml 2015-03-25 18:42:20 +0000 |
584 | +++ src/app/webcontainer/WebappContainerWebview.qml 2015-04-30 16:33:24 +0000 |
585 | @@ -40,6 +40,14 @@ |
586 | property bool blockOpenExternalUrls: false |
587 | property bool runningLocalApplication: false |
588 | |
589 | + PopupWindowController { |
590 | + id: popupController |
591 | + objectName: "popupController" |
592 | + webappUrlPatterns: containerWebview.webappUrlPatterns |
593 | + mainWebappView: containerWebview.currentWebview |
594 | + blockOpenExternalUrls: containerWebview.blockOpenExternalUrls |
595 | + } |
596 | + |
597 | Loader { |
598 | id: webappContainerWebViewLoader |
599 | objectName: "containerWebviewLoader" |
600 | @@ -68,7 +76,9 @@ |
601 | , developerExtrasEnabled: containerWebview.developerExtrasEnabled |
602 | , popupRedirectionUrlPrefixPattern: containerWebview.popupRedirectionUrlPrefixPattern |
603 | , blockOpenExternalUrls: containerWebview.blockOpenExternalUrls |
604 | - , runningLocalApplication: containerWebview.runningLocalApplication}) |
605 | + , runningLocalApplication: containerWebview.runningLocalApplication |
606 | + , popupController: popupController |
607 | + , overlayViewsParent: containerWebview.parent}) |
608 | } |
609 | } |
610 | |
611 | |
612 | === modified file 'tests/autopilot/webapp_container/tests/__init__.py' |
613 | --- tests/autopilot/webapp_container/tests/__init__.py 2015-03-20 18:22:41 +0000 |
614 | +++ tests/autopilot/webapp_container/tests/__init__.py 2015-04-30 16:33:24 +0000 |
615 | @@ -83,6 +83,12 @@ |
616 | def get_webview(self): |
617 | return self.app.select_single(objectName="webview") |
618 | |
619 | + def get_popup_overlay_views(self): |
620 | + return self.app.select_many("PopupWindowOverlay") |
621 | + |
622 | + def get_popup_controller(self): |
623 | + return self.app.select_single(objectName="popupController") |
624 | + |
625 | def get_oxide_webview(self): |
626 | container = self.get_webview().select_single( |
627 | objectName='containerWebviewLoader') |
628 | |
629 | === modified file 'tests/autopilot/webapp_container/tests/fake_servers.py' |
630 | --- tests/autopilot/webapp_container/tests/fake_servers.py 2014-11-28 17:42:50 +0000 |
631 | +++ tests/autopilot/webapp_container/tests/fake_servers.py 2015-04-30 16:33:24 +0000 |
632 | @@ -66,22 +66,22 @@ |
633 | </html> |
634 | """ |
635 | |
636 | - def targetted_click_content(self, differentDomain=True): |
637 | - url = 'http://www.test.com/' |
638 | - if differentDomain: |
639 | - url = 'http://www.ubuntu.com/' |
640 | + def targetted_click_content(self): |
641 | return """ |
642 | <html> |
643 | <head> |
644 | <title>Some content</title> |
645 | </head> |
646 | <body> |
647 | -<div><a href='{}' target='_blank'> |
648 | -<div style="height: 100%; width: 100%"></div> |
649 | -</a></div> |
650 | +<div> |
651 | +<a href="/open-close-content" target="_blank"> |
652 | +<div style="height: 100%; width: 100%"> |
653 | +</div> |
654 | +</a> |
655 | +</div> |
656 | </body> |
657 | </html> |
658 | - """.format(url) |
659 | + """ |
660 | |
661 | def display_ua_content(self): |
662 | return """ |
663 | @@ -99,6 +99,27 @@ |
664 | </html> |
665 | """.format("'"+self.headers['user-agent']+"'") |
666 | |
667 | + def open_close_content(self): |
668 | + return """ |
669 | +<html> |
670 | +<head> |
671 | +<title>open-close</title> |
672 | +<script> |
673 | +</script> |
674 | +</head> |
675 | +<body> |
676 | + <a href="/open-close-content" target="_blank"> |
677 | + <div style="height: 50%; width: 100%; background-color: red"> |
678 | + target blank link |
679 | + </div> |
680 | + </a> |
681 | + <div id="lorem" style="height: 50%; width: 100%; background-color: blue"> |
682 | + Lorem ipsum dolor sit amet |
683 | + </div> |
684 | +</body> |
685 | +</html> |
686 | + """ |
687 | + |
688 | def do_GET(self): |
689 | if self.path == '/': |
690 | self.send_response(200) |
691 | @@ -114,13 +135,13 @@ |
692 | self.serve_content(self.external_click_content()) |
693 | elif self.path == '/with-targetted-link': |
694 | self.send_response(200) |
695 | - self.serve_content(self.targetted_click_content(False)) |
696 | - elif self.path == '/with-different-targetted-link': |
697 | - self.send_response(200) |
698 | self.serve_content(self.targetted_click_content()) |
699 | elif self.path == '/show-user-agent': |
700 | self.send_response(200) |
701 | self.serve_content(self.display_ua_content()) |
702 | + elif self.path == '/open-close-content': |
703 | + self.send_response(200) |
704 | + self.serve_content(self.open_close_content()) |
705 | else: |
706 | self.send_error(404) |
707 | |
708 | |
709 | === added file 'tests/autopilot/webapp_container/tests/test_popup_webview_overlay.py' |
710 | --- tests/autopilot/webapp_container/tests/test_popup_webview_overlay.py 1970-01-01 00:00:00 +0000 |
711 | +++ tests/autopilot/webapp_container/tests/test_popup_webview_overlay.py 2015-04-30 16:33:24 +0000 |
712 | @@ -0,0 +1,170 @@ |
713 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
714 | +# Copyright 2015 Canonical |
715 | +# |
716 | +# This program is free software: you can redistribute it and/or modify it |
717 | +# under the terms of the GNU General Public License version 3, as published |
718 | +# by the Free Software Foundation. |
719 | +# |
720 | +# This program is distributed in the hope that it will be useful, |
721 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
722 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
723 | +# GNU General Public License for more details. |
724 | +# |
725 | +# You should have received a copy of the GNU General Public License |
726 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
727 | + |
728 | +from testtools.matchers import Equals, Contains, GreaterThan |
729 | +from autopilot.matchers import Eventually |
730 | + |
731 | +from webapp_container.tests import WebappContainerTestCaseWithLocalContentBase |
732 | + |
733 | + |
734 | +class WebappContainerPopupWebViewOverlayTestCase( |
735 | + WebappContainerTestCaseWithLocalContentBase): |
736 | + |
737 | + def click_href_target_blank(self): |
738 | + webview = self.get_oxide_webview() |
739 | + self.assertThat(webview.url, Contains('/open-close-content')) |
740 | + gr = webview.globalRect |
741 | + self.pointing_device.move( |
742 | + gr.x + gr.width/4, |
743 | + gr.y + gr.height/4) |
744 | + self.pointing_device.click() |
745 | + |
746 | + def click_window_open(self): |
747 | + webview = self.get_oxide_webview() |
748 | + self.assertThat(webview.url.endswith('/open-close-content')) |
749 | + gr = webview.globalRect |
750 | + self.pointing_device.move( |
751 | + gr.x + webview.width*3/4, |
752 | + gr.y + webview.height*3/4) |
753 | + self.pointing_device.click() |
754 | + |
755 | + def test_open_close_back_to_mainview(self): |
756 | + args = [] |
757 | + self.launch_webcontainer_app_with_local_http_server( |
758 | + args, |
759 | + '/open-close-content') |
760 | + self.get_webcontainer_window().visible.wait_for(True) |
761 | + |
762 | + popup_controller = self.get_popup_controller() |
763 | + new_view_watcher = popup_controller.watch_signal( |
764 | + 'newViewCreated(QString)') |
765 | + animation_watcher = popup_controller.watch_signal( |
766 | + 'windowOverlayOpenAnimationDone()') |
767 | + animation_signal_emission = animation_watcher.num_emissions |
768 | + |
769 | + views = self.get_popup_overlay_views() |
770 | + self.assertThat(len(views), Equals(0)) |
771 | + |
772 | + self.click_href_target_blank() |
773 | + |
774 | + self.assertThat( |
775 | + lambda: new_view_watcher.was_emitted, |
776 | + Eventually(Equals(True))) |
777 | + self.assertThat( |
778 | + lambda: len(self.get_popup_overlay_views()), |
779 | + Eventually(Equals(1))) |
780 | + views = self.get_popup_overlay_views() |
781 | + overlay = views[0] |
782 | + self.assertThat( |
783 | + overlay.select_single(objectName="overlayWebview").url, |
784 | + Contains('/open-close-content')) |
785 | + |
786 | + self.assertThat( |
787 | + lambda: animation_watcher.num_emissions, |
788 | + Eventually(GreaterThan(animation_signal_emission))) |
789 | + animation_signal_emission = animation_watcher.num_emissions |
790 | + |
791 | + closeButton = overlay.select_single( |
792 | + objectName='overlayCloseButton') |
793 | + |
794 | + self.pointing_device.click_object(closeButton) |
795 | + |
796 | + self.assertThat( |
797 | + lambda: len(self.get_popup_overlay_views()), |
798 | + Eventually(Equals(0))) |
799 | + |
800 | + def test_open_overlay_in_main_browser(self): |
801 | + args = [] |
802 | + self.launch_webcontainer_app_with_local_http_server( |
803 | + args, |
804 | + '/open-close-content', |
805 | + {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1'}) |
806 | + self.get_webcontainer_window().visible.wait_for(True) |
807 | + |
808 | + popup_controller = self.get_popup_controller() |
809 | + webview = self.get_oxide_webview() |
810 | + self.assertThat( |
811 | + lambda: webview.visible, |
812 | + Eventually(Equals(True))) |
813 | + external_open_watcher = popup_controller.watch_signal( |
814 | + 'openExternalUrlTriggered(QString)') |
815 | + |
816 | + animation_watcher = popup_controller.watch_signal( |
817 | + 'windowOverlayOpenAnimationDone()') |
818 | + animation_signal_emission = animation_watcher.num_emissions |
819 | + |
820 | + self.click_href_target_blank() |
821 | + |
822 | + self.assertThat( |
823 | + lambda: len(self.get_popup_overlay_views()), |
824 | + Eventually(Equals(1))) |
825 | + |
826 | + views = self.get_popup_overlay_views() |
827 | + overlay = views[0] |
828 | + |
829 | + self.assertThat( |
830 | + lambda: animation_watcher.num_emissions, |
831 | + Eventually(GreaterThan(animation_signal_emission))) |
832 | + animation_signal_emission = animation_watcher.num_emissions |
833 | + |
834 | + openInBrowserButton = overlay.select_single( |
835 | + objectName='overlayButtonOpenInBrowser') |
836 | + |
837 | + self.pointing_device.click_object(openInBrowserButton) |
838 | + |
839 | + self.assertThat( |
840 | + lambda: len(self.get_popup_overlay_views()), |
841 | + Eventually(Equals(0))) |
842 | + self.assertThat( |
843 | + lambda: external_open_watcher.was_emitted, |
844 | + Eventually(Equals(True))) |
845 | + self.assertThat( |
846 | + lambda: webview.visible, |
847 | + Eventually(Equals(True))) |
848 | + |
849 | + def test_max_overlay_count_reached(self): |
850 | + args = [] |
851 | + self.launch_webcontainer_app_with_local_http_server( |
852 | + args, |
853 | + '/open-close-content', |
854 | + {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1'}) |
855 | + self.get_webcontainer_window().visible.wait_for(True) |
856 | + |
857 | + popup_controller = self.get_popup_controller() |
858 | + webview = self.get_oxide_webview() |
859 | + self.assertThat( |
860 | + lambda: webview.visible, |
861 | + Eventually(Equals(True))) |
862 | + |
863 | + animation_watcher = popup_controller.watch_signal( |
864 | + 'windowOverlayOpenAnimationDone()') |
865 | + animation_signal_emission = animation_watcher.num_emissions |
866 | + |
867 | + OVERLAY_MAX_COUNT = 3 |
868 | + for i in range(0, OVERLAY_MAX_COUNT): |
869 | + self.click_href_target_blank() |
870 | + self.assertThat( |
871 | + lambda: animation_watcher.num_emissions, |
872 | + Eventually(GreaterThan(animation_signal_emission))) |
873 | + animation_signal_emission = animation_watcher.num_emissions |
874 | + |
875 | + external_open_watcher = popup_controller.watch_signal( |
876 | + 'openExternalUrlTriggered(QString)') |
877 | + |
878 | + self.click_href_target_blank() |
879 | + |
880 | + self.assertThat( |
881 | + lambda: external_open_watcher.was_emitted, |
882 | + Eventually(Equals(True))) |
883 | |
884 | === removed file 'tests/autopilot/webapp_container/tests/test_redirection_pattern.py' |
885 | --- tests/autopilot/webapp_container/tests/test_redirection_pattern.py 2014-10-07 16:16:13 +0000 |
886 | +++ tests/autopilot/webapp_container/tests/test_redirection_pattern.py 1970-01-01 00:00:00 +0000 |
887 | @@ -1,59 +0,0 @@ |
888 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
889 | -# Copyright 2014 Canonical |
890 | -# |
891 | -# This program is free software: you can redistribute it and/or modify it |
892 | -# under the terms of the GNU General Public License version 3, as published |
893 | -# by the Free Software Foundation. |
894 | -# |
895 | -# This program is distributed in the hope that it will be useful, |
896 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
897 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
898 | -# GNU General Public License for more details. |
899 | -# |
900 | -# You should have received a copy of the GNU General Public License |
901 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
902 | - |
903 | -from testtools.matchers import Equals |
904 | -from autopilot.matchers import Eventually |
905 | - |
906 | -from webapp_container.tests import WebappContainerTestCaseWithLocalContentBase |
907 | - |
908 | - |
909 | -class WebappContainerRedirectionPatternTestCase( |
910 | - WebappContainerTestCaseWithLocalContentBase): |
911 | - |
912 | - def test_browse_to_redirection_pattern_url(self): |
913 | - REDIRECTION_HOSTNAME = self.get_base_url_hostname() |
914 | - args = ["--popup-redirection-url-prefix={}{}{}".format( |
915 | - 'http://', REDIRECTION_HOSTNAME.replace('.', '\.'), |
916 | - '/redirect\\?url=([^&]*).*')] |
917 | - self.launch_webcontainer_app_with_local_http_server( |
918 | - args, |
919 | - '/get-redirect', |
920 | - {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1', |
921 | - 'WEBAPP_CONTAINER_DO_NOT_FILTER_PATTERN_URL': '1'}) |
922 | - self.get_webcontainer_window().visible.wait_for(True) |
923 | - |
924 | - webview = self.get_oxide_webview() |
925 | - external_open_watcher = webview.watch_signal( |
926 | - 'openExternalUrlTriggered(QString)') |
927 | - got_redirection_url_watcher = webview.watch_signal( |
928 | - 'gotRedirectionUrl(QString)') |
929 | - |
930 | - self.assertThat(external_open_watcher.was_emitted, Equals(False)) |
931 | - self.assertThat(got_redirection_url_watcher.was_emitted, Equals(False)) |
932 | - self.browse_to( |
933 | - "http://{}/get-redirect".format(REDIRECTION_HOSTNAME)) |
934 | - |
935 | - self.pointing_device.click_object(webview) |
936 | - |
937 | - self.assertThat( |
938 | - lambda: got_redirection_url_watcher.was_emitted, |
939 | - Eventually(Equals(True))) |
940 | - self.assertThat( |
941 | - webview.get_signal_emissions( |
942 | - 'gotRedirectionUrl(QString)')[0][0], |
943 | - Equals('myredirect')) |
944 | - self.assertThat( |
945 | - lambda: external_open_watcher.was_emitted, |
946 | - Eventually(Equals(True))) |
947 | |
948 | === modified file 'tests/autopilot/webapp_container/tests/test_url_patterns.py' |
949 | --- tests/autopilot/webapp_container/tests/test_url_patterns.py 2015-02-18 11:05:35 +0000 |
950 | +++ tests/autopilot/webapp_container/tests/test_url_patterns.py 2015-04-30 16:33:24 +0000 |
951 | @@ -43,55 +43,3 @@ |
952 | self.assertThat( |
953 | lambda: external_open_watcher.was_emitted, |
954 | Eventually(Equals(True))) |
955 | - |
956 | - def test_pattern_with_allowed_targetted_url(self): |
957 | - args = ["--webappUrlPatterns=http://www.test.com/*"] |
958 | - rule = 'MAP *.test.com:80 ' + self.get_base_url_hostname() |
959 | - self.launch_webcontainer_app_with_local_http_server( |
960 | - args, |
961 | - '', |
962 | - {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1', |
963 | - 'UBUNTU_WEBVIEW_HOST_MAPPING_RULES': rule}, |
964 | - "http://www.test.com/with-targetted-link") |
965 | - |
966 | - self.get_webcontainer_window().visible.wait_for(True) |
967 | - |
968 | - webview = self.get_oxide_webview() |
969 | - external_open_watcher = webview.watch_signal( |
970 | - 'openExternalUrlTriggered(QString)') |
971 | - |
972 | - self.pointing_device.click_object(webview) |
973 | - |
974 | - self.assertThat( |
975 | - webview.url, |
976 | - Eventually(Equals("http://www.test.com/"))) |
977 | - |
978 | - self.assertThat( |
979 | - external_open_watcher.was_emitted, |
980 | - Equals(False)) |
981 | - |
982 | - def test_pattern_with_different_targetted_url(self): |
983 | - args = ["--webappUrlPatterns=http://www.test.com/*"] |
984 | - rule = 'MAP *.test.com:80 ' + self.get_base_url_hostname() |
985 | - self.launch_webcontainer_app_with_local_http_server( |
986 | - args, |
987 | - '', |
988 | - {'WEBAPP_CONTAINER_BLOCK_OPEN_URL_EXTERNALLY': '1', |
989 | - 'UBUNTU_WEBVIEW_HOST_MAPPING_RULES': rule}, |
990 | - "http://www.test.com/with-different-targetted-link") |
991 | - |
992 | - self.get_webcontainer_window().visible.wait_for(True) |
993 | - |
994 | - webview = self.get_oxide_webview() |
995 | - external_open_watcher = webview.watch_signal( |
996 | - 'openExternalUrlTriggered(QString)') |
997 | - |
998 | - self.pointing_device.click_object(webview) |
999 | - |
1000 | - self.assertThat( |
1001 | - webview.url, |
1002 | - Equals("http://www.test.com/with-different-targetted-link")) |
1003 | - |
1004 | - self.assertThat( |
1005 | - lambda: external_open_watcher.was_emitted, |
1006 | - Eventually(Equals(True))) |
FAILED: Continuous integration, rev:943 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 1552/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 1930/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- amd64-ci/ 310/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 310/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- i386-ci/ 310/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 1928/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 1552/rebuild
http://