Merge lp:~osomon/webbrowser-app/with-oxide into lp:webbrowser-app
- with-oxide
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 473 | ||||||||
Proposed branch: | lp:~osomon/webbrowser-app/with-oxide | ||||||||
Merge into: | lp:webbrowser-app | ||||||||
Diff against target: |
3771 lines (+1789/-1133) 50 files modified
CMakeLists.txt (+1/-0) debian/control (+5/-2) po/webbrowser-app.pot (+93/-67) src/Ubuntu/Components/Extras/Browser/CMakeLists.txt (+1/-1) src/Ubuntu/Components/Extras/Browser/ItemSelector01.qml (+63/-0) src/Ubuntu/Components/Extras/Browser/ItemSelector02.qml (+5/-2) src/Ubuntu/Components/Extras/Browser/UbuntuWebContext.qml (+58/-0) src/Ubuntu/Components/Extras/Browser/UbuntuWebView01.qml (+272/-0) src/Ubuntu/Components/Extras/Browser/UbuntuWebView02.qml (+86/-50) src/Ubuntu/Components/Extras/Browser/UserAgent01.qml (+90/-0) src/Ubuntu/Components/Extras/Browser/UserAgent02.qml (+34/-62) src/Ubuntu/Components/Extras/Browser/dummysingleton.qml (+27/-0) src/Ubuntu/Components/Extras/Browser/plugin.cpp (+34/-0) src/Ubuntu/Components/Extras/Browser/qmldir (+5/-1) src/Ubuntu/Components/Extras/Browser/selection01.js (+193/-0) src/Ubuntu/Components/Extras/Browser/selection02.js (+128/-174) src/Ubuntu/Components/Extras/Browser/ua-override-worker.js (+46/-0) src/app/AlertDialog.qml (+2/-2) src/app/BeforeUnloadDialog.qml (+38/-0) src/app/CMakeLists.txt (+2/-0) src/app/PanelLoader.qml (+4/-1) src/app/PromptDialog.qml (+7/-1) src/app/WebViewImpl.qml (+14/-18) src/app/browserapplication.cpp (+29/-2) src/app/browserapplication.h (+3/-3) src/app/webbrowser/BookmarksView.qml (+2/-2) src/app/webbrowser/Browser.qml (+4/-22) src/app/webbrowser/CMakeLists.txt (+1/-13) src/app/webbrowser/TabsList.qml (+1/-1) src/app/webbrowser/TimelineView.qml (+5/-5) src/app/webbrowser/webbrowser-app.cpp (+4/-28) src/app/webbrowser/webbrowser-app.h (+0/-5) src/app/webbrowser/webthumbnail-provider.cpp (+0/-53) src/app/webbrowser/webthumbnail-provider.h (+0/-39) src/app/webbrowser/webthumbnail-utils.cpp (+0/-108) src/app/webbrowser/webthumbnail-utils.h (+0/-51) src/app/webbrowser/webview-thumbnailer.cpp (+0/-162) src/app/webbrowser/webview-thumbnailer.h (+0/-64) src/app/webcontainer/WebApp.qml (+18/-103) src/app/webcontainer/WebViewImplWebkit.qml (+159/-0) src/app/webcontainer/WebappContainerWebview.qml (+151/-0) src/app/webcontainer/webapp-container.cpp (+56/-0) src/app/webcontainer/webapp-container.h (+1/-0) src/app/webcontainer/webapp-container.qml (+1/-0) tests/autopilot/webbrowser_app/tests/test_tabs.py (+5/-0) tests/unittests/qml/CMakeLists.txt (+10/-3) tests/unittests/qml/tst_UbuntuWebView01.qml (+46/-0) tests/unittests/qml/tst_UbuntuWebView02.qml (+3/-6) tests/unittests/qml/tst_UserAgent.qml (+0/-82) tests/unittests/qml/tst_UserAgent01.qml (+82/-0) |
||||||||
To merge this branch: | bzr merge lp:~osomon/webbrowser-app/with-oxide | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+213256@code.launchpad.net |
Commit message
Land the master Oxide support branch. See individual revisions for details.
Description of the change
Land the master Oxide support branch. See individual revisions for details.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 492. By Alexandre Abreu
-
Make the webapp-container adaptable to the runtime context (oxide or not) and instanciate the proper web backend.
To account for the multiple potential frameworks (13.10, and soon 14.04) and avoid
1. user having their webapps not working anymore,
2. asking user to update their click package,
a bit of runtime behavior has been added (ack'd by Jamie Strandboge) to validate the presence of oxide. - 493. By Olivier Tilloy
-
Clean up changelog.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:492
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:493
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-10-09 08:32:01 +0000 |
3 | +++ CMakeLists.txt 2014-03-28 17:03:06 +0000 |
4 | @@ -29,6 +29,7 @@ |
5 | endif() |
6 | |
7 | find_package(Qt5Core REQUIRED) |
8 | +find_package(Qt5Gui REQUIRED) |
9 | find_package(Qt5Sql REQUIRED) |
10 | find_package(Qt5Widgets REQUIRED) |
11 | find_package(Qt5Quick REQUIRED) |
12 | |
13 | === modified file 'debian/control' |
14 | --- debian/control 2014-03-17 16:05:04 +0000 |
15 | +++ debian/control 2014-03-28 17:03:06 +0000 |
16 | @@ -8,8 +8,8 @@ |
17 | hardening-wrapper, |
18 | python, |
19 | libqt5sql5-sqlite, |
20 | - libqt5webkit5-dev, |
21 | libqt5webkit5-qmlwebkitplugin, |
22 | + liboxideqt-qmlplugin, |
23 | qt5-default, |
24 | qt5-qmake, |
25 | qtbase5-dev, |
26 | @@ -19,6 +19,7 @@ |
27 | qtdeclarative5-qtquick2-plugin, |
28 | qtdeclarative5-test-plugin, |
29 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
30 | + xvfb, |
31 | Standards-Version: 3.9.4 |
32 | Homepage: https://launchpad.net/webbrowser-app |
33 | # If you aren't a member of ~phablet-team but need to upload packaging changes, |
34 | @@ -30,7 +31,7 @@ |
35 | Multi-Arch: foreign |
36 | Depends: ${misc:Depends}, |
37 | ${shlibs:Depends}, |
38 | - libqt5webkit5-qmlwebkitplugin, |
39 | + liboxideqt-qmlplugin, |
40 | qtdeclarative5-qtquick2-plugin, |
41 | qtdeclarative5-ubuntu-ui-extras-browser-plugin (= ${binary:Version}), |
42 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
43 | @@ -50,6 +51,7 @@ |
44 | Depends: ${misc:Depends}, |
45 | ${shlibs:Depends}, |
46 | unity-webapps-qml, |
47 | + libqt5webkit5-qmlwebkitplugin, |
48 | webbrowser-app (= ${binary:Version}), |
49 | Description: Ubuntu web applications container |
50 | A lightweight webapps container tailored for Ubuntu, based on the Webkit |
51 | @@ -62,6 +64,7 @@ |
52 | ${shlibs:Depends}, |
53 | libqt5sql5-sqlite, |
54 | libqt5webkit5-qmlwebkitplugin, |
55 | + liboxideqt-qmlplugin, |
56 | qtdeclarative5-qtquick2-plugin, |
57 | qtdeclarative5-ubuntu-ui-extras-browser-plugin-assets (>= ${source:Version}), |
58 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
59 | |
60 | === modified file 'po/webbrowser-app.pot' |
61 | --- po/webbrowser-app.pot 2013-11-13 08:11:24 +0000 |
62 | +++ po/webbrowser-app.pot 2014-03-28 17:03:06 +0000 |
63 | @@ -8,7 +8,7 @@ |
64 | msgstr "" |
65 | "Project-Id-Version: webbrowser-app\n" |
66 | "Report-Msgid-Bugs-To: \n" |
67 | -"POT-Creation-Date: 2013-11-13 09:10+0100\n" |
68 | +"POT-Creation-Date: 2014-03-26 10:59+0100\n" |
69 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
70 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
71 | "Language-Team: LANGUAGE <LL@li.org>\n" |
72 | @@ -17,14 +17,6 @@ |
73 | "Content-Type: text/plain; charset=UTF-8\n" |
74 | "Content-Transfer-Encoding: 8bit\n" |
75 | |
76 | -#: src/app/ActivityView.qml:36 src/app/Chrome.qml:127 |
77 | -msgid "Activity" |
78 | -msgstr "" |
79 | - |
80 | -#: src/app/ActivityView.qml:54 |
81 | -msgid "Bookmarks" |
82 | -msgstr "" |
83 | - |
84 | #: src/app/AlertDialog.qml:24 |
85 | msgid "JavaScript Alert" |
86 | msgstr "" |
87 | @@ -57,6 +49,18 @@ |
88 | msgid "Cancel" |
89 | msgstr "" |
90 | |
91 | +#: src/app/BeforeUnloadDialog.qml:24 |
92 | +msgid "Confirm Navigation" |
93 | +msgstr "" |
94 | + |
95 | +#: src/app/BeforeUnloadDialog.qml:28 |
96 | +msgid "Leave" |
97 | +msgstr "" |
98 | + |
99 | +#: src/app/BeforeUnloadDialog.qml:33 |
100 | +msgid "Stay" |
101 | +msgstr "" |
102 | + |
103 | #: src/app/CertificateVerificationDialog.qml:24 |
104 | msgid "This connection is untrusted" |
105 | msgstr "" |
106 | @@ -85,6 +89,10 @@ |
107 | msgid "Forward" |
108 | msgstr "" |
109 | |
110 | +#: src/app/Chrome.qml:127 src/app/webbrowser/ActivityView.qml:36 |
111 | +msgid "Activity" |
112 | +msgstr "" |
113 | + |
114 | #: src/app/ConfirmDialog.qml:24 |
115 | msgid "JavaScript Confirmation" |
116 | msgstr "" |
117 | @@ -134,52 +142,6 @@ |
118 | msgid "The website %1:%2 requires authentication." |
119 | msgstr "" |
120 | |
121 | -#. TRANSLATORS: %1 refers to the number of open tabs |
122 | -#: src/app/TabsList.qml:37 |
123 | -#, qt-format |
124 | -msgid "Currently viewing (%1)" |
125 | -msgstr "" |
126 | - |
127 | -#: src/app/TabsList.qml:68 |
128 | -msgid "+" |
129 | -msgstr "" |
130 | - |
131 | -#: src/app/TimelineView.qml:83 |
132 | -msgid "Today" |
133 | -msgstr "" |
134 | - |
135 | -#: src/app/TimelineView.qml:85 |
136 | -msgid "Yesterday" |
137 | -msgstr "" |
138 | - |
139 | -#: src/app/TimelineView.qml:87 |
140 | -msgid "Last 7 Days" |
141 | -msgstr "" |
142 | - |
143 | -#: src/app/TimelineView.qml:89 |
144 | -msgid "This Month" |
145 | -msgstr "" |
146 | - |
147 | -#: src/app/TimelineView.qml:91 |
148 | -msgid "This Year" |
149 | -msgstr "" |
150 | - |
151 | -#: src/app/TimelineView.qml:93 |
152 | -msgid "Older" |
153 | -msgstr "" |
154 | - |
155 | -#: src/app/TimelineView.qml:276 |
156 | -msgid "(local files)" |
157 | -msgstr "" |
158 | - |
159 | -#: src/app/TimelineView.qml:278 |
160 | -msgid "(other)" |
161 | -msgstr "" |
162 | - |
163 | -#: src/app/WebViewImpl.qml:52 |
164 | -msgid "This page wants to know your device’s location." |
165 | -msgstr "" |
166 | - |
167 | #. TRANSLATORS: This is a free-form list of keywords associated to the 'Back' action. |
168 | #. Keywords may actually be sentences, and must be separated by semi-colons. |
169 | #: src/app/actions/Back.qml:26 |
170 | @@ -266,24 +228,88 @@ |
171 | msgid "Leave Page" |
172 | msgstr "" |
173 | |
174 | +#: src/app/webbrowser/ActivityView.qml:54 |
175 | +msgid "Bookmarks" |
176 | +msgstr "" |
177 | + |
178 | +#. TRANSLATORS: %1 refers to the number of open tabs |
179 | +#: src/app/webbrowser/TabsList.qml:37 |
180 | +#, qt-format |
181 | +msgid "Currently viewing (%1)" |
182 | +msgstr "" |
183 | + |
184 | +#: src/app/webbrowser/TabsList.qml:68 |
185 | +msgid "+" |
186 | +msgstr "" |
187 | + |
188 | +#: src/app/webbrowser/TimelineView.qml:84 |
189 | +msgid "Today" |
190 | +msgstr "" |
191 | + |
192 | +#: src/app/webbrowser/TimelineView.qml:86 |
193 | +msgid "Yesterday" |
194 | +msgstr "" |
195 | + |
196 | +#: src/app/webbrowser/TimelineView.qml:88 |
197 | +msgid "Last 7 Days" |
198 | +msgstr "" |
199 | + |
200 | +#: src/app/webbrowser/TimelineView.qml:90 |
201 | +msgid "This Month" |
202 | +msgstr "" |
203 | + |
204 | +#: src/app/webbrowser/TimelineView.qml:92 |
205 | +msgid "This Year" |
206 | +msgstr "" |
207 | + |
208 | +#: src/app/webbrowser/TimelineView.qml:94 |
209 | +msgid "Older" |
210 | +msgstr "" |
211 | + |
212 | +#: src/app/webbrowser/TimelineView.qml:277 |
213 | +msgid "(local files)" |
214 | +msgstr "" |
215 | + |
216 | +#: src/app/webbrowser/TimelineView.qml:279 |
217 | +msgid "(other)" |
218 | +msgstr "" |
219 | + |
220 | +#: src/app/webbrowser/webbrowser-app.desktop.in:3 |
221 | +msgid "Browser" |
222 | +msgstr "" |
223 | + |
224 | +#: src/app/webbrowser/webbrowser-app.desktop.in:4 |
225 | +msgid "Web Browser" |
226 | +msgstr "" |
227 | + |
228 | +#: src/app/webbrowser/webbrowser-app.desktop.in:5 |
229 | +msgid "Browse the World Wide Web" |
230 | +msgstr "" |
231 | + |
232 | #. TRANSLATORS: %1 refers to the current page’s title |
233 | -#: src/app/webapp-container.qml:44 src/app/webbrowser-app.qml:35 |
234 | +#: src/app/webbrowser/webbrowser-app.qml:35 |
235 | +#: src/app/webcontainer/webapp-container.qml:44 |
236 | #, qt-format |
237 | msgid "%1 - Ubuntu Web Browser" |
238 | msgstr "" |
239 | |
240 | -#: src/app/webapp-container.qml:46 src/app/webbrowser-app.qml:37 |
241 | +#: src/app/webbrowser/webbrowser-app.qml:37 |
242 | +#: src/app/webcontainer/webapp-container.qml:46 |
243 | msgid "Ubuntu Web Browser" |
244 | msgstr "" |
245 | |
246 | -#: src/app/webbrowser-app.desktop.in:3 |
247 | -msgid "Browser" |
248 | -msgstr "" |
249 | - |
250 | -#: src/app/webbrowser-app.desktop.in:4 |
251 | -msgid "Web Browser" |
252 | -msgstr "" |
253 | - |
254 | -#: src/app/webbrowser-app.desktop.in:5 |
255 | -msgid "Browse the World Wide Web" |
256 | +#: src/app/webcontainer/AccountsLoginPage.qml:70 |
257 | +msgid "No local account found for " |
258 | +msgstr "" |
259 | + |
260 | +#: src/app/webcontainer/AccountsLoginPage.qml:75 |
261 | +msgid "Skip account creation step" |
262 | +msgstr "" |
263 | + |
264 | +#: src/app/webcontainer/AccountsLoginPage.qml:124 |
265 | +msgid "Add account" |
266 | +msgstr "" |
267 | + |
268 | +#: src/app/webcontainer/AccountsView.qml:38 |
269 | +msgid "Select an account" |
270 | msgstr "" |
271 | |
272 | === modified file 'src/Ubuntu/Components/Extras/Browser/CMakeLists.txt' |
273 | --- src/Ubuntu/Components/Extras/Browser/CMakeLists.txt 2014-03-13 07:33:10 +0000 |
274 | +++ src/Ubuntu/Components/Extras/Browser/CMakeLists.txt 2014-03-28 17:03:06 +0000 |
275 | @@ -13,7 +13,7 @@ |
276 | |
277 | add_library(${PLUGIN} MODULE ${PLUGIN_SRC}) |
278 | |
279 | -qt5_use_modules(${PLUGIN} Core Qml) |
280 | +qt5_use_modules(${PLUGIN} Core Gui Qml) |
281 | |
282 | file(GLOB QML_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.qml qmldir *.js) |
283 | install(TARGETS ${PLUGIN} DESTINATION ${WEBBROWSER_IMPORTS_DIR}) |
284 | |
285 | === added file 'src/Ubuntu/Components/Extras/Browser/ItemSelector01.qml' |
286 | --- src/Ubuntu/Components/Extras/Browser/ItemSelector01.qml 1970-01-01 00:00:00 +0000 |
287 | +++ src/Ubuntu/Components/Extras/Browser/ItemSelector01.qml 2014-03-28 17:03:06 +0000 |
288 | @@ -0,0 +1,63 @@ |
289 | +/* |
290 | + * Copyright 2013 Canonical Ltd. |
291 | + * |
292 | + * This file is part of webbrowser-app. |
293 | + * |
294 | + * webbrowser-app is free software; you can redistribute it and/or modify |
295 | + * it under the terms of the GNU General Public License as published by |
296 | + * the Free Software Foundation; version 3. |
297 | + * |
298 | + * webbrowser-app is distributed in the hope that it will be useful, |
299 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
300 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
301 | + * GNU General Public License for more details. |
302 | + * |
303 | + * You should have received a copy of the GNU General Public License |
304 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
305 | + */ |
306 | + |
307 | +import QtQuick 2.0 |
308 | +import Ubuntu.Components 0.1 |
309 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
310 | +import Ubuntu.Components.Popups 0.1 |
311 | + |
312 | +Popover { |
313 | + id: itemSelector |
314 | + |
315 | + property QtObject selectorModel: model |
316 | + |
317 | + caller: parent |
318 | + contentWidth: Math.min(parent.width - units.gu(10), units.gu(40)) |
319 | + property real listContentHeight: 0 // intermediate property to avoid binding loop |
320 | + contentHeight: Math.min(parent.height - units.gu(10), listContentHeight) |
321 | + |
322 | + ListView { |
323 | + clip: true |
324 | + width: itemSelector.contentWidth |
325 | + height: itemSelector.contentHeight |
326 | + |
327 | + model: selectorModel.items |
328 | + |
329 | + delegate: ListItem.Standard { |
330 | + text: model.text |
331 | + enabled: model.enabled |
332 | + selected: model.selected |
333 | + onClicked: selectorModel.accept(model.index) |
334 | + } |
335 | + |
336 | + section.property: "group" |
337 | + section.delegate: ListItem.Header { |
338 | + text: section |
339 | + } |
340 | + |
341 | + onContentHeightChanged: itemSelector.listContentHeight = contentHeight |
342 | + } |
343 | + |
344 | + Component.onCompleted: show() |
345 | + |
346 | + onVisibleChanged: { |
347 | + if (!visible) { |
348 | + selectorModel.reject() |
349 | + } |
350 | + } |
351 | +} |
352 | |
353 | === renamed file 'src/Ubuntu/Components/Extras/Browser/ItemSelector.qml' => 'src/Ubuntu/Components/Extras/Browser/ItemSelector02.qml' |
354 | --- src/Ubuntu/Components/Extras/Browser/ItemSelector.qml 2013-03-21 16:44:04 +0000 |
355 | +++ src/Ubuntu/Components/Extras/Browser/ItemSelector02.qml 2014-03-28 17:03:06 +0000 |
356 | @@ -42,7 +42,10 @@ |
357 | text: model.text |
358 | enabled: model.enabled |
359 | selected: model.selected |
360 | - onClicked: selectorModel.accept(model.index) |
361 | + onClicked: { |
362 | + selectorModel.items.select(model.index) |
363 | + selectorModel.accept() |
364 | + } |
365 | } |
366 | |
367 | section.property: "group" |
368 | @@ -57,7 +60,7 @@ |
369 | |
370 | onVisibleChanged: { |
371 | if (!visible) { |
372 | - selectorModel.reject() |
373 | + selectorModel.cancel() |
374 | } |
375 | } |
376 | } |
377 | |
378 | === added file 'src/Ubuntu/Components/Extras/Browser/UbuntuWebContext.qml' |
379 | --- src/Ubuntu/Components/Extras/Browser/UbuntuWebContext.qml 1970-01-01 00:00:00 +0000 |
380 | +++ src/Ubuntu/Components/Extras/Browser/UbuntuWebContext.qml 2014-03-28 17:03:06 +0000 |
381 | @@ -0,0 +1,58 @@ |
382 | +/* |
383 | + * Copyright 2014 Canonical Ltd. |
384 | + * |
385 | + * This file is part of webbrowser-app. |
386 | + * |
387 | + * webbrowser-app is free software; you can redistribute it and/or modify |
388 | + * it under the terms of the GNU General Public License as published by |
389 | + * the Free Software Foundation; version 3. |
390 | + * |
391 | + * webbrowser-app is distributed in the hope that it will be useful, |
392 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
393 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
394 | + * GNU General Public License for more details. |
395 | + * |
396 | + * You should have received a copy of the GNU General Public License |
397 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
398 | + */ |
399 | + |
400 | +pragma Singleton |
401 | + |
402 | +import QtQuick 2.0 |
403 | +import com.canonical.Oxide 0.1 |
404 | + |
405 | +Item { |
406 | + property string customUA: userAgent.defaultUA |
407 | + |
408 | + property QtObject sharedContext: WebContext { |
409 | + dataPath: dataLocation |
410 | + userAgent: customUA |
411 | + networkRequestDelegate: uaOverrideWorker.item |
412 | + userAgentOverrideDelegate: networkRequestDelegate |
413 | + userScripts: [ |
414 | + UserScript { |
415 | + context: "oxide://selection/" |
416 | + url: Qt.resolvedUrl("selection02.js") |
417 | + incognitoEnabled: true |
418 | + matchAllFrames: true |
419 | + } |
420 | + ] |
421 | + } |
422 | + |
423 | + Component { |
424 | + id: uaOverrideWorkerComponent |
425 | + |
426 | + WebContextDelegateWorker { |
427 | + source: Qt.resolvedUrl("ua-override-worker.js") |
428 | + onMessage: console.log("Overriden UA for", message.url, ":", message.override) |
429 | + } |
430 | + } |
431 | + Loader { |
432 | + id: uaOverrideWorker |
433 | + sourceComponent: (formFactor === "mobile") ? uaOverrideWorkerComponent : undefined |
434 | + } |
435 | + |
436 | + UserAgent02 { |
437 | + id: userAgent |
438 | + } |
439 | +} |
440 | |
441 | === added file 'src/Ubuntu/Components/Extras/Browser/UbuntuWebView01.qml' |
442 | --- src/Ubuntu/Components/Extras/Browser/UbuntuWebView01.qml 1970-01-01 00:00:00 +0000 |
443 | +++ src/Ubuntu/Components/Extras/Browser/UbuntuWebView01.qml 2014-03-28 17:03:06 +0000 |
444 | @@ -0,0 +1,272 @@ |
445 | +/* |
446 | + * Copyright 2013 Canonical Ltd. |
447 | + * |
448 | + * This file is part of webbrowser-app. |
449 | + * |
450 | + * webbrowser-app is free software; you can redistribute it and/or modify |
451 | + * it under the terms of the GNU General Public License as published by |
452 | + * the Free Software Foundation; version 3. |
453 | + * |
454 | + * webbrowser-app is distributed in the hope that it will be useful, |
455 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
456 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
457 | + * GNU General Public License for more details. |
458 | + * |
459 | + * You should have received a copy of the GNU General Public License |
460 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
461 | + */ |
462 | + |
463 | +import QtQuick 2.0 |
464 | +import QtWebKit 3.1 |
465 | +import QtWebKit.experimental 1.0 |
466 | +import Ubuntu.Components 0.1 |
467 | +import Ubuntu.Components.Extras.Browser 0.1 |
468 | +import Ubuntu.Components.Popups 0.1 |
469 | + |
470 | +/*! |
471 | + \qmltype MainView |
472 | + \inqmlmodule Ubuntu.Components.Extras.Browser 0.1 |
473 | + \obsolete |
474 | + \brief Custom Ubuntu WebView extending QtWebKit’s WebView |
475 | + |
476 | + This version of UbuntuWebView is deprecated and shouldn’t be used in new |
477 | + code. Use version 0.2 or higher instead. |
478 | +*/ |
479 | +WebView { |
480 | + id: _webview |
481 | + |
482 | + signal newTabRequested(url url) |
483 | + |
484 | + QtObject { |
485 | + property real devicePixelRatio: QtWebKitDPR |
486 | + onDevicePixelRatioChanged: { |
487 | + // Do not make this patch to QtWebKit a hard requirement. |
488 | + if (_webview.experimental.hasOwnProperty('devicePixelRatio')) { |
489 | + _webview.experimental.devicePixelRatio = devicePixelRatio |
490 | + } |
491 | + } |
492 | + } |
493 | + |
494 | + interactive: !selection.visible |
495 | + maximumFlickVelocity: height * 5 |
496 | + |
497 | + /** |
498 | + * Client overridable function called before the default treatment of a |
499 | + * valid navigation request. This function can stop the navigation request |
500 | + * if it sets the 'action' field of the request to IgnoreRequest. |
501 | + * |
502 | + */ |
503 | + function navigationRequestedDelegate(request) { } |
504 | + |
505 | + UserAgent01 { |
506 | + id: userAgent |
507 | + } |
508 | + |
509 | + /** |
510 | + * This function can be overridden by client applications that embed an |
511 | + * UbuntuWebView to provide a static overridden UA string. |
512 | + * If not overridden, the default UA string and the default override |
513 | + * mechanism will be used. |
514 | + */ |
515 | + function getUAString() { |
516 | + // Note that this function used to accept a 'url' parameter to allow |
517 | + // embedders to implement a custom override mechanism. It was removed |
518 | + // after observing that no application was using it, and to simplify |
519 | + // the API. Embedders willing to provide a custom override mechanism |
520 | + // can always override (at their own risk) the onNavigationRequested |
521 | + // slot. |
522 | + return undefined |
523 | + } |
524 | + experimental.userAgent: (_webview.getUAString() === undefined) ? userAgent.defaultUA : _webview.getUAString() |
525 | + onNavigationRequested: { |
526 | + request.action = WebView.AcceptRequest; |
527 | + |
528 | + navigationRequestedDelegate (request); |
529 | + if (request.action === WebView.IgnoreRequest) |
530 | + return; |
531 | + |
532 | + var staticUA = _webview.getUAString() |
533 | + if (staticUA === undefined) { |
534 | + _webview.experimental.userAgent = userAgent.getUAString(request.url) |
535 | + } else { |
536 | + _webview.experimental.userAgent = staticUA |
537 | + } |
538 | + } |
539 | + |
540 | + experimental.preferences.navigatorQtObjectEnabled: true |
541 | + experimental.userScripts: [Qt.resolvedUrl("hyperlinks.js"), |
542 | + Qt.resolvedUrl("selection01.js")] |
543 | + experimental.onMessageReceived: { |
544 | + var data = null |
545 | + try { |
546 | + data = JSON.parse(message.data) |
547 | + } catch (error) { |
548 | + console.debug('DEBUG:', message.data) |
549 | + return |
550 | + } |
551 | + if ('event' in data) { |
552 | + if (data.event === 'longpress') { |
553 | + if (('img' in data) || ('href' in data)) { |
554 | + contextualData.clear() |
555 | + if ('img' in data) { |
556 | + contextualData.img = data.img |
557 | + } |
558 | + if ('href' in data) { |
559 | + contextualData.href = data.href |
560 | + contextualData.title = data.title |
561 | + } |
562 | + contextualRectangle.position(data) |
563 | + PopupUtils.open(contextualPopover, contextualRectangle) |
564 | + return |
565 | + } |
566 | + } |
567 | + if ((data.event === 'longpress') || (data.event === 'selectionadjusted')) { |
568 | + selection.clearData() |
569 | + selection.createData() |
570 | + if ('html' in data) { |
571 | + selection.mimedata.html = data.html |
572 | + } |
573 | + // FIXME: push the text and image data in the order |
574 | + // they appear in the selected block. |
575 | + if ('text' in data) { |
576 | + selection.mimedata.text = data.text |
577 | + } |
578 | + if ('images' in data) { |
579 | + // TODO: download and cache the images locally |
580 | + // (grab them from the webview’s cache, if possible), |
581 | + // and forward local URLs. |
582 | + selection.mimedata.urls = data.images |
583 | + } |
584 | + selection.show(data.left, data.top, data.width, data.height) |
585 | + } else if (data.event === 'newtab') { |
586 | + newTabRequested(data.url) |
587 | + } |
588 | + } |
589 | + } |
590 | + |
591 | + experimental.itemSelector: ItemSelector01 {} |
592 | + |
593 | + property alias selection: selection |
594 | + property ActionList selectionActions |
595 | + Selection { |
596 | + id: selection |
597 | + |
598 | + anchors.fill: parent |
599 | + visible: false |
600 | + |
601 | + property Item __popover: null |
602 | + property var mimedata: null |
603 | + |
604 | + Component { |
605 | + id: selectionPopover |
606 | + ActionSelectionPopover { |
607 | + grabDismissAreaEvents: false |
608 | + actions: selectionActions |
609 | + } |
610 | + } |
611 | + |
612 | + function createData() { |
613 | + if (mimedata === null) { |
614 | + mimedata = Clipboard.newData() |
615 | + } |
616 | + } |
617 | + |
618 | + function clearData() { |
619 | + if (mimedata !== null) { |
620 | + delete mimedata |
621 | + mimedata = null |
622 | + } |
623 | + } |
624 | + |
625 | + function actionTriggered() { |
626 | + selection.visible = false |
627 | + } |
628 | + |
629 | + function __showPopover() { |
630 | + __popover = PopupUtils.open(selectionPopover, selection.rect) |
631 | + var actions = __popover.actions.actions |
632 | + for (var i in actions) { |
633 | + actions[i].onTriggered.connect(actionTriggered) |
634 | + } |
635 | + } |
636 | + |
637 | + function show(x, y, width, height) { |
638 | + var scale = _webview.experimental.test.contentsScale * _webview.experimental.test.devicePixelRatio |
639 | + rect.x = x * scale + _webview.contentX |
640 | + rect.y = y * scale + _webview.contentY |
641 | + rect.width = width * scale |
642 | + rect.height = height * scale |
643 | + visible = true |
644 | + __showPopover() |
645 | + } |
646 | + |
647 | + onVisibleChanged: { |
648 | + if (!visible && (__popover != null)) { |
649 | + PopupUtils.close(__popover) |
650 | + __popover = null |
651 | + } |
652 | + } |
653 | + |
654 | + onResized: { |
655 | + var message = new Object |
656 | + message.query = 'adjustselection' |
657 | + var rect = selection.rect |
658 | + var scale = _webview.experimental.test.contentsScale * _webview.experimental.test.devicePixelRatio |
659 | + message.left = (rect.x - _webview.contentX) / scale |
660 | + message.right = (rect.x + rect.width - _webview.contentX) / scale |
661 | + message.top = (rect.y - _webview.contentY) / scale |
662 | + message.bottom = (rect.y + rect.height - _webview.contentY) / scale |
663 | + _webview.experimental.postMessage(JSON.stringify(message)) |
664 | + } |
665 | + |
666 | + function copy() { |
667 | + Clipboard.push(mimedata) |
668 | + clearData() |
669 | + } |
670 | + } |
671 | + |
672 | + Item { |
673 | + id: contextualRectangle |
674 | + |
675 | + visible: false |
676 | + |
677 | + function position(data) { |
678 | + var scale = _webview.experimental.test.contentsScale * _webview.experimental.test.devicePixelRatio |
679 | + x = data.left * scale |
680 | + y = data.top * scale |
681 | + width = data.width * scale |
682 | + height = data.height * scale |
683 | + } |
684 | + } |
685 | + property QtObject contextualData: QtObject { |
686 | + property url href |
687 | + property string title |
688 | + property url img |
689 | + |
690 | + function clear() { |
691 | + href = '' |
692 | + title = '' |
693 | + img = '' |
694 | + } |
695 | + } |
696 | + |
697 | + property ActionList contextualActions |
698 | + Component { |
699 | + id: contextualPopover |
700 | + ActionSelectionPopover { |
701 | + actions: contextualActions |
702 | + } |
703 | + } |
704 | + |
705 | + Scrollbar { |
706 | + parent: _webview.parent |
707 | + flickableItem: _webview |
708 | + align: Qt.AlignTrailing |
709 | + } |
710 | + |
711 | + Scrollbar { |
712 | + parent: _webview.parent |
713 | + flickableItem: _webview |
714 | + align: Qt.AlignBottom |
715 | + } |
716 | +} |
717 | |
718 | === renamed file 'src/Ubuntu/Components/Extras/Browser/UbuntuWebView.qml' => 'src/Ubuntu/Components/Extras/Browser/UbuntuWebView02.qml' |
719 | --- src/Ubuntu/Components/Extras/Browser/UbuntuWebView.qml 2014-03-14 17:33:23 +0000 |
720 | +++ src/Ubuntu/Components/Extras/Browser/UbuntuWebView02.qml 2014-03-28 17:03:06 +0000 |
721 | @@ -17,29 +17,18 @@ |
722 | */ |
723 | |
724 | import QtQuick 2.0 |
725 | -import QtWebKit 3.1 |
726 | -import QtWebKit.experimental 1.0 |
727 | +import QtQuick.Window 2.0 |
728 | +import com.canonical.Oxide 0.1 |
729 | import Ubuntu.Components 0.1 |
730 | -import Ubuntu.Components.Extras.Browser 0.1 |
731 | import Ubuntu.Components.Popups 0.1 |
732 | +import "." |
733 | |
734 | WebView { |
735 | id: _webview |
736 | |
737 | signal newTabRequested(url url) |
738 | |
739 | - QtObject { |
740 | - property real devicePixelRatio: QtWebKitDPR |
741 | - onDevicePixelRatioChanged: { |
742 | - // Do not make this patch to QtWebKit a hard requirement. |
743 | - if (_webview.experimental.hasOwnProperty('devicePixelRatio')) { |
744 | - _webview.experimental.devicePixelRatio = devicePixelRatio |
745 | - } |
746 | - } |
747 | - } |
748 | - |
749 | - interactive: !selection.visible |
750 | - maximumFlickVelocity: height * 5 |
751 | + //interactive: !selection.visible |
752 | |
753 | /** |
754 | * Client overridable function called before the default treatment of a |
755 | @@ -49,27 +38,65 @@ |
756 | */ |
757 | function navigationRequestedDelegate(request) { } |
758 | |
759 | - UserAgent { |
760 | - id: userAgent |
761 | - } |
762 | - |
763 | /** |
764 | * This function can be overridden by client applications that embed an |
765 | * UbuntuWebView to provide a static overridden UA string. |
766 | * If not overridden, the default UA string and the default override |
767 | * mechanism will be used. |
768 | + * |
769 | + * Note: as the UA string is a property of the shared context, |
770 | + * an application that embeds several UbuntuWebViews that define different |
771 | + * custom UA strings will result in the last view instantiated setting the |
772 | + * UA for all the views. |
773 | */ |
774 | function getUAString() { |
775 | - // Note that this function used to accept a 'url' parameter to allow |
776 | - // embedders to implement a custom override mechanism. It was removed |
777 | - // after observing that no application was using it, and to simplify |
778 | - // the API. Embedders willing to provide a custom override mechanism |
779 | - // can always override (at their own risk) the onNavigationRequested |
780 | - // slot. |
781 | return undefined |
782 | } |
783 | - experimental.userAgent: (_webview.getUAString() === undefined) ? userAgent.defaultUA : _webview.getUAString() |
784 | - onNavigationRequested: { |
785 | + |
786 | + context: UbuntuWebContext.sharedContext |
787 | + Component.onCompleted: { |
788 | + var customUA = getUAString() |
789 | + if (customUA !== undefined) { |
790 | + UbuntuWebContext.customUA = customUA |
791 | + } |
792 | + } |
793 | + |
794 | + messageHandlers: [ |
795 | + ScriptMessageHandler { |
796 | + msgId: "contextmenu" |
797 | + contexts: ["oxide://selection/"] |
798 | + callback: function(msg, frame) { |
799 | + if (('img' in msg.args) || ('href' in msg.args)) { |
800 | + if (internal.currentContextualMenu != null) { |
801 | + PopupUtils.close(internal.currentContextualMenu) |
802 | + } |
803 | + contextualData.clear() |
804 | + if ('img' in msg.args) { |
805 | + contextualData.img = msg.args.img |
806 | + } |
807 | + if ('href' in msg.args) { |
808 | + contextualData.href = msg.args.href |
809 | + contextualData.title = msg.args.title |
810 | + } |
811 | + contextualRectangle.position(msg.args) |
812 | + internal.currentContextualMenu = PopupUtils.open(contextualPopover, contextualRectangle) |
813 | + } else if (internal.currentContextualMenu != null) { |
814 | + PopupUtils.close(internal.currentContextualMenu) |
815 | + } |
816 | + } |
817 | + }, |
818 | + ScriptMessageHandler { |
819 | + msgId: "scroll" |
820 | + contexts: ["oxide://selection/"] |
821 | + callback: function(msg, frame) { |
822 | + if (internal.currentContextualMenu != null) { |
823 | + PopupUtils.close(internal.currentContextualMenu) |
824 | + } |
825 | + } |
826 | + } |
827 | + ] |
828 | + |
829 | + /*onNavigationRequested: { |
830 | request.action = WebView.AcceptRequest; |
831 | |
832 | navigationRequestedDelegate (request); |
833 | @@ -82,9 +109,9 @@ |
834 | } else { |
835 | _webview.experimental.userAgent = staticUA |
836 | } |
837 | - } |
838 | + }*/ |
839 | |
840 | - experimental.preferences.navigatorQtObjectEnabled: true |
841 | + /*experimental.preferences.navigatorQtObjectEnabled: true |
842 | experimental.userScripts: [Qt.resolvedUrl("hyperlinks.js"), |
843 | Qt.resolvedUrl("selection.js")] |
844 | experimental.onMessageReceived: { |
845 | @@ -133,11 +160,11 @@ |
846 | newTabRequested(data.url) |
847 | } |
848 | } |
849 | - } |
850 | - |
851 | - experimental.itemSelector: ItemSelector {} |
852 | - |
853 | - property alias selection: selection |
854 | + }*/ |
855 | + |
856 | + popupMenu: ItemSelector02 {} |
857 | + |
858 | + /*property alias selection: selection |
859 | property ActionList selectionActions |
860 | Selection { |
861 | id: selection |
862 | @@ -214,7 +241,7 @@ |
863 | Clipboard.push(mimedata) |
864 | clearData() |
865 | } |
866 | - } |
867 | + }*/ |
868 | |
869 | Item { |
870 | id: contextualRectangle |
871 | @@ -222,11 +249,10 @@ |
872 | visible: false |
873 | |
874 | function position(data) { |
875 | - var scale = _webview.experimental.test.contentsScale * _webview.experimental.test.devicePixelRatio |
876 | - x = data.left * scale |
877 | - y = data.top * scale |
878 | - width = data.width * scale |
879 | - height = data.height * scale |
880 | + x = data.left * data.scaleX |
881 | + y = data.top * data.scaleY |
882 | + width = data.width * data.scaleX |
883 | + height = data.height * data.scaleY |
884 | } |
885 | } |
886 | property QtObject contextualData: QtObject { |
887 | @@ -249,15 +275,25 @@ |
888 | } |
889 | } |
890 | |
891 | - Scrollbar { |
892 | - parent: _webview.parent |
893 | - flickableItem: _webview |
894 | - align: Qt.AlignTrailing |
895 | - } |
896 | - |
897 | - Scrollbar { |
898 | - parent: _webview.parent |
899 | - flickableItem: _webview |
900 | - align: Qt.AlignBottom |
901 | + QtObject { |
902 | + id: internal |
903 | + property int lastLoadRequestStatus: -1 |
904 | + property Item currentContextualMenu: null |
905 | + } |
906 | + |
907 | + readonly property bool lastLoadSucceeded: internal.lastLoadRequestStatus === LoadEvent.TypeSucceeded |
908 | + readonly property bool lastLoadStopped: internal.lastLoadRequestStatus === LoadEvent.TypeStopped |
909 | + readonly property bool lastLoadFailed: internal.lastLoadRequestStatus === LoadEvent.TypeFailed |
910 | + onLoadingChanged: { |
911 | + if (loadEvent.url.toString() !== "data:text/html,chromewebdata") { |
912 | + internal.lastLoadRequestStatus = loadEvent.type |
913 | + } |
914 | + } |
915 | + |
916 | + readonly property int screenOrientation: Screen.orientation |
917 | + onScreenOrientationChanged: { |
918 | + if (internal.currentContextualMenu != null) { |
919 | + PopupUtils.close(internal.currentContextualMenu) |
920 | + } |
921 | } |
922 | } |
923 | |
924 | === added file 'src/Ubuntu/Components/Extras/Browser/UserAgent01.qml' |
925 | --- src/Ubuntu/Components/Extras/Browser/UserAgent01.qml 1970-01-01 00:00:00 +0000 |
926 | +++ src/Ubuntu/Components/Extras/Browser/UserAgent01.qml 2014-03-28 17:03:06 +0000 |
927 | @@ -0,0 +1,90 @@ |
928 | +/* |
929 | + * Copyright 2013 Canonical Ltd. |
930 | + * |
931 | + * This file is part of webbrowser-app. |
932 | + * |
933 | + * webbrowser-app is free software; you can redistribute it and/or modify |
934 | + * it under the terms of the GNU General Public License as published by |
935 | + * the Free Software Foundation; version 3. |
936 | + * |
937 | + * webbrowser-app is distributed in the hope that it will be useful, |
938 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
939 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
940 | + * GNU General Public License for more details. |
941 | + * |
942 | + * You should have received a copy of the GNU General Public License |
943 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
944 | + */ |
945 | + |
946 | +import QtQuick 2.0 |
947 | +import QtQuick.Window 2.0 |
948 | +import Ubuntu.Components 0.1 |
949 | +import "ua-overrides.js" as Overrides |
950 | + |
951 | +/* |
952 | + * Useful documentation: |
953 | + * http://en.wikipedia.org/wiki/User_agent#Format |
954 | + * https://developer.mozilla.org/en-US/docs/Gecko_user_agent_string_reference |
955 | + * https://wiki.mozilla.org/B2G/User_Agent |
956 | + * https://github.com/mozilla-b2g/gaia/blob/master/build/ua-override-prefs.js |
957 | + * https://developers.google.com/chrome/mobile/docs/user-agent |
958 | + */ |
959 | + |
960 | +// This is an Item, not a QtObject, because it needs information about the Screen. |
961 | +Item { |
962 | + // %1: form factor (Mobile, Tablet, Desktop) |
963 | + // %2: WebKit version |
964 | + readonly property string _template: "Mozilla/5.0 (Ubuntu; %1) WebKit/%2" |
965 | + |
966 | + // See Source/WebCore/Configurations/Version.xcconfig in QtWebKit’s source tree |
967 | + // TODO: determine this value at runtime |
968 | + readonly property string _webkitVersion: "537.21" |
969 | + |
970 | + // FIXME: this is a quick hack that will become increasingly unreliable |
971 | + // as we support more devices, so we need a better solution for this |
972 | + // FIXME: only handling phone and tablet for now, need to handle desktop too |
973 | + readonly property string _formFactor: (Screen.width >= units.gu(60)) ? "Tablet" : "Mobile" |
974 | + |
975 | + property string defaultUA: _template.arg(_formFactor).arg(_webkitVersion) |
976 | + |
977 | + property var overrides: Overrides.overrides |
978 | + |
979 | + function getDomain(url) { |
980 | + var domain = url.toString() |
981 | + var indexOfScheme = domain.indexOf("://") |
982 | + if (indexOfScheme !== -1) { |
983 | + domain = domain.slice(indexOfScheme + 3) |
984 | + } |
985 | + var indexOfPath = domain.indexOf("/") |
986 | + if (indexOfPath !== -1) { |
987 | + domain = domain.slice(0, indexOfPath) |
988 | + } |
989 | + return domain |
990 | + } |
991 | + |
992 | + function getDomains(domain) { |
993 | + var components = domain.split(".") |
994 | + var domains = [] |
995 | + for (var i = 0; i < components.length; i++) { |
996 | + domains.push(components.slice(i).join(".")) |
997 | + } |
998 | + return domains |
999 | + } |
1000 | + |
1001 | + function getUAString(url) { |
1002 | + var ua = defaultUA |
1003 | + var domains = getDomains(getDomain(url)) |
1004 | + for (var i = 0; i < domains.length; i++) { |
1005 | + var domain = domains[i] |
1006 | + if (domain in overrides) { |
1007 | + var form = overrides[domain] |
1008 | + if (typeof form == "string") { |
1009 | + return form |
1010 | + } else if (typeof form == "object") { |
1011 | + return ua.replace(form[0], form[1]) |
1012 | + } |
1013 | + } |
1014 | + } |
1015 | + return ua |
1016 | + } |
1017 | +} |
1018 | |
1019 | === renamed file 'src/Ubuntu/Components/Extras/Browser/UserAgent.qml' => 'src/Ubuntu/Components/Extras/Browser/UserAgent02.qml' |
1020 | --- src/Ubuntu/Components/Extras/Browser/UserAgent.qml 2013-09-25 16:38:06 +0000 |
1021 | +++ src/Ubuntu/Components/Extras/Browser/UserAgent02.qml 2014-03-28 17:03:06 +0000 |
1022 | @@ -1,5 +1,5 @@ |
1023 | /* |
1024 | - * Copyright 2013 Canonical Ltd. |
1025 | + * Copyright 2013-2014 Canonical Ltd. |
1026 | * |
1027 | * This file is part of webbrowser-app. |
1028 | * |
1029 | @@ -16,10 +16,7 @@ |
1030 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1031 | */ |
1032 | |
1033 | -import QtQuick 2.0 |
1034 | -import QtQuick.Window 2.0 |
1035 | -import Ubuntu.Components 0.1 |
1036 | -import "ua-overrides.js" as Overrides |
1037 | +import QtQml 2.0 |
1038 | |
1039 | /* |
1040 | * Useful documentation: |
1041 | @@ -30,61 +27,36 @@ |
1042 | * https://developers.google.com/chrome/mobile/docs/user-agent |
1043 | */ |
1044 | |
1045 | -// This is an Item, not a QtObject, because it needs information about the Screen. |
1046 | -Item { |
1047 | - // %1: form factor (Mobile, Tablet, Desktop) |
1048 | - // %2: WebKit version |
1049 | - readonly property string _template: "Mozilla/5.0 (Ubuntu; %1) WebKit/%2" |
1050 | - |
1051 | - // See Source/WebCore/Configurations/Version.xcconfig in QtWebKit’s source tree |
1052 | - // TODO: determine this value at runtime |
1053 | - readonly property string _webkitVersion: "537.21" |
1054 | - |
1055 | - // FIXME: this is a quick hack that will become increasingly unreliable |
1056 | - // as we support more devices, so we need a better solution for this |
1057 | - // FIXME: only handling phone and tablet for now, need to handle desktop too |
1058 | - readonly property string _formFactor: (Screen.width >= units.gu(60)) ? "Tablet" : "Mobile" |
1059 | - |
1060 | - property string defaultUA: _template.arg(_formFactor).arg(_webkitVersion) |
1061 | - |
1062 | - property var overrides: Overrides.overrides |
1063 | - |
1064 | - function getDomain(url) { |
1065 | - var domain = url.toString() |
1066 | - var indexOfScheme = domain.indexOf("://") |
1067 | - if (indexOfScheme !== -1) { |
1068 | - domain = domain.slice(indexOfScheme + 3) |
1069 | - } |
1070 | - var indexOfPath = domain.indexOf("/") |
1071 | - if (indexOfPath !== -1) { |
1072 | - domain = domain.slice(0, indexOfPath) |
1073 | - } |
1074 | - return domain |
1075 | - } |
1076 | - |
1077 | - function getDomains(domain) { |
1078 | - var components = domain.split(".") |
1079 | - var domains = [] |
1080 | - for (var i = 0; i < components.length; i++) { |
1081 | - domains.push(components.slice(i).join(".")) |
1082 | - } |
1083 | - return domains |
1084 | - } |
1085 | - |
1086 | - function getUAString(url) { |
1087 | - var ua = defaultUA |
1088 | - var domains = getDomains(getDomain(url)) |
1089 | - for (var i = 0; i < domains.length; i++) { |
1090 | - var domain = domains[i] |
1091 | - if (domain in overrides) { |
1092 | - var form = overrides[domain] |
1093 | - if (typeof form == "string") { |
1094 | - return form |
1095 | - } else if (typeof form == "object") { |
1096 | - return ua.replace(form[0], form[1]) |
1097 | - } |
1098 | - } |
1099 | - } |
1100 | - return ua |
1101 | - } |
1102 | +QtObject { |
1103 | + // %1: Ubuntu version, e.g. "14.04" |
1104 | + // %2: optional token to specify further attributes of the platform (must start with a whitespace), e.g. "like Android" |
1105 | + // %3: optional hardware ID token (must start with a semi-colon if present) |
1106 | + // %4: WebKit version, e.g. "537.36" |
1107 | + // %5: Chromium version, e.g. "35.0.1870.2" |
1108 | + // %6: optional token to provide additional free-form information (must start with a whitespace), e.g. "Mobile" |
1109 | + // note #1: "Mozilla/5.0" is misinformation, but it is a legacy token that |
1110 | + // virtually every single UA out there has, it seems unwise to remove it |
1111 | + // note #2: "AppleWebKit", as opposed to plain "WebKit", does make a |
1112 | + // difference in the content served by certain sites (e.g. gmail.com) |
1113 | + readonly property string _template: "Mozilla/5.0 (Linux; Ubuntu %1%2%3) AppleWebKit/%4 Chromium/%5%6" |
1114 | + |
1115 | + // FIXME: compute at build time (using lsb_release) |
1116 | + readonly property string _ubuntuVersion: "14.04" |
1117 | + |
1118 | + readonly property string _attributes: (formFactor === "mobile") ? " like Android 4.4" : "" |
1119 | + |
1120 | + readonly property string _hardwareID: "" |
1121 | + |
1122 | + // See chromium/src/webkit/build/webkit_version.h.in in oxide’s source tree. |
1123 | + readonly property string _webkitVersion: "537.36" |
1124 | + |
1125 | + // See chromium/src/chrome/VERSION in oxide’s source tree. |
1126 | + // Note: the actual version number probably doesn’t matter that much, |
1127 | + // however its format does, so we probably don’t need to bump it |
1128 | + // every time we rebase on a newer chromium. |
1129 | + readonly property string _chromiumVersion: "35.0.1870.2" |
1130 | + |
1131 | + readonly property string _more: (formFactor === "mobile") ? " Mobile" : "" |
1132 | + |
1133 | + property string defaultUA: _template.arg(_ubuntuVersion).arg(_attributes).arg(_hardwareID).arg(_webkitVersion).arg(_chromiumVersion).arg(_more) |
1134 | } |
1135 | |
1136 | === added file 'src/Ubuntu/Components/Extras/Browser/dummysingleton.qml' |
1137 | --- src/Ubuntu/Components/Extras/Browser/dummysingleton.qml 1970-01-01 00:00:00 +0000 |
1138 | +++ src/Ubuntu/Components/Extras/Browser/dummysingleton.qml 2014-03-28 17:03:06 +0000 |
1139 | @@ -0,0 +1,27 @@ |
1140 | +/* |
1141 | + * Copyright 2014 Canonical Ltd. |
1142 | + * |
1143 | + * This file is part of webbrowser-app. |
1144 | + * |
1145 | + * webbrowser-app is free software; you can redistribute it and/or modify |
1146 | + * it under the terms of the GNU General Public License as published by |
1147 | + * the Free Software Foundation; version 3. |
1148 | + * |
1149 | + * webbrowser-app is distributed in the hope that it will be useful, |
1150 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1151 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1152 | + * GNU General Public License for more details. |
1153 | + * |
1154 | + * You should have received a copy of the GNU General Public License |
1155 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1156 | + */ |
1157 | + |
1158 | +// This file is not really used, but without it importing version 0.1 of |
1159 | +// Ubuntu.Components.Extras.Browser fails because the QML engine requests type |
1160 | +// UbuntuWebContext, despite it being specific to version 0.2 of the module. |
1161 | + |
1162 | +pragma Singleton |
1163 | + |
1164 | +import QtQml 2.0 |
1165 | + |
1166 | +QtObject {} |
1167 | |
1168 | === modified file 'src/Ubuntu/Components/Extras/Browser/plugin.cpp' |
1169 | --- src/Ubuntu/Components/Extras/Browser/plugin.cpp 2014-03-12 17:48:34 +0000 |
1170 | +++ src/Ubuntu/Components/Extras/Browser/plugin.cpp 2014-03-28 17:03:06 +0000 |
1171 | @@ -21,6 +21,8 @@ |
1172 | // Qt |
1173 | #include <QtCore/QDir> |
1174 | #include <QtCore/QStandardPaths> |
1175 | +#include <QtCore/QtGlobal> |
1176 | +#include <QtGui/QGuiApplication> |
1177 | #include <QtQml> |
1178 | |
1179 | static float getQtWebkitDpr() |
1180 | @@ -31,6 +33,36 @@ |
1181 | return ok ? value : 1.0; |
1182 | } |
1183 | |
1184 | +static QString getFormFactor() |
1185 | +{ |
1186 | + // This implementation only considers two possible form factors: desktop, |
1187 | + // and mobile (which includes phones and tablets). |
1188 | + // XXX: do we need to consider other form factors, such as tablet? |
1189 | + const char* DESKTOP = "desktop"; |
1190 | + const char* MOBILE = "mobile"; |
1191 | + |
1192 | + // The "DESKTOP_MODE" environment variable can be used to force the form |
1193 | + // factor to desktop, when set to any valid value other than 0. |
1194 | + const char* DESKTOP_MODE_ENV_VAR = "DESKTOP_MODE"; |
1195 | + if (qEnvironmentVariableIsSet(DESKTOP_MODE_ENV_VAR)) { |
1196 | + QByteArray stringValue = qgetenv(DESKTOP_MODE_ENV_VAR); |
1197 | + bool ok = false; |
1198 | + int value = stringValue.toInt(&ok); |
1199 | + if (ok) { |
1200 | + return (value == 0) ? MOBILE : DESKTOP; |
1201 | + } |
1202 | + } |
1203 | + |
1204 | + // XXX: Assume that QtUbuntu means mobile, which is currently the case, |
1205 | + // but may not remain true forever. |
1206 | + QString platform = QGuiApplication::platformName(); |
1207 | + if ((platform == "ubuntu") || (platform == "ubuntumirclient")) { |
1208 | + return MOBILE; |
1209 | + } |
1210 | + |
1211 | + return DESKTOP; |
1212 | +} |
1213 | + |
1214 | void UbuntuBrowserPlugin::initializeEngine(QQmlEngine* engine, const char* uri) |
1215 | { |
1216 | Q_UNUSED(uri); |
1217 | @@ -45,6 +77,8 @@ |
1218 | // Set the desired pixel ratio (not needed once we use Qt’s way of |
1219 | // calculating the proper pixel ratio by device/screen). |
1220 | context->setContextProperty("QtWebKitDPR", getQtWebkitDpr()); |
1221 | + |
1222 | + context->setContextProperty("formFactor", getFormFactor()); |
1223 | } |
1224 | |
1225 | void UbuntuBrowserPlugin::registerTypes(const char* uri) |
1226 | |
1227 | === modified file 'src/Ubuntu/Components/Extras/Browser/qmldir' |
1228 | --- src/Ubuntu/Components/Extras/Browser/qmldir 2014-03-12 15:27:10 +0000 |
1229 | +++ src/Ubuntu/Components/Extras/Browser/qmldir 2014-03-28 17:03:06 +0000 |
1230 | @@ -1,3 +1,7 @@ |
1231 | module Ubuntu.Components.Extras.Browser |
1232 | plugin ubuntu-ui-extras-browser-plugin |
1233 | -UbuntuWebView 0.1 UbuntuWebView.qml |
1234 | +UbuntuWebView 0.1 UbuntuWebView01.qml |
1235 | +UbuntuWebView 0.2 UbuntuWebView02.qml |
1236 | +# Without the following line, importing version 0.1 of the module fails |
1237 | +singleton UbuntuWebContext 0.1 dummysingleton.qml |
1238 | +singleton UbuntuWebContext 0.2 UbuntuWebContext.qml |
1239 | |
1240 | === added file 'src/Ubuntu/Components/Extras/Browser/selection01.js' |
1241 | --- src/Ubuntu/Components/Extras/Browser/selection01.js 1970-01-01 00:00:00 +0000 |
1242 | +++ src/Ubuntu/Components/Extras/Browser/selection01.js 2014-03-28 17:03:06 +0000 |
1243 | @@ -0,0 +1,193 @@ |
1244 | +/* |
1245 | + * Copyright 2013-2014 Canonical Ltd. |
1246 | + * |
1247 | + * This file is part of webbrowser-app. |
1248 | + * |
1249 | + * webbrowser-app is free software; you can redistribute it and/or modify |
1250 | + * it under the terms of the GNU General Public License as published by |
1251 | + * the Free Software Foundation; version 3. |
1252 | + * |
1253 | + * webbrowser-app is distributed in the hope that it will be useful, |
1254 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1255 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1256 | + * GNU General Public License for more details. |
1257 | + * |
1258 | + * You should have received a copy of the GNU General Public License |
1259 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1260 | + */ |
1261 | + |
1262 | +// List of domains known to interfere with touch events listeners |
1263 | +var blacklist = [ |
1264 | + "m.8tracks.com", // http://pad.lv/1279903 |
1265 | +]; |
1266 | +if (blacklist.indexOf(document.domain) === -1) { |
1267 | + |
1268 | + function elementContainedInBox(element, box) { |
1269 | + var rect = element.getBoundingClientRect(); |
1270 | + return ((box.left <= rect.left) && (box.right >= rect.right) && |
1271 | + (box.top <= rect.top) && (box.bottom >= rect.bottom)); |
1272 | + } |
1273 | + |
1274 | + function getImgFullUri(uri) { |
1275 | + if ((uri.slice(0, 7) === 'http://') || |
1276 | + (uri.slice(0, 8) === 'https://') || |
1277 | + (uri.slice(0, 7) === 'file://')) { |
1278 | + return uri; |
1279 | + } else if (uri.slice(0, 1) === '/') { |
1280 | + var docuri = document.documentURI; |
1281 | + var firstcolon = docuri.indexOf('://'); |
1282 | + var protocol = 'http://'; |
1283 | + if (firstcolon !== -1) { |
1284 | + protocol = docuri.slice(0, firstcolon + 3); |
1285 | + } |
1286 | + return protocol + document.domain + uri; |
1287 | + } else { |
1288 | + var base = document.baseURI; |
1289 | + var lastslash = base.lastIndexOf('/'); |
1290 | + if (lastslash === -1) { |
1291 | + return base + '/' + uri; |
1292 | + } else { |
1293 | + return base.slice(0, lastslash + 1) + uri; |
1294 | + } |
1295 | + } |
1296 | + } |
1297 | + |
1298 | + function getSelectedData(element) { |
1299 | + var node = element; |
1300 | + var data = new Object; |
1301 | + |
1302 | + var nodeName = node.nodeName.toLowerCase(); |
1303 | + if (nodeName === 'img') { |
1304 | + data.img = getImgFullUri(node.getAttribute('src')); |
1305 | + } else if (nodeName === 'a') { |
1306 | + data.href = node.href; |
1307 | + data.title = node.title; |
1308 | + } |
1309 | + |
1310 | + // If the parent tag is a hyperlink, we want it too. |
1311 | + var parent = node.parentNode; |
1312 | + if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) { |
1313 | + data.href = parent.href; |
1314 | + data.title = parent.title; |
1315 | + node = parent; |
1316 | + } |
1317 | + |
1318 | + var boundingRect = node.getBoundingClientRect(); |
1319 | + data.left = boundingRect.left; |
1320 | + data.top = boundingRect.top; |
1321 | + data.width = boundingRect.width; |
1322 | + data.height = boundingRect.height; |
1323 | + |
1324 | + node = node.cloneNode(true); |
1325 | + // filter out script nodes |
1326 | + var scripts = node.getElementsByTagName('script'); |
1327 | + while (scripts.length > 0) { |
1328 | + var scriptNode = scripts[0]; |
1329 | + if (scriptNode.parentNode) { |
1330 | + scriptNode.parentNode.removeChild(scriptNode); |
1331 | + } |
1332 | + } |
1333 | + data.html = node.outerHTML; |
1334 | + data.nodeName = node.nodeName.toLowerCase(); |
1335 | + // FIXME: extract the text and images in the order they appear in the block, |
1336 | + // so that this order is respected when the data is pushed to the clipboard. |
1337 | + data.text = node.textContent; |
1338 | + var images = []; |
1339 | + var imgs = node.getElementsByTagName('img'); |
1340 | + for (var i = 0; i < imgs.length; i++) { |
1341 | + images.push(getImgFullUri(imgs[i].getAttribute('src'))); |
1342 | + } |
1343 | + if (images.length > 0) { |
1344 | + data.images = images; |
1345 | + } |
1346 | + |
1347 | + return data; |
1348 | + } |
1349 | + |
1350 | + function adjustSelection(selection) { |
1351 | + // FIXME: allow selecting two consecutive blocks, instead of |
1352 | + // interpolating to the containing block. |
1353 | + var centerX = (selection.left + selection.right) / 2; |
1354 | + var centerY = (selection.top + selection.bottom) / 2; |
1355 | + var element = document.elementFromPoint(centerX, centerY); |
1356 | + var parent = element; |
1357 | + while (elementContainedInBox(parent, selection)) { |
1358 | + parent = parent.parentNode; |
1359 | + } |
1360 | + element = parent; |
1361 | + return getSelectedData(element); |
1362 | + } |
1363 | + |
1364 | + function distance(touch1, touch2) { |
1365 | + return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) + |
1366 | + Math.pow(touch2.clientY - touch1.clientY, 2)); |
1367 | + } |
1368 | + |
1369 | + navigator.qt.onmessage = function(message) { |
1370 | + var data = null; |
1371 | + try { |
1372 | + data = JSON.parse(message.data); |
1373 | + } catch (error) { |
1374 | + return; |
1375 | + } |
1376 | + if ('query' in data) { |
1377 | + if (data.query === 'adjustselection') { |
1378 | + var selection = adjustSelection(data); |
1379 | + selection.event = 'selectionadjusted'; |
1380 | + navigator.qt.postMessage(JSON.stringify(selection)); |
1381 | + } |
1382 | + } |
1383 | + } |
1384 | + |
1385 | + var longpressObserver = -1; |
1386 | + var currentTouch = null; |
1387 | + var longpressDetected = false; |
1388 | + |
1389 | + function longPressDetected(x, y) { |
1390 | + longpressDetected = true; |
1391 | + var element = document.elementFromPoint(x, y); |
1392 | + var data = getSelectedData(element); |
1393 | + data.event = 'longpress'; |
1394 | + navigator.qt.postMessage(JSON.stringify(data)); |
1395 | + } |
1396 | + |
1397 | + function clearLongpressTimeout() { |
1398 | + clearTimeout(longpressObserver); |
1399 | + longpressObserver = -1; |
1400 | + currentTouch = null; |
1401 | + } |
1402 | + |
1403 | + var doc = document.documentElement; |
1404 | + |
1405 | + doc.addEventListener('touchstart', function(event) { |
1406 | + if (event.touches.length == 1) { |
1407 | + currentTouch = event.touches[0]; |
1408 | + longpressObserver = setTimeout(longPressDetected, 800, currentTouch.clientX, currentTouch.clientY); |
1409 | + } |
1410 | + }); |
1411 | + |
1412 | + doc.addEventListener('touchend', function(event) { |
1413 | + if (longpressDetected) { |
1414 | + longpressDetected = false; |
1415 | + event.preventDefault(); |
1416 | + } |
1417 | + clearLongpressTimeout(); |
1418 | + }); |
1419 | + |
1420 | + doc.addEventListener('touchmove', function(event) { |
1421 | + if (!currentTouch) { |
1422 | + return; |
1423 | + } |
1424 | + if ((event.changedTouches.length > 1) || (distance(event.changedTouches[0], currentTouch) > 3)) { |
1425 | + clearLongpressTimeout(); |
1426 | + } |
1427 | + }); |
1428 | + |
1429 | + doc.addEventListener('touchcancel', function(event) { |
1430 | + if (longpressDetected) { |
1431 | + longpressDetected = false; |
1432 | + } |
1433 | + clearLongpressTimeout(); |
1434 | + }); |
1435 | + |
1436 | +} |
1437 | |
1438 | === renamed file 'src/Ubuntu/Components/Extras/Browser/selection.js' => 'src/Ubuntu/Components/Extras/Browser/selection02.js' |
1439 | --- src/Ubuntu/Components/Extras/Browser/selection.js 2014-02-19 15:53:33 +0000 |
1440 | +++ src/Ubuntu/Components/Extras/Browser/selection02.js 2014-03-28 17:03:06 +0000 |
1441 | @@ -16,178 +16,132 @@ |
1442 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1443 | */ |
1444 | |
1445 | -// List of domains known to interfere with touch events listeners |
1446 | -var blacklist = [ |
1447 | - "m.8tracks.com", // http://pad.lv/1279903 |
1448 | -]; |
1449 | -if (blacklist.indexOf(document.domain) === -1) { |
1450 | - |
1451 | - function elementContainedInBox(element, box) { |
1452 | - var rect = element.getBoundingClientRect(); |
1453 | - return ((box.left <= rect.left) && (box.right >= rect.right) && |
1454 | - (box.top <= rect.top) && (box.bottom >= rect.bottom)); |
1455 | - } |
1456 | - |
1457 | - function getImgFullUri(uri) { |
1458 | - if ((uri.slice(0, 7) === 'http://') || |
1459 | - (uri.slice(0, 8) === 'https://') || |
1460 | - (uri.slice(0, 7) === 'file://')) { |
1461 | - return uri; |
1462 | - } else if (uri.slice(0, 1) === '/') { |
1463 | - var docuri = document.documentURI; |
1464 | - var firstcolon = docuri.indexOf('://'); |
1465 | - var protocol = 'http://'; |
1466 | - if (firstcolon !== -1) { |
1467 | - protocol = docuri.slice(0, firstcolon + 3); |
1468 | - } |
1469 | - return protocol + document.domain + uri; |
1470 | +function elementContainedInBox(element, box) { |
1471 | + var rect = element.getBoundingClientRect(); |
1472 | + return ((box.left <= rect.left) && (box.right >= rect.right) && |
1473 | + (box.top <= rect.top) && (box.bottom >= rect.bottom)); |
1474 | +} |
1475 | + |
1476 | +function getImgFullUri(uri) { |
1477 | + if ((uri.slice(0, 7) === 'http://') || |
1478 | + (uri.slice(0, 8) === 'https://') || |
1479 | + (uri.slice(0, 7) === 'file://')) { |
1480 | + return uri; |
1481 | + } else if (uri.slice(0, 1) === '/') { |
1482 | + var docuri = document.documentURI; |
1483 | + var firstcolon = docuri.indexOf('://'); |
1484 | + var protocol = 'http://'; |
1485 | + if (firstcolon !== -1) { |
1486 | + protocol = docuri.slice(0, firstcolon + 3); |
1487 | + } |
1488 | + return protocol + document.domain + uri; |
1489 | + } else { |
1490 | + var base = document.baseURI; |
1491 | + var lastslash = base.lastIndexOf('/'); |
1492 | + if (lastslash === -1) { |
1493 | + return base + '/' + uri; |
1494 | } else { |
1495 | - var base = document.baseURI; |
1496 | - var lastslash = base.lastIndexOf('/'); |
1497 | - if (lastslash === -1) { |
1498 | - return base + '/' + uri; |
1499 | - } else { |
1500 | - return base.slice(0, lastslash + 1) + uri; |
1501 | - } |
1502 | - } |
1503 | - } |
1504 | - |
1505 | - function getSelectedData(element) { |
1506 | - var node = element; |
1507 | - var data = new Object; |
1508 | - |
1509 | - var nodeName = node.nodeName.toLowerCase(); |
1510 | - if (nodeName === 'img') { |
1511 | - data.img = getImgFullUri(node.getAttribute('src')); |
1512 | - } else if (nodeName === 'a') { |
1513 | - data.href = node.href; |
1514 | - data.title = node.title; |
1515 | - } |
1516 | - |
1517 | - // If the parent tag is a hyperlink, we want it too. |
1518 | - var parent = node.parentNode; |
1519 | - if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) { |
1520 | - data.href = parent.href; |
1521 | - data.title = parent.title; |
1522 | - node = parent; |
1523 | - } |
1524 | - |
1525 | - var boundingRect = node.getBoundingClientRect(); |
1526 | - data.left = boundingRect.left; |
1527 | - data.top = boundingRect.top; |
1528 | - data.width = boundingRect.width; |
1529 | - data.height = boundingRect.height; |
1530 | - |
1531 | - node = node.cloneNode(true); |
1532 | - // filter out script nodes |
1533 | - var scripts = node.getElementsByTagName('script'); |
1534 | - while (scripts.length > 0) { |
1535 | - var scriptNode = scripts[0]; |
1536 | - if (scriptNode.parentNode) { |
1537 | - scriptNode.parentNode.removeChild(scriptNode); |
1538 | - } |
1539 | - } |
1540 | - data.html = node.outerHTML; |
1541 | - data.nodeName = node.nodeName.toLowerCase(); |
1542 | - // FIXME: extract the text and images in the order they appear in the block, |
1543 | - // so that this order is respected when the data is pushed to the clipboard. |
1544 | - data.text = node.textContent; |
1545 | - var images = []; |
1546 | - var imgs = node.getElementsByTagName('img'); |
1547 | - for (var i = 0; i < imgs.length; i++) { |
1548 | - images.push(getImgFullUri(imgs[i].getAttribute('src'))); |
1549 | - } |
1550 | - if (images.length > 0) { |
1551 | - data.images = images; |
1552 | - } |
1553 | - |
1554 | - return data; |
1555 | - } |
1556 | - |
1557 | - function adjustSelection(selection) { |
1558 | - // FIXME: allow selecting two consecutive blocks, instead of |
1559 | - // interpolating to the containing block. |
1560 | - var centerX = (selection.left + selection.right) / 2; |
1561 | - var centerY = (selection.top + selection.bottom) / 2; |
1562 | - var element = document.elementFromPoint(centerX, centerY); |
1563 | - var parent = element; |
1564 | - while (elementContainedInBox(parent, selection)) { |
1565 | - parent = parent.parentNode; |
1566 | - } |
1567 | - element = parent; |
1568 | - return getSelectedData(element); |
1569 | - } |
1570 | - |
1571 | - function distance(touch1, touch2) { |
1572 | - return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) + |
1573 | - Math.pow(touch2.clientY - touch1.clientY, 2)); |
1574 | - } |
1575 | - |
1576 | - navigator.qt.onmessage = function(message) { |
1577 | - var data = null; |
1578 | - try { |
1579 | - data = JSON.parse(message.data); |
1580 | - } catch (error) { |
1581 | - return; |
1582 | - } |
1583 | - if ('query' in data) { |
1584 | - if (data.query === 'adjustselection') { |
1585 | - var selection = adjustSelection(data); |
1586 | - selection.event = 'selectionadjusted'; |
1587 | - navigator.qt.postMessage(JSON.stringify(selection)); |
1588 | - } |
1589 | - } |
1590 | - } |
1591 | - |
1592 | - var longpressObserver = -1; |
1593 | - var currentTouch = null; |
1594 | - var longpressDetected = false; |
1595 | - |
1596 | - function longPressDetected(x, y) { |
1597 | - longpressDetected = true; |
1598 | - var element = document.elementFromPoint(x, y); |
1599 | - var data = getSelectedData(element); |
1600 | - data.event = 'longpress'; |
1601 | - navigator.qt.postMessage(JSON.stringify(data)); |
1602 | - } |
1603 | - |
1604 | - function clearLongpressTimeout() { |
1605 | - clearTimeout(longpressObserver); |
1606 | - longpressObserver = -1; |
1607 | - currentTouch = null; |
1608 | - } |
1609 | - |
1610 | - var doc = document.documentElement; |
1611 | - |
1612 | - doc.addEventListener('touchstart', function(event) { |
1613 | - if (event.touches.length == 1) { |
1614 | - currentTouch = event.touches[0]; |
1615 | - longpressObserver = setTimeout(longPressDetected, 800, currentTouch.clientX, currentTouch.clientY); |
1616 | - } |
1617 | - }); |
1618 | - |
1619 | - doc.addEventListener('touchend', function(event) { |
1620 | - if (longpressDetected) { |
1621 | - longpressDetected = false; |
1622 | - event.preventDefault(); |
1623 | - } |
1624 | - clearLongpressTimeout(); |
1625 | - }); |
1626 | - |
1627 | - doc.addEventListener('touchmove', function(event) { |
1628 | - if (!currentTouch) { |
1629 | - return; |
1630 | - } |
1631 | - if ((event.changedTouches.length > 1) || (distance(event.changedTouches[0], currentTouch) > 3)) { |
1632 | - clearLongpressTimeout(); |
1633 | - } |
1634 | - }); |
1635 | - |
1636 | - doc.addEventListener('touchcancel', function(event) { |
1637 | - if (longpressDetected) { |
1638 | - longpressDetected = false; |
1639 | - } |
1640 | - clearLongpressTimeout(); |
1641 | - }); |
1642 | - |
1643 | -} |
1644 | + return base.slice(0, lastslash + 1) + uri; |
1645 | + } |
1646 | + } |
1647 | +} |
1648 | + |
1649 | +function getSelectedData(element) { |
1650 | + var node = element; |
1651 | + var data = new Object; |
1652 | + |
1653 | + var nodeName = node.nodeName.toLowerCase(); |
1654 | + if (nodeName === 'img') { |
1655 | + data.img = getImgFullUri(node.getAttribute('src')); |
1656 | + } else if (nodeName === 'a') { |
1657 | + data.href = node.href; |
1658 | + data.title = node.title; |
1659 | + } |
1660 | + |
1661 | + // If the parent tag is a hyperlink, we want it too. |
1662 | + var parent = node.parentNode; |
1663 | + if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) { |
1664 | + data.href = parent.href; |
1665 | + data.title = parent.title; |
1666 | + node = parent; |
1667 | + } |
1668 | + |
1669 | + var boundingRect = node.getBoundingClientRect(); |
1670 | + data.left = boundingRect.left; |
1671 | + data.top = boundingRect.top; |
1672 | + data.width = boundingRect.width; |
1673 | + data.height = boundingRect.height; |
1674 | + |
1675 | + node = node.cloneNode(true); |
1676 | + // filter out script nodes |
1677 | + var scripts = node.getElementsByTagName('script'); |
1678 | + while (scripts.length > 0) { |
1679 | + var scriptNode = scripts[0]; |
1680 | + if (scriptNode.parentNode) { |
1681 | + scriptNode.parentNode.removeChild(scriptNode); |
1682 | + } |
1683 | + } |
1684 | + data.html = node.outerHTML; |
1685 | + data.nodeName = node.nodeName.toLowerCase(); |
1686 | + // FIXME: extract the text and images in the order they appear in the block, |
1687 | + // so that this order is respected when the data is pushed to the clipboard. |
1688 | + data.text = node.textContent; |
1689 | + var images = []; |
1690 | + var imgs = node.getElementsByTagName('img'); |
1691 | + for (var i = 0; i < imgs.length; i++) { |
1692 | + images.push(getImgFullUri(imgs[i].getAttribute('src'))); |
1693 | + } |
1694 | + if (images.length > 0) { |
1695 | + data.images = images; |
1696 | + } |
1697 | + |
1698 | + return data; |
1699 | +} |
1700 | + |
1701 | +function adjustSelection(selection) { |
1702 | + // FIXME: allow selecting two consecutive blocks, instead of |
1703 | + // interpolating to the containing block. |
1704 | + var centerX = (selection.left + selection.right) / 2; |
1705 | + var centerY = (selection.top + selection.bottom) / 2; |
1706 | + var element = document.elementFromPoint(centerX, centerY); |
1707 | + var parent = element; |
1708 | + while (elementContainedInBox(parent, selection)) { |
1709 | + parent = parent.parentNode; |
1710 | + } |
1711 | + element = parent; |
1712 | + return getSelectedData(element); |
1713 | +} |
1714 | + |
1715 | +function distance(touch1, touch2) { |
1716 | + return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) + |
1717 | + Math.pow(touch2.clientY - touch1.clientY, 2)); |
1718 | +} |
1719 | + |
1720 | +/*navigator.qt.onmessage = function(message) { |
1721 | + var data = null; |
1722 | + try { |
1723 | + data = JSON.parse(message.data); |
1724 | + } catch (error) { |
1725 | + return; |
1726 | + } |
1727 | + if ('query' in data) { |
1728 | + if (data.query === 'adjustselection') { |
1729 | + var selection = adjustSelection(data); |
1730 | + selection.event = 'selectionadjusted'; |
1731 | + navigator.qt.postMessage(JSON.stringify(selection)); |
1732 | + } |
1733 | + } |
1734 | +}*/ |
1735 | + |
1736 | +document.documentElement.addEventListener('contextmenu', function(event) { |
1737 | + var element = document.elementFromPoint(event.clientX, event.clientY); |
1738 | + var data = getSelectedData(element); |
1739 | + var w = document.defaultView; |
1740 | + data['scaleX'] = w.outerWidth / w.innerWidth * w.devicePixelRatio; |
1741 | + data['scaleY'] = w.outerHeight / w.innerHeight * w.devicePixelRatio; |
1742 | + oxide.sendMessage('contextmenu', data); |
1743 | +}); |
1744 | + |
1745 | +document.defaultView.addEventListener('scroll', function(event) { |
1746 | + oxide.sendMessage('scroll', {}); |
1747 | +}); |
1748 | |
1749 | === added file 'src/Ubuntu/Components/Extras/Browser/ua-override-worker.js' |
1750 | --- src/Ubuntu/Components/Extras/Browser/ua-override-worker.js 1970-01-01 00:00:00 +0000 |
1751 | +++ src/Ubuntu/Components/Extras/Browser/ua-override-worker.js 2014-03-28 17:03:06 +0000 |
1752 | @@ -0,0 +1,46 @@ |
1753 | +/* |
1754 | + * Copyright 2014 Canonical Ltd. |
1755 | + * |
1756 | + * This file is part of webbrowser-app. |
1757 | + * |
1758 | + * webbrowser-app is free software; you can redistribute it and/or modify |
1759 | + * it under the terms of the GNU General Public License as published by |
1760 | + * the Free Software Foundation; version 3. |
1761 | + * |
1762 | + * webbrowser-app is distributed in the hope that it will be useful, |
1763 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1764 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1765 | + * GNU General Public License for more details. |
1766 | + * |
1767 | + * You should have received a copy of the GNU General Public License |
1768 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1769 | + */ |
1770 | + |
1771 | +var overrides = [ |
1772 | + [/^https?:\/\/mail.google.com\//, "Mozilla/5.0 (Linux; Ubuntu 14.04 like Android 4.4) AppleWebKit/537.36 Chromium/35.0.1870.2 Mobile Safari"] |
1773 | +]; |
1774 | + |
1775 | +function getUAoverride(url) { |
1776 | + for (var i = 0; i < overrides.length; i++) { |
1777 | + var override = overrides[i]; |
1778 | + if (override[0].test(url)) { |
1779 | + return override[1]; |
1780 | + } |
1781 | + } |
1782 | + return null; |
1783 | +} |
1784 | + |
1785 | +exports.onBeforeSendHeaders = function(event) { |
1786 | + var override = getUAoverride(event.url); |
1787 | + if (override !== null) { |
1788 | + event.setHeader("User-Agent", override); |
1789 | + oxide.sendMessage({url: event.url, override: override}); |
1790 | + } |
1791 | +} |
1792 | + |
1793 | +exports.onGetUserAgentOverride = function(data) { |
1794 | + var override = getUAoverride(event.url); |
1795 | + if (override !== null) { |
1796 | + data.userAgentOverride = override; |
1797 | + } |
1798 | +} |
1799 | |
1800 | === modified file 'src/app/AlertDialog.qml' |
1801 | --- src/app/AlertDialog.qml 2013-09-21 19:56:15 +0000 |
1802 | +++ src/app/AlertDialog.qml 2014-03-28 17:03:06 +0000 |
1803 | @@ -26,8 +26,8 @@ |
1804 | |
1805 | Button { |
1806 | text: i18n.tr("OK") |
1807 | - onClicked: model.dismiss() |
1808 | + onClicked: model.accept() |
1809 | } |
1810 | |
1811 | Component.onCompleted: show() |
1812 | -} |
1813 | \ No newline at end of file |
1814 | +} |
1815 | |
1816 | === added file 'src/app/BeforeUnloadDialog.qml' |
1817 | --- src/app/BeforeUnloadDialog.qml 1970-01-01 00:00:00 +0000 |
1818 | +++ src/app/BeforeUnloadDialog.qml 2014-03-28 17:03:06 +0000 |
1819 | @@ -0,0 +1,38 @@ |
1820 | +/* |
1821 | + * Copyright 2014 Canonical Ltd. |
1822 | + * |
1823 | + * This file is part of webbrowser-app. |
1824 | + * |
1825 | + * webbrowser-app is free software; you can redistribute it and/or modify |
1826 | + * it under the terms of the GNU General Public License as published by |
1827 | + * the Free Software Foundation; version 3. |
1828 | + * |
1829 | + * webbrowser-app is distributed in the hope that it will be useful, |
1830 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1831 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1832 | + * GNU General Public License for more details. |
1833 | + * |
1834 | + * You should have received a copy of the GNU General Public License |
1835 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1836 | + */ |
1837 | + |
1838 | +import QtQuick 2.0 |
1839 | +import Ubuntu.Components 0.1 |
1840 | +import Ubuntu.Components.Popups 0.1 as Popups |
1841 | + |
1842 | +Popups.Dialog { |
1843 | + title: i18n.tr("Confirm Navigation") |
1844 | + text: model.message |
1845 | + |
1846 | + Button { |
1847 | + text: i18n.tr("Leave") |
1848 | + onClicked: model.accept() |
1849 | + } |
1850 | + |
1851 | + Button { |
1852 | + text: i18n.tr("Stay") |
1853 | + onClicked: model.reject() |
1854 | + } |
1855 | + |
1856 | + Component.onCompleted: show() |
1857 | +} |
1858 | |
1859 | === modified file 'src/app/CMakeLists.txt' |
1860 | --- src/app/CMakeLists.txt 2014-03-13 07:33:10 +0000 |
1861 | +++ src/app/CMakeLists.txt 2014-03-28 17:03:06 +0000 |
1862 | @@ -16,6 +16,8 @@ |
1863 | |
1864 | qt5_use_modules(${COMMONLIB} Core Network Qml Quick Widgets) |
1865 | |
1866 | +include_directories(${Qt5Quick_PRIVATE_INCLUDE_DIRS}) |
1867 | + |
1868 | file(GLOB QML_FILES *.qml) |
1869 | install(FILES ${QML_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app) |
1870 | install(DIRECTORY actions DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app |
1871 | |
1872 | === modified file 'src/app/PanelLoader.qml' |
1873 | --- src/app/PanelLoader.qml 2013-11-15 17:04:27 +0000 |
1874 | +++ src/app/PanelLoader.qml 2014-03-28 17:03:06 +0000 |
1875 | @@ -75,7 +75,10 @@ |
1876 | |
1877 | url: currentWebview ? currentWebview.url : "" |
1878 | |
1879 | - loading: currentWebview ? currentWebview.loading || (currentWebview.loadProgress === 0) : false |
1880 | + loading: currentWebview ? currentWebview.loading |
1881 | + // workaround for https://bugs.launchpad.net/oxide/+bug/1290821 |
1882 | + && !currentWebview.lastLoadStopped |
1883 | + : false |
1884 | loadProgress: currentWebview ? currentWebview.loadProgress : 0 |
1885 | |
1886 | canGoBack: currentWebview ? currentWebview.canGoBack : false |
1887 | |
1888 | === modified file 'src/app/PromptDialog.qml' |
1889 | --- src/app/PromptDialog.qml 2013-09-21 20:06:03 +0000 |
1890 | +++ src/app/PromptDialog.qml 2014-03-28 17:03:06 +0000 |
1891 | @@ -42,5 +42,11 @@ |
1892 | onClicked: model.reject() |
1893 | } |
1894 | |
1895 | + Binding { |
1896 | + target: model |
1897 | + property: "currentValue" |
1898 | + value: input.text |
1899 | + } |
1900 | + |
1901 | Component.onCompleted: show() |
1902 | -} |
1903 | \ No newline at end of file |
1904 | +} |
1905 | |
1906 | === modified file 'src/app/WebViewImpl.qml' |
1907 | --- src/app/WebViewImpl.qml 2014-03-13 10:16:20 +0000 |
1908 | +++ src/app/WebViewImpl.qml 2014-03-28 17:03:06 +0000 |
1909 | @@ -17,12 +17,10 @@ |
1910 | */ |
1911 | |
1912 | import QtQuick 2.0 |
1913 | -import QtWebKit 3.1 |
1914 | -import QtWebKit.experimental 1.0 |
1915 | -import Ubuntu.Components 0.1 |
1916 | -import Ubuntu.Components.Extras.Browser 0.1 |
1917 | -import Ubuntu.Components.Popups 0.1 |
1918 | -import "actions" as Actions |
1919 | +//import Ubuntu.Components 0.1 |
1920 | +import Ubuntu.Components.Extras.Browser 0.2 |
1921 | +//import Ubuntu.Components.Popups 0.1 |
1922 | +//import "actions" as Actions |
1923 | |
1924 | UbuntuWebView { |
1925 | id: webview |
1926 | @@ -30,20 +28,21 @@ |
1927 | property var currentWebview: webview |
1928 | property var toolbar: null |
1929 | |
1930 | - experimental.certificateVerificationDialog: CertificateVerificationDialog {} |
1931 | + /*experimental.certificateVerificationDialog: CertificateVerificationDialog {} |
1932 | experimental.authenticationDialog: AuthenticationDialog {} |
1933 | - experimental.proxyAuthenticationDialog: ProxyAuthenticationDialog {} |
1934 | - experimental.alertDialog: AlertDialog {} |
1935 | - experimental.confirmDialog: ConfirmDialog {} |
1936 | - experimental.promptDialog: PromptDialog {} |
1937 | + experimental.proxyAuthenticationDialog: ProxyAuthenticationDialog {}*/ |
1938 | + /*alertDialog: AlertDialog {} |
1939 | + confirmDialog: ConfirmDialog {} |
1940 | + promptDialog: PromptDialog {} |
1941 | + beforeUnloadDialog: BeforeUnloadDialog {}*/ |
1942 | |
1943 | - selectionActions: ActionList { |
1944 | + /*selectionActions: ActionList { |
1945 | Actions.Copy { |
1946 | onTriggered: selection.copy() |
1947 | } |
1948 | - } |
1949 | + }*/ |
1950 | |
1951 | - experimental.onPermissionRequested: { |
1952 | + /*experimental.onPermissionRequested: { |
1953 | if (permission.type === PermissionRequest.Geolocation) { |
1954 | if (webview.toolbar) { |
1955 | webview.toolbar.close() |
1956 | @@ -56,8 +55,5 @@ |
1957 | // TODO: handle other types of permission requests |
1958 | // TODO: we might want to store the answer to avoid requesting |
1959 | // the permission everytime the user visits this site. |
1960 | - } |
1961 | - |
1962 | - property int lastLoadRequestStatus: -1 |
1963 | - onLoadingChanged: lastLoadRequestStatus = loadRequest.status |
1964 | + }*/ |
1965 | } |
1966 | |
1967 | === modified file 'src/app/browserapplication.cpp' |
1968 | --- src/app/browserapplication.cpp 2014-03-14 14:51:22 +0000 |
1969 | +++ src/app/browserapplication.cpp 2014-03-28 17:03:06 +0000 |
1970 | @@ -17,10 +17,13 @@ |
1971 | */ |
1972 | |
1973 | // Qt |
1974 | +#include <QtCore/QLibrary> |
1975 | #include <QtNetwork/QNetworkInterface> |
1976 | +#include <QtGui/QOpenGLContext> |
1977 | #include <QtQml/QQmlComponent> |
1978 | #include <QtQml/QQmlContext> |
1979 | #include <QtQml/QQmlEngine> |
1980 | +#include <QtQuick/private/qsgcontext_p.h> |
1981 | #include <QtQuick/QQuickWindow> |
1982 | |
1983 | // local |
1984 | @@ -29,7 +32,7 @@ |
1985 | #include "webbrowser-window.h" |
1986 | |
1987 | BrowserApplication::BrowserApplication(int& argc, char** argv) |
1988 | - : QApplication(argc, argv) |
1989 | + : QGuiApplication(argc, argv) |
1990 | , m_engine(0) |
1991 | , m_window(0) |
1992 | , m_component(0) |
1993 | @@ -37,6 +40,25 @@ |
1994 | { |
1995 | m_arguments = arguments(); |
1996 | m_arguments.removeFirst(); |
1997 | + |
1998 | + // The testability driver is only loaded by QApplication but not by |
1999 | + // QGuiApplication (see https://codereview.qt-project.org/#change,66513). |
2000 | + // Let’s load the testability driver on our own. |
2001 | + if (m_arguments.contains(QLatin1String("-testability")) || |
2002 | + qgetenv("QT_LOAD_TESTABILITY") == "1") { |
2003 | + QLibrary testLib(QLatin1String("qttestability")); |
2004 | + if (testLib.load()) { |
2005 | + typedef void (*TasInitialize)(void); |
2006 | + TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); |
2007 | + if (initFunction) { |
2008 | + initFunction(); |
2009 | + } else { |
2010 | + qCritical("Library qttestability resolve failed!"); |
2011 | + } |
2012 | + } else { |
2013 | + qCritical("Library qttestability load failed!"); |
2014 | + } |
2015 | + } |
2016 | } |
2017 | |
2018 | BrowserApplication::~BrowserApplication() |
2019 | @@ -80,6 +102,11 @@ |
2020 | QString appPkgName = qgetenv("APP_ID").split('_').first(); |
2021 | QCoreApplication::setApplicationName(appPkgName); |
2022 | |
2023 | + // Enable compositing in oxide |
2024 | + QOpenGLContext* glcontext = new QOpenGLContext(this); |
2025 | + glcontext->create(); |
2026 | + QSGContext::setSharedOpenGLContext(glcontext); |
2027 | + |
2028 | bool inspector = m_arguments.contains("--inspector"); |
2029 | if (inspector) { |
2030 | QString host; |
2031 | @@ -113,7 +140,7 @@ |
2032 | m_webbrowserWindowProxy = new WebBrowserWindow(); |
2033 | context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy); |
2034 | |
2035 | - QObject* browser = m_component->create(); |
2036 | + QObject* browser = m_component->beginCreate(context); |
2037 | m_window = qobject_cast<QQuickWindow*>(browser); |
2038 | m_webbrowserWindowProxy->setWindow(m_window); |
2039 | |
2040 | |
2041 | === modified file 'src/app/browserapplication.h' |
2042 | --- src/app/browserapplication.h 2014-03-14 14:51:22 +0000 |
2043 | +++ src/app/browserapplication.h 2014-03-28 17:03:06 +0000 |
2044 | @@ -24,14 +24,14 @@ |
2045 | #include <QtCore/QString> |
2046 | #include <QtCore/QStringList> |
2047 | #include <QtCore/QUrl> |
2048 | -#include <QtWidgets/QApplication> |
2049 | +#include <QtGui/QGuiApplication> |
2050 | |
2051 | class QQmlComponent; |
2052 | class QQmlEngine; |
2053 | class QQuickWindow; |
2054 | class WebBrowserWindow; |
2055 | |
2056 | -class BrowserApplication : public QApplication |
2057 | +class BrowserApplication : public QGuiApplication |
2058 | { |
2059 | Q_OBJECT |
2060 | |
2061 | @@ -49,11 +49,11 @@ |
2062 | QStringList m_arguments; |
2063 | QQmlEngine* m_engine; |
2064 | QQuickWindow* m_window; |
2065 | + QQmlComponent* m_component; |
2066 | |
2067 | private: |
2068 | QString appId() const; |
2069 | |
2070 | - QQmlComponent* m_component; |
2071 | WebBrowserWindow *m_webbrowserWindowProxy; |
2072 | }; |
2073 | |
2074 | |
2075 | === modified file 'src/app/webbrowser/BookmarksView.qml' |
2076 | --- src/app/webbrowser/BookmarksView.qml 2014-03-12 22:45:12 +0000 |
2077 | +++ src/app/webbrowser/BookmarksView.qml 2014-03-28 17:03:06 +0000 |
2078 | @@ -50,8 +50,8 @@ |
2079 | url: model.url |
2080 | label: model.title ? model.title : model.url |
2081 | |
2082 | - property url thumbnailSource: "image://webthumbnail/" + model.url |
2083 | - thumbnail: WebThumbnailer.thumbnailExists(model.url) ? thumbnailSource : "" |
2084 | + //property url thumbnailSource: "image://webthumbnail/" + model.url |
2085 | + //thumbnail: WebThumbnailer.thumbnailExists(model.url) ? thumbnailSource : "" |
2086 | |
2087 | canBookmark: true |
2088 | bookmarksModel: bookmarksView.bookmarksModel |
2089 | |
2090 | === modified file 'src/app/webbrowser/Browser.qml' |
2091 | --- src/app/webbrowser/Browser.qml 2014-03-13 10:16:20 +0000 |
2092 | +++ src/app/webbrowser/Browser.qml 2014-03-28 17:03:06 +0000 |
2093 | @@ -17,8 +17,6 @@ |
2094 | */ |
2095 | |
2096 | import QtQuick 2.0 |
2097 | -import QtWebKit 3.1 |
2098 | -import QtWebKit.experimental 1.0 |
2099 | import Ubuntu.Components 0.1 |
2100 | import webbrowserapp.private 0.1 |
2101 | import "../actions" as Actions |
2102 | @@ -48,7 +46,7 @@ |
2103 | }, |
2104 | Actions.Bookmark { |
2105 | enabled: currentWebview |
2106 | - onTriggered: bookmarksModel.add(currentWebview.url, currentWebview.title, currentWebview.icon) |
2107 | + onTriggered: bookmarksModel.add(currentWebview.url, currentWebview.title, "")//currentWebview.icon) |
2108 | }, |
2109 | Actions.NewTab { |
2110 | onTriggered: newTab("", true) |
2111 | @@ -73,7 +71,7 @@ |
2112 | |
2113 | ErrorSheet { |
2114 | anchors.fill: webviewContainer |
2115 | - visible: currentWebview ? (currentWebview.lastLoadRequestStatus === WebView.LoadFailedStatus) : false |
2116 | + visible: currentWebview ? currentWebview.lastLoadFailed : false |
2117 | url: currentWebview ? currentWebview.url : "" |
2118 | onRefreshClicked: currentWebview.reload() |
2119 | } |
2120 | @@ -217,7 +215,7 @@ |
2121 | enabled: stack.depth === 0 |
2122 | visible: currentWebview === webview |
2123 | |
2124 | - experimental.preferences.developerExtrasEnabled: developerExtrasEnabled |
2125 | + //experimental.preferences.developerExtrasEnabled: developerExtrasEnabled |
2126 | |
2127 | contextualActions: ActionList { |
2128 | Actions.OpenLinkInNewTab { |
2129 | @@ -244,25 +242,9 @@ |
2130 | |
2131 | onNewTabRequested: newTab(url, true) |
2132 | |
2133 | - WebviewThumbnailer { |
2134 | - id: thumbnailer |
2135 | - webview: webview |
2136 | - targetSize: Qt.size(units.gu(12), units.gu(12)) |
2137 | - property url thumbnailSource: "image://webthumbnail/" + webview.url |
2138 | - onThumbnailRendered: { |
2139 | - if (url == webview.url) { |
2140 | - webview.thumbnail = thumbnailer.thumbnailSource |
2141 | - } |
2142 | - } |
2143 | - } |
2144 | - property url thumbnail: (url && thumbnailer.thumbnailExists()) ? thumbnailer.thumbnailSource : "" |
2145 | - |
2146 | onLoadingChanged: { |
2147 | - if (loadRequest.status === WebView.LoadSucceededStatus) { |
2148 | + if (lastLoadSucceeded) { |
2149 | _historyModel.add(webview.url, webview.title, webview.icon) |
2150 | - if (!thumbnailer.thumbnailExists()) { |
2151 | - thumbnailer.renderThumbnail() |
2152 | - } |
2153 | } |
2154 | } |
2155 | } |
2156 | |
2157 | === modified file 'src/app/webbrowser/CMakeLists.txt' |
2158 | --- src/app/webbrowser/CMakeLists.txt 2014-03-13 07:30:35 +0000 |
2159 | +++ src/app/webbrowser/CMakeLists.txt 2014-03-28 17:03:06 +0000 |
2160 | @@ -19,25 +19,13 @@ |
2161 | bookmarks-model.cpp |
2162 | settings.cpp |
2163 | webbrowser-app.cpp |
2164 | - webthumbnail-provider.cpp |
2165 | - webthumbnail-utils.cpp |
2166 | - webview-thumbnailer.cpp |
2167 | ) |
2168 | |
2169 | add_executable(${WEBBROWSER_APP} ${WEBBROWSER_APP_SRC}) |
2170 | |
2171 | target_link_libraries(${WEBBROWSER_APP} ${COMMONLIB}) |
2172 | |
2173 | -qt5_use_modules(${WEBBROWSER_APP} Core Gui Quick Sql WebKit) |
2174 | - |
2175 | -# work around the lack of a public cmake module for Qt5V8 |
2176 | -set(Qt5V8_PRIVATE_INCLUDE_DIRS |
2177 | - "/usr/include/qt5/QtV8/${Qt5Qml_VERSION_STRING}" |
2178 | - "/usr/include/qt5/QtV8/${Qt5Qml_VERSION_STRING}/QtV8") |
2179 | -include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS} |
2180 | - ${Qt5V8_PRIVATE_INCLUDE_DIRS} |
2181 | - ${Qt5Quick_PRIVATE_INCLUDE_DIRS} |
2182 | - ${Qt5WebKit_PRIVATE_INCLUDE_DIRS}) |
2183 | +qt5_use_modules(${WEBBROWSER_APP} Core Gui Quick Sql) |
2184 | |
2185 | install(TARGETS ${WEBBROWSER_APP} |
2186 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) |
2187 | |
2188 | === modified file 'src/app/webbrowser/TabsList.qml' |
2189 | --- src/app/webbrowser/TabsList.qml 2014-03-12 22:45:12 +0000 |
2190 | +++ src/app/webbrowser/TabsList.qml 2014-03-28 17:03:06 +0000 |
2191 | @@ -82,7 +82,7 @@ |
2192 | |
2193 | url: model.url |
2194 | label: model.title ? model.title : model.url |
2195 | - thumbnail: model.webview.thumbnail |
2196 | + //thumbnail: model.webview.thumbnail |
2197 | canClose: true |
2198 | |
2199 | onStateChanged: listview.state = state |
2200 | |
2201 | === modified file 'src/app/webbrowser/TimelineView.qml' |
2202 | --- src/app/webbrowser/TimelineView.qml 2014-03-12 22:45:12 +0000 |
2203 | +++ src/app/webbrowser/TimelineView.qml 2014-03-28 17:03:06 +0000 |
2204 | @@ -18,7 +18,7 @@ |
2205 | |
2206 | import QtQuick 2.0 |
2207 | import Ubuntu.Components 0.1 |
2208 | -import Ubuntu.Components.Extras.Browser 0.1 |
2209 | +//import Ubuntu.Components.Extras.Browser 0.1 |
2210 | import Ubuntu.Components.ListItems 0.1 as ListItem |
2211 | import webbrowserapp.private 0.1 |
2212 | |
2213 | @@ -173,8 +173,8 @@ |
2214 | url: model.url |
2215 | label: model.title ? model.title : model.url |
2216 | |
2217 | - property url thumbnailSource: "image://webthumbnail/" + model.url |
2218 | - thumbnail: WebThumbnailer.thumbnailExists(model.url) ? thumbnailSource : "" |
2219 | + //property url thumbnailSource: "image://webthumbnail/" + model.url |
2220 | + //thumbnail: WebThumbnailer.thumbnailExists(model.url) ? thumbnailSource : "" |
2221 | |
2222 | canBookmark: true |
2223 | bookmarksModel: timelineView.bookmarksModel |
2224 | @@ -282,8 +282,8 @@ |
2225 | } |
2226 | } |
2227 | |
2228 | - property url thumbnailSource: "image://webthumbnail/" + model.domain |
2229 | - thumbnail: WebThumbnailer.thumbnailExists(model.domain) ? thumbnailSource : "" |
2230 | + //property url thumbnailSource: "image://webthumbnail/" + model.domain |
2231 | + //thumbnail: WebThumbnailer.thumbnailExists(model.domain) ? thumbnailSource : "" |
2232 | |
2233 | onClicked: { |
2234 | if ((timeline.currentIndex == timelineIndex) && |
2235 | |
2236 | === modified file 'src/app/webbrowser/webbrowser-app.cpp' |
2237 | --- src/app/webbrowser/webbrowser-app.cpp 2014-03-12 23:09:21 +0000 |
2238 | +++ src/app/webbrowser/webbrowser-app.cpp 2014-03-28 17:03:06 +0000 |
2239 | @@ -26,9 +26,6 @@ |
2240 | #include "settings.h" |
2241 | #include "tabs-model.h" |
2242 | #include "webbrowser-app.h" |
2243 | -#include "webthumbnail-provider.h" |
2244 | -#include "webthumbnail-utils.h" |
2245 | -#include "webview-thumbnailer.h" |
2246 | |
2247 | // system |
2248 | #include <string.h> |
2249 | @@ -41,23 +38,12 @@ |
2250 | #include <QtCore/QMetaObject> |
2251 | #include <QtCore/QString> |
2252 | #include <QtCore/QTextStream> |
2253 | -#include <QtCore/QThread> |
2254 | #include <QtQml/QtQml> |
2255 | #include <QtQuick/QQuickWindow> |
2256 | |
2257 | WebbrowserApp::WebbrowserApp(int& argc, char** argv) |
2258 | : BrowserApplication(argc, argv) |
2259 | - , m_thumbnailUtilsThread(0) |
2260 | -{ |
2261 | -} |
2262 | - |
2263 | -WebbrowserApp::~WebbrowserApp() |
2264 | -{ |
2265 | - if (m_thumbnailUtilsThread) { |
2266 | - m_thumbnailUtilsThread->quit(); |
2267 | - m_thumbnailUtilsThread->wait(); |
2268 | - delete m_thumbnailUtilsThread; |
2269 | - } |
2270 | +{ |
2271 | } |
2272 | |
2273 | bool WebbrowserApp::initialize() |
2274 | @@ -91,22 +77,9 @@ |
2275 | qmlRegisterType<HistoryDomainListChronologicalModel>(uri, 0, 1, "HistoryDomainListChronologicalModel"); |
2276 | qmlRegisterType<TabsModel>(uri, 0, 1, "TabsModel"); |
2277 | qmlRegisterType<BookmarksModel>(uri, 0, 1, "BookmarksModel"); |
2278 | - qmlRegisterType<WebviewThumbnailer>(uri, 0, 1, "WebviewThumbnailer"); |
2279 | |
2280 | if (BrowserApplication::initialize("webbrowser/webbrowser-app.qml")) { |
2281 | m_window->setProperty("chromeless", m_arguments.contains("--chromeless")); |
2282 | - |
2283 | - // This singleton lives in its own thread to ensure that |
2284 | - // disk I/O is not performed in the UI thread. |
2285 | - WebThumbnailUtils& utils = WebThumbnailUtils::instance(); |
2286 | - m_thumbnailUtilsThread = new QThread; |
2287 | - utils.moveToThread(m_thumbnailUtilsThread); |
2288 | - m_thumbnailUtilsThread->start(); |
2289 | - |
2290 | - WebThumbnailProvider* thumbnailer = new WebThumbnailProvider; |
2291 | - m_engine->addImageProvider(QLatin1String("webthumbnail"), thumbnailer); |
2292 | - m_engine->rootContext()->setContextProperty("WebThumbnailer", thumbnailer); |
2293 | - |
2294 | QList<QUrl> urls = this->urls(); |
2295 | if (urls.isEmpty()) { |
2296 | Settings settings; |
2297 | @@ -116,6 +89,9 @@ |
2298 | Q_FOREACH(const QUrl& url, urls) { |
2299 | QMetaObject::invokeMethod(browser, "newTab", Q_ARG(QVariant, url), Q_ARG(QVariant, true)); |
2300 | } |
2301 | + |
2302 | + m_component->completeCreate(); |
2303 | + |
2304 | return true; |
2305 | } else { |
2306 | return false; |
2307 | |
2308 | === modified file 'src/app/webbrowser/webbrowser-app.h' |
2309 | --- src/app/webbrowser/webbrowser-app.h 2014-03-12 23:09:21 +0000 |
2310 | +++ src/app/webbrowser/webbrowser-app.h 2014-03-28 17:03:06 +0000 |
2311 | @@ -21,22 +21,17 @@ |
2312 | |
2313 | #include "browserapplication.h" |
2314 | |
2315 | -class QThread; |
2316 | - |
2317 | class WebbrowserApp : public BrowserApplication |
2318 | { |
2319 | Q_OBJECT |
2320 | |
2321 | public: |
2322 | WebbrowserApp(int& argc, char** argv); |
2323 | - ~WebbrowserApp(); |
2324 | |
2325 | bool initialize(); |
2326 | |
2327 | private: |
2328 | virtual void printUsage() const; |
2329 | - |
2330 | - QThread* m_thumbnailUtilsThread; |
2331 | }; |
2332 | |
2333 | #endif // __WEBBROWSER_APP_H__ |
2334 | |
2335 | === removed file 'src/app/webbrowser/webthumbnail-provider.cpp' |
2336 | --- src/app/webbrowser/webthumbnail-provider.cpp 2014-03-12 23:09:21 +0000 |
2337 | +++ src/app/webbrowser/webthumbnail-provider.cpp 1970-01-01 00:00:00 +0000 |
2338 | @@ -1,53 +0,0 @@ |
2339 | -/* |
2340 | - * Copyright 2013 Canonical Ltd. |
2341 | - * |
2342 | - * This file is part of webbrowser-app. |
2343 | - * |
2344 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2345 | - * it under the terms of the GNU General Public License as published by |
2346 | - * the Free Software Foundation; version 3. |
2347 | - * |
2348 | - * webbrowser-app is distributed in the hope that it will be useful, |
2349 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2350 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2351 | - * GNU General Public License for more details. |
2352 | - * |
2353 | - * You should have received a copy of the GNU General Public License |
2354 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2355 | - */ |
2356 | - |
2357 | -#include "webthumbnail-provider.h" |
2358 | -#include "webthumbnail-utils.h" |
2359 | - |
2360 | -// Qt |
2361 | -#include <QtCore/QDebug> |
2362 | -#include <QtGui/QImageReader> |
2363 | - |
2364 | -WebThumbnailProvider::WebThumbnailProvider(QObject* parent) |
2365 | - : QObject(parent) |
2366 | - , QQuickImageProvider(QQuickImageProvider::Image) |
2367 | -{ |
2368 | -} |
2369 | - |
2370 | -QImage WebThumbnailProvider::requestImage(const QString& id, QSize* size, const QSize& requestedSize) |
2371 | -{ |
2372 | - QImage image; |
2373 | - QFileInfo cached = WebThumbnailUtils::thumbnailFile(QUrl(id)); |
2374 | - if (cached.exists()) { |
2375 | - QImageReader reader(cached.absoluteFilePath(), "PNG"); |
2376 | - if (requestedSize.isValid()) { |
2377 | - reader.setScaledSize(requestedSize); |
2378 | - } |
2379 | - *size = reader.size(); |
2380 | - reader.read(&image); |
2381 | - if (image.isNull()) { |
2382 | - qWarning() << "Failed to load cached thumbnail:" << reader.errorString(); |
2383 | - } |
2384 | - } |
2385 | - return image; |
2386 | -} |
2387 | - |
2388 | -bool WebThumbnailProvider::thumbnailExists(const QUrl& url) const |
2389 | -{ |
2390 | - return WebThumbnailUtils::thumbnailFile(url).exists(); |
2391 | -} |
2392 | |
2393 | === removed file 'src/app/webbrowser/webthumbnail-provider.h' |
2394 | --- src/app/webbrowser/webthumbnail-provider.h 2014-03-12 23:09:21 +0000 |
2395 | +++ src/app/webbrowser/webthumbnail-provider.h 1970-01-01 00:00:00 +0000 |
2396 | @@ -1,39 +0,0 @@ |
2397 | -/* |
2398 | - * Copyright 2013 Canonical Ltd. |
2399 | - * |
2400 | - * This file is part of webbrowser-app. |
2401 | - * |
2402 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2403 | - * it under the terms of the GNU General Public License as published by |
2404 | - * the Free Software Foundation; version 3. |
2405 | - * |
2406 | - * webbrowser-app is distributed in the hope that it will be useful, |
2407 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2408 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2409 | - * GNU General Public License for more details. |
2410 | - * |
2411 | - * You should have received a copy of the GNU General Public License |
2412 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2413 | - */ |
2414 | - |
2415 | -#ifndef __WEBTHUMBNAIL_PROVIDER_H__ |
2416 | -#define __WEBTHUMBNAIL_PROVIDER_H__ |
2417 | - |
2418 | -// Qt |
2419 | -#include <QtCore/QObject> |
2420 | -#include <QtCore/QUrl> |
2421 | -#include <QtQuick/QQuickImageProvider> |
2422 | - |
2423 | -class WebThumbnailProvider : public QObject, public QQuickImageProvider |
2424 | -{ |
2425 | - Q_OBJECT |
2426 | - |
2427 | -public: |
2428 | - WebThumbnailProvider(QObject* parent=0); |
2429 | - |
2430 | - virtual QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize); |
2431 | - |
2432 | - Q_INVOKABLE bool thumbnailExists(const QUrl& url) const; |
2433 | -}; |
2434 | - |
2435 | -#endif // __WEBTHUMBNAIL_PROVIDER_H__ |
2436 | |
2437 | === removed file 'src/app/webbrowser/webthumbnail-utils.cpp' |
2438 | --- src/app/webbrowser/webthumbnail-utils.cpp 2014-03-12 23:09:21 +0000 |
2439 | +++ src/app/webbrowser/webthumbnail-utils.cpp 1970-01-01 00:00:00 +0000 |
2440 | @@ -1,108 +0,0 @@ |
2441 | -/* |
2442 | - * Copyright 2013 Canonical Ltd. |
2443 | - * |
2444 | - * This file is part of webbrowser-app. |
2445 | - * |
2446 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2447 | - * it under the terms of the GNU General Public License as published by |
2448 | - * the Free Software Foundation; version 3. |
2449 | - * |
2450 | - * webbrowser-app is distributed in the hope that it will be useful, |
2451 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2452 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2453 | - * GNU General Public License for more details. |
2454 | - * |
2455 | - * You should have received a copy of the GNU General Public License |
2456 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2457 | - */ |
2458 | - |
2459 | -#include "domain-utils.h" |
2460 | -#include "webthumbnail-utils.h" |
2461 | - |
2462 | -// Qt |
2463 | -#include <QtCore/QCryptographicHash> |
2464 | -#include <QtCore/QFile> |
2465 | -#include <QtCore/QStandardPaths> |
2466 | -#include <QtCore/QUrl> |
2467 | -#include <QtGui/QImage> |
2468 | - |
2469 | -#define MAX_CACHE_SIZE_IN_BYTES 5 * 1024 * 1024 // 5MB |
2470 | - |
2471 | -WebThumbnailUtils::WebThumbnailUtils(QObject* parent) |
2472 | - : QObject(parent) |
2473 | -{ |
2474 | -} |
2475 | - |
2476 | -WebThumbnailUtils& WebThumbnailUtils::instance() |
2477 | -{ |
2478 | - static WebThumbnailUtils utils; |
2479 | - return utils; |
2480 | -} |
2481 | - |
2482 | -WebThumbnailUtils::~WebThumbnailUtils() |
2483 | -{ |
2484 | -} |
2485 | - |
2486 | -QDir WebThumbnailUtils::cacheLocation() |
2487 | -{ |
2488 | - return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/thumbnails"; |
2489 | -} |
2490 | - |
2491 | -void WebThumbnailUtils::ensureCacheLocation() |
2492 | -{ |
2493 | - QDir cache = cacheLocation(); |
2494 | - if (!cache.exists()) { |
2495 | - QDir::root().mkpath(cache.absolutePath()); |
2496 | - } |
2497 | -} |
2498 | - |
2499 | -QFileInfo WebThumbnailUtils::thumbnailFile(const QUrl& url) |
2500 | -{ |
2501 | - QString hash(QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Md5).toHex()); |
2502 | - return cacheLocation().absoluteFilePath(hash + ".png"); |
2503 | -} |
2504 | - |
2505 | -void WebThumbnailUtils::cacheThumbnail(const QUrl& url, const QImage& thumbnail) const |
2506 | -{ |
2507 | - ensureCacheLocation(); |
2508 | - QFileInfo file = thumbnailFile(url); |
2509 | - bool saved = thumbnail.save(file.absoluteFilePath()); |
2510 | - |
2511 | - if (saved) { |
2512 | - // Make a link to the thumbnail file for the corresponding domain’s thumbnail. |
2513 | - QUrl domain(DomainUtils::extractTopLevelDomainName(url)); |
2514 | - QString domainThumbnail = WebThumbnailUtils::thumbnailFile(domain).absoluteFilePath(); |
2515 | - if (QFile::exists(domainThumbnail)) { |
2516 | - QFile::remove(domainThumbnail); |
2517 | - } |
2518 | - QFile::link(file.fileName(), domainThumbnail); |
2519 | - } |
2520 | - |
2521 | - expireCache(); |
2522 | -} |
2523 | - |
2524 | -void WebThumbnailUtils::expireCache() const |
2525 | -{ |
2526 | - QDir cache = cacheLocation(); |
2527 | - if (!cache.exists()) { |
2528 | - return; |
2529 | - } |
2530 | - QStringList nameFilters = QStringList() << "*.png"; |
2531 | - QDir::Filters filters = QDir::Files | QDir::NoDotAndDotDot; |
2532 | - QDir::SortFlags sort = QDir::Time; |
2533 | - QFileInfoList entries = cache.entryInfoList(nameFilters, filters, sort); |
2534 | - qint64 currentSize = 0; |
2535 | - Q_FOREACH(const QFileInfo& entry, entries) { |
2536 | - currentSize += entry.size(); |
2537 | - } |
2538 | - if (currentSize > MAX_CACHE_SIZE_IN_BYTES) { |
2539 | - qint64 goal = MAX_CACHE_SIZE_IN_BYTES * 9 / 10; |
2540 | - while (!entries.isEmpty() && (currentSize > goal)) { |
2541 | - QFileInfo entry = entries.takeLast(); |
2542 | - qint64 size = entry.size(); |
2543 | - if (QFile::remove(entry.absoluteFilePath())) { |
2544 | - currentSize -= size; |
2545 | - } |
2546 | - } |
2547 | - } |
2548 | -} |
2549 | |
2550 | === removed file 'src/app/webbrowser/webthumbnail-utils.h' |
2551 | --- src/app/webbrowser/webthumbnail-utils.h 2014-03-12 23:09:21 +0000 |
2552 | +++ src/app/webbrowser/webthumbnail-utils.h 1970-01-01 00:00:00 +0000 |
2553 | @@ -1,51 +0,0 @@ |
2554 | -/* |
2555 | - * Copyright 2013 Canonical Ltd. |
2556 | - * |
2557 | - * This file is part of webbrowser-app. |
2558 | - * |
2559 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2560 | - * it under the terms of the GNU General Public License as published by |
2561 | - * the Free Software Foundation; version 3. |
2562 | - * |
2563 | - * webbrowser-app is distributed in the hope that it will be useful, |
2564 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2565 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2566 | - * GNU General Public License for more details. |
2567 | - * |
2568 | - * You should have received a copy of the GNU General Public License |
2569 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2570 | - */ |
2571 | - |
2572 | -#ifndef __WEBTHUMBNAIL_UTILS_H__ |
2573 | -#define __WEBTHUMBNAIL_UTILS_H__ |
2574 | - |
2575 | -// Qt |
2576 | -#include <QtCore/QDir> |
2577 | -#include <QtCore/QFileInfo> |
2578 | -#include <QtCore/QObject> |
2579 | - |
2580 | -class QImage; |
2581 | -class QUrl; |
2582 | - |
2583 | -class WebThumbnailUtils : public QObject |
2584 | -{ |
2585 | - Q_OBJECT |
2586 | - |
2587 | -public: |
2588 | - static WebThumbnailUtils& instance(); |
2589 | - ~WebThumbnailUtils(); |
2590 | - |
2591 | - static QDir cacheLocation(); |
2592 | - static void ensureCacheLocation(); |
2593 | - static QFileInfo thumbnailFile(const QUrl& url); |
2594 | - |
2595 | -public Q_SLOTS: |
2596 | - void cacheThumbnail(const QUrl& url, const QImage& thumbnail) const; |
2597 | - |
2598 | -private: |
2599 | - WebThumbnailUtils(QObject* parent=0); |
2600 | - |
2601 | - void expireCache() const; |
2602 | -}; |
2603 | - |
2604 | -#endif // __WEBTHUMBNAIL_UTILS_H__ |
2605 | |
2606 | === removed file 'src/app/webbrowser/webview-thumbnailer.cpp' |
2607 | --- src/app/webbrowser/webview-thumbnailer.cpp 2014-03-19 08:25:39 +0000 |
2608 | +++ src/app/webbrowser/webview-thumbnailer.cpp 1970-01-01 00:00:00 +0000 |
2609 | @@ -1,162 +0,0 @@ |
2610 | -/* |
2611 | - * Copyright 2013 Canonical Ltd. |
2612 | - * |
2613 | - * This file is part of webbrowser-app. |
2614 | - * |
2615 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2616 | - * it under the terms of the GNU General Public License as published by |
2617 | - * the Free Software Foundation; version 3. |
2618 | - * |
2619 | - * webbrowser-app is distributed in the hope that it will be useful, |
2620 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2621 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2622 | - * GNU General Public License for more details. |
2623 | - * |
2624 | - * You should have received a copy of the GNU General Public License |
2625 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2626 | - */ |
2627 | - |
2628 | -#include "webthumbnail-utils.h" |
2629 | -#include "webview-thumbnailer.h" |
2630 | - |
2631 | -// Qt |
2632 | -#include <QtCore/QtGlobal> |
2633 | -#include <QtCore/QMetaObject> |
2634 | -#include <QtCore/QTimer> |
2635 | -#include <QtQuick/private/qsgrenderer_p.h> |
2636 | -#include <QtWebKit/private/qquickwebpage_p.h> |
2637 | -#include <QtWebKit/private/qquickwebview_p.h> |
2638 | - |
2639 | -class BindableFbo : public QSGBindable |
2640 | -{ |
2641 | -public: |
2642 | - BindableFbo(QOpenGLFramebufferObject* fbo) : m_fbo(fbo) {} |
2643 | - virtual void bind() const { m_fbo->bind(); } |
2644 | - |
2645 | -private: |
2646 | - QOpenGLFramebufferObject *m_fbo; |
2647 | -}; |
2648 | - |
2649 | -WebviewThumbnailer::WebviewThumbnailer(QQuickItem* parent) |
2650 | - : QQuickItem(parent) |
2651 | - , m_webview(0) |
2652 | -{ |
2653 | -} |
2654 | - |
2655 | -QQuickWebView* WebviewThumbnailer::webview() const |
2656 | -{ |
2657 | - return m_webview; |
2658 | -} |
2659 | - |
2660 | -void WebviewThumbnailer::setWebview(QQuickWebView* webview) |
2661 | -{ |
2662 | - if (webview != m_webview) { |
2663 | - m_webview = webview; |
2664 | - setFlag(QQuickItem::ItemHasContents, false); |
2665 | - Q_EMIT webviewChanged(); |
2666 | - } |
2667 | -} |
2668 | - |
2669 | -const QSize& WebviewThumbnailer::targetSize() const |
2670 | -{ |
2671 | - return m_targetSize; |
2672 | -} |
2673 | - |
2674 | -void WebviewThumbnailer::setTargetSize(const QSize& targetSize) |
2675 | -{ |
2676 | - if (targetSize != m_targetSize) { |
2677 | - m_targetSize = targetSize; |
2678 | - Q_EMIT targetSizeChanged(); |
2679 | - } |
2680 | -} |
2681 | - |
2682 | -bool WebviewThumbnailer::thumbnailExists() const |
2683 | -{ |
2684 | - if (m_webview) { |
2685 | - QUrl url = m_webview->url(); |
2686 | - if (url.isValid()) { |
2687 | - return WebThumbnailUtils::thumbnailFile(url).exists(); |
2688 | - } |
2689 | - } |
2690 | - return false; |
2691 | -} |
2692 | - |
2693 | -void WebviewThumbnailer::renderThumbnail() |
2694 | -{ |
2695 | - // Delay the actual rendering to give all elements on the page |
2696 | - // a chance to be fully rendered. |
2697 | - QTimer::singleShot(1000, this, SLOT(doRenderThumbnail())); |
2698 | -} |
2699 | - |
2700 | -void WebviewThumbnailer::doRenderThumbnail() |
2701 | -{ |
2702 | - if (m_webview) { |
2703 | - setFlag(QQuickItem::ItemHasContents); |
2704 | - update(); |
2705 | - } |
2706 | -} |
2707 | - |
2708 | -QSGNode* WebviewThumbnailer::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData) |
2709 | -{ |
2710 | - Q_UNUSED(updatePaintNodeData); |
2711 | - |
2712 | - if (!(m_webview && (flags() & QQuickItem::ItemHasContents))) { |
2713 | - return oldNode; |
2714 | - } |
2715 | - setFlag(QQuickItem::ItemHasContents, false); |
2716 | - |
2717 | - QQuickWebPage* page = m_webview->page(); |
2718 | - qreal min = qMin(page->width(), page->height()); |
2719 | - QSize size(min, min); |
2720 | - |
2721 | - QSGNode* node = QQuickItemPrivate::get(page)->itemNode(); |
2722 | - QSGNode* parent = node->QSGNode::parent(); |
2723 | - QSGNode* previousSibling = node->previousSibling(); |
2724 | - if (parent) { |
2725 | - parent->removeChildNode(node); |
2726 | - } |
2727 | - QSGRootNode root; |
2728 | - root.appendChildNode(node); |
2729 | - |
2730 | - QSGRenderer* renderer; |
2731 | -#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) |
2732 | - renderer = QQuickItemPrivate::get(this)->sceneGraphContext()->createRenderer(); |
2733 | -#else |
2734 | - renderer = QQuickItemPrivate::get(this)->sceneGraphRenderContext()->createRenderer(); |
2735 | -#endif |
2736 | - renderer->setRootNode(static_cast<QSGRootNode*>(&root)); |
2737 | - |
2738 | - QOpenGLFramebufferObject fbo(size); |
2739 | - |
2740 | - renderer->setDeviceRect(size); |
2741 | - renderer->setViewportRect(size); |
2742 | - renderer->setProjectionMatrixToRect(QRectF(QPointF(), size)); |
2743 | - renderer->setClearColor(Qt::transparent); |
2744 | - |
2745 | - renderer->renderScene(BindableFbo(&fbo)); |
2746 | - |
2747 | - fbo.release(); |
2748 | - |
2749 | - const QUrl& url = m_webview->url(); |
2750 | - QImage image = fbo.toImage().scaled(m_targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); |
2751 | - |
2752 | - // Invoke the method asynchronously. |
2753 | - QMetaObject::invokeMethod(&WebThumbnailUtils::instance(), "cacheThumbnail", |
2754 | - Qt::QueuedConnection, Q_ARG(QUrl, url), Q_ARG(QImage, image)); |
2755 | - |
2756 | - root.removeChildNode(node); |
2757 | - renderer->setRootNode(0); |
2758 | - delete renderer; |
2759 | - |
2760 | - if (parent) { |
2761 | - if (previousSibling) { |
2762 | - parent->insertChildNodeAfter(node, previousSibling); |
2763 | - } else { |
2764 | - parent->prependChildNode(node); |
2765 | - } |
2766 | - } |
2767 | - |
2768 | - Q_EMIT thumbnailRendered(url); |
2769 | - |
2770 | - return oldNode; |
2771 | -} |
2772 | |
2773 | === removed file 'src/app/webbrowser/webview-thumbnailer.h' |
2774 | --- src/app/webbrowser/webview-thumbnailer.h 2014-03-19 08:25:39 +0000 |
2775 | +++ src/app/webbrowser/webview-thumbnailer.h 1970-01-01 00:00:00 +0000 |
2776 | @@ -1,64 +0,0 @@ |
2777 | -/* |
2778 | - * Copyright 2013 Canonical Ltd. |
2779 | - * |
2780 | - * This file is part of webbrowser-app. |
2781 | - * |
2782 | - * webbrowser-app is free software; you can redistribute it and/or modify |
2783 | - * it under the terms of the GNU General Public License as published by |
2784 | - * the Free Software Foundation; version 3. |
2785 | - * |
2786 | - * webbrowser-app is distributed in the hope that it will be useful, |
2787 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2788 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2789 | - * GNU General Public License for more details. |
2790 | - * |
2791 | - * You should have received a copy of the GNU General Public License |
2792 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2793 | - */ |
2794 | - |
2795 | -#ifndef __WEBVIEW_THUMBNAILER_H__ |
2796 | -#define __WEBVIEW_THUMBNAILER_H__ |
2797 | - |
2798 | -// Qt |
2799 | -#include <QtCore/QSize> |
2800 | -#include <QtCore/QUrl> |
2801 | -#include <QtQuick/private/qquickitem_p.h> |
2802 | - |
2803 | -class QQuickWebView; |
2804 | - |
2805 | -class WebviewThumbnailer : public QQuickItem |
2806 | -{ |
2807 | - Q_OBJECT |
2808 | - |
2809 | - Q_PROPERTY(QQuickWebView* webview READ webview WRITE setWebview NOTIFY webviewChanged) |
2810 | - Q_PROPERTY(QSize targetSize READ targetSize WRITE setTargetSize NOTIFY targetSizeChanged) |
2811 | - |
2812 | -public: |
2813 | - WebviewThumbnailer(QQuickItem* parent=0); |
2814 | - |
2815 | - QQuickWebView* webview() const; |
2816 | - void setWebview(QQuickWebView* webview); |
2817 | - |
2818 | - const QSize& targetSize() const; |
2819 | - void setTargetSize(const QSize& targetSize); |
2820 | - |
2821 | - Q_INVOKABLE bool thumbnailExists() const; |
2822 | - Q_INVOKABLE void renderThumbnail(); |
2823 | - |
2824 | -Q_SIGNALS: |
2825 | - void webviewChanged() const; |
2826 | - void targetSizeChanged() const; |
2827 | - void thumbnailRendered(const QUrl& url) const; |
2828 | - |
2829 | -protected: |
2830 | - virtual QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData); |
2831 | - |
2832 | -private Q_SLOTS: |
2833 | - void doRenderThumbnail(); |
2834 | - |
2835 | -private: |
2836 | - QQuickWebView* m_webview; |
2837 | - QSize m_targetSize; |
2838 | -}; |
2839 | - |
2840 | -#endif // __WEBVIEW_THUMBNAILER_H__ |
2841 | |
2842 | === modified file 'src/app/webcontainer/WebApp.qml' |
2843 | --- src/app/webcontainer/WebApp.qml 2014-03-20 18:17:12 +0000 |
2844 | +++ src/app/webcontainer/WebApp.qml 2014-03-28 17:03:06 +0000 |
2845 | @@ -17,8 +17,6 @@ |
2846 | */ |
2847 | |
2848 | import QtQuick 2.0 |
2849 | -import QtWebKit 3.1 |
2850 | -import QtWebKit.experimental 1.0 |
2851 | import Ubuntu.Components 0.1 |
2852 | import Ubuntu.Components.Popups 0.1 |
2853 | import Ubuntu.Unity.Action 1.0 as UnityActions |
2854 | @@ -29,20 +27,23 @@ |
2855 | BrowserView { |
2856 | id: webapp |
2857 | |
2858 | - currentWebview: webview |
2859 | + currentWebview: webview.currentWebview |
2860 | |
2861 | property alias url: webview.url |
2862 | - property string webappName: "" |
2863 | + |
2864 | property string webappModelSearchPath: "" |
2865 | - property var webappUrlPatterns: null |
2866 | + |
2867 | + property alias oxide: webview.withOxide |
2868 | + property alias webappName: webview.webappName |
2869 | + property alias webappUrlPatterns: webview.webappUrlPatterns |
2870 | |
2871 | actions: [ |
2872 | Actions.Back { |
2873 | - enabled: backForwardButtonsVisible && currentWebview.canGoBack |
2874 | + enabled: backForwardButtonsVisible && webview.currentWebview && webview.currentWebview.canGoBack |
2875 | onTriggered: webview.goBack() |
2876 | }, |
2877 | Actions.Forward { |
2878 | - enabled: backForwardButtonsVisible && currentWebview.canGoForward |
2879 | + enabled: backForwardButtonsVisible && webview.currentWebview && webview.currentWebview.canGoForward |
2880 | onTriggered: webview.goForward() |
2881 | }, |
2882 | Actions.Reload { |
2883 | @@ -58,10 +59,8 @@ |
2884 | // The UITK is trying too hard to be clever about the header and toolbar. |
2885 | flickable: null |
2886 | |
2887 | - WebViewImpl { |
2888 | + WebappContainerWebview { |
2889 | id: webview |
2890 | - |
2891 | - currentWebview: webview |
2892 | toolbar: panel.panel |
2893 | |
2894 | anchors { |
2895 | @@ -70,97 +69,17 @@ |
2896 | top: parent.top |
2897 | } |
2898 | height: parent.height - osk.height |
2899 | - |
2900 | - experimental.preferences.developerExtrasEnabled: developerExtrasEnabled |
2901 | - |
2902 | - contextualActions: ActionList { |
2903 | - Actions.CopyLink { |
2904 | - enabled: webview.contextualData.href.toString() |
2905 | - onTriggered: Clipboard.push([webview.contextualData.href]) |
2906 | - } |
2907 | - Actions.CopyImage { |
2908 | - enabled: webview.contextualData.img.toString() |
2909 | - onTriggered: Clipboard.push([webview.contextualData.img]) |
2910 | - } |
2911 | - } |
2912 | - |
2913 | - function haveValidUrlPatterns() { |
2914 | - return webappUrlPatterns && webappUrlPatterns.length !== 0 |
2915 | - } |
2916 | - |
2917 | - function navigationRequestedDelegate(request) { |
2918 | - if (!request.isMainFrame) { |
2919 | - request.action = WebView.AcceptRequest |
2920 | - return |
2921 | - } |
2922 | - |
2923 | - // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
2924 | - // or if we dont have a list of url patterns specified to filter the |
2925 | - // browsing actions |
2926 | - if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
2927 | - request.action = WebView.AcceptRequest |
2928 | - return |
2929 | - } |
2930 | - |
2931 | - var action = WebView.IgnoreRequest |
2932 | - var url = request.url.toString() |
2933 | - |
2934 | - // The list of url patterns defined by the webapp takes precedence over command line |
2935 | - if (isRunningAsANamedWebapp()) { |
2936 | - if (unityWebapps.model.exists(unityWebapps.name) && |
2937 | - unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
2938 | - request.action = WebView.AcceptRequest |
2939 | - return; |
2940 | - } |
2941 | - } |
2942 | - |
2943 | - // We still take the possible additional patterns specified in the command line |
2944 | - // (the in the case of finer grained ones specifically for the container and not |
2945 | - // as an 'install source' for the webapp). |
2946 | - if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
2947 | - for (var i = 0; i < webappUrlPatterns.length; ++i) { |
2948 | - var pattern = webappUrlPatterns[i] |
2949 | - if (url.match(pattern)) { |
2950 | - action = WebView.AcceptRequest |
2951 | - break |
2952 | - } |
2953 | - } |
2954 | - } |
2955 | - |
2956 | - request.action = action |
2957 | - if (action === WebView.IgnoreRequest) { |
2958 | - console.debug('Opening: ' + url + ' in the browser window.') |
2959 | - Qt.openUrlExternally(url) |
2960 | - } |
2961 | - } |
2962 | - |
2963 | - onNewTabRequested: Qt.openUrlExternally(url) |
2964 | - |
2965 | - // Small shim needed when running as a webapp to wire-up connections |
2966 | - // with the webview (message received, etc…). |
2967 | - // This is being called (and expected) internally by the webapps |
2968 | - // component as a way to bind to a webview lookalike without |
2969 | - // reaching out directly to its internals (see it as an interface). |
2970 | - function getUnityWebappsProxies() { |
2971 | - var eventHandlers = { |
2972 | - onAppRaised: function () { |
2973 | - if (webbrowserWindow) { |
2974 | - try { |
2975 | - webbrowserWindow.raise(); |
2976 | - } catch (e) { |
2977 | - console.debug('Error while raising: ' + e); |
2978 | - } |
2979 | - } |
2980 | - } |
2981 | - }; |
2982 | - return UnityWebAppsUtils.makeProxiesForQtWebViewBindee(webview, eventHandlers) |
2983 | - } |
2984 | + developerExtrasEnabled: webapp.developerExtrasEnabled |
2985 | } |
2986 | |
2987 | ErrorSheet { |
2988 | anchors.fill: webview |
2989 | - visible: webview.lastLoadRequestStatus == WebView.LoadFailedStatus |
2990 | - url: webview.url |
2991 | + visible: { |
2992 | + if (webview.lastLoadFailed !== undefined) |
2993 | + return webview.lastLoadFailed |
2994 | + return webview.currentWebview && webview.currentWebview.lastLoadFailed |
2995 | + } |
2996 | + url: webview.currentWebview.url |
2997 | onRefreshClicked: webview.reload() |
2998 | } |
2999 | } |
3000 | @@ -168,7 +87,7 @@ |
3001 | PanelLoader { |
3002 | id: panel |
3003 | |
3004 | - currentWebview: webview |
3005 | + currentWebview: webview.currentWebview |
3006 | chromeless: webapp.chromeless |
3007 | |
3008 | backForwardButtonsVisible: webapp.backForwardButtonsVisible |
3009 | @@ -185,12 +104,8 @@ |
3010 | UnityWebApps.UnityWebApps { |
3011 | id: unityWebapps |
3012 | name: webappName |
3013 | - bindee: webview |
3014 | + bindee: webview.currentWebview |
3015 | actionsContext: actionManager.globalContext |
3016 | model: UnityWebApps.UnityWebappsAppModel { searchPath: webappModelSearchPath } |
3017 | } |
3018 | - |
3019 | - function isRunningAsANamedWebapp() { |
3020 | - return webappName && typeof(webappName) === 'string' && webappName.length != 0 |
3021 | - } |
3022 | } |
3023 | |
3024 | === added file 'src/app/webcontainer/WebViewImplWebkit.qml' |
3025 | --- src/app/webcontainer/WebViewImplWebkit.qml 1970-01-01 00:00:00 +0000 |
3026 | +++ src/app/webcontainer/WebViewImplWebkit.qml 2014-03-28 17:03:06 +0000 |
3027 | @@ -0,0 +1,159 @@ |
3028 | +/* |
3029 | + * Copyright 2013 Canonical Ltd. |
3030 | + * |
3031 | + * This file is part of webbrowser-app. |
3032 | + * |
3033 | + * webbrowser-app is free software; you can redistribute it and/or modify |
3034 | + * it under the terms of the GNU General Public License as published by |
3035 | + * the Free Software Foundation; version 3. |
3036 | + * |
3037 | + * webbrowser-app is distributed in the hope that it will be useful, |
3038 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3039 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3040 | + * GNU General Public License for more details. |
3041 | + * |
3042 | + * You should have received a copy of the GNU General Public License |
3043 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3044 | + */ |
3045 | + |
3046 | +import QtQuick 2.0 |
3047 | +import QtWebKit 3.1 |
3048 | +import QtWebKit.experimental 1.0 |
3049 | +import Ubuntu.Components 0.1 |
3050 | +import Ubuntu.Components.Extras.Browser 0.1 |
3051 | +import Ubuntu.UnityWebApps 0.1 as UnityWebApps |
3052 | +import Ubuntu.Components.Popups 0.1 |
3053 | +import "../actions" as Actions |
3054 | +import ".." |
3055 | + |
3056 | +UbuntuWebView { |
3057 | + id: webview |
3058 | + |
3059 | + property bool developerExtrasEnabled: false |
3060 | + property var currentWebview: webview |
3061 | + property var toolbar: null |
3062 | + property string webappName: "" |
3063 | + property var webappUrlPatterns: null |
3064 | + |
3065 | + experimental.certificateVerificationDialog: CertificateVerificationDialog {} |
3066 | + experimental.authenticationDialog: AuthenticationDialog {} |
3067 | + experimental.proxyAuthenticationDialog: ProxyAuthenticationDialog {} |
3068 | + experimental.alertDialog: AlertDialog {} |
3069 | + experimental.confirmDialog: ConfirmDialog {} |
3070 | + experimental.promptDialog: PromptDialog {} |
3071 | + |
3072 | + selectionActions: ActionList { |
3073 | + Actions.Copy { |
3074 | + onTriggered: selection.copy() |
3075 | + } |
3076 | + } |
3077 | + |
3078 | + property bool lastLoadFailed: false |
3079 | + onLoadingChanged: { |
3080 | + lastLoadFailed = (loadRequest.status === WebView.LoadFailedStatus) |
3081 | + } |
3082 | + |
3083 | + experimental.preferences.developerExtrasEnabled: developerExtrasEnabled |
3084 | + |
3085 | + experimental.onPermissionRequested: { |
3086 | + if (permission.type === PermissionRequest.Geolocation) { |
3087 | + if (webview.toolbar) { |
3088 | + webview.toolbar.close() |
3089 | + } |
3090 | + var text = i18n.tr("This page wants to know your device’s location.") |
3091 | + PopupUtils.open(Qt.resolvedUrl("PermissionRequest.qml"), |
3092 | + webview.currentWebview, |
3093 | + {"permission": permission, "text": text}) |
3094 | + } |
3095 | + // TODO: handle other types of permission requests |
3096 | + // TODO: we might want to store the answer to avoid requesting |
3097 | + // the permission everytime the user visits this site. |
3098 | + } |
3099 | + |
3100 | + contextualActions: ActionList { |
3101 | + Actions.CopyLink { |
3102 | + enabled: webview.contextualData.href.toString() |
3103 | + onTriggered: Clipboard.push([webview.contextualData.href]) |
3104 | + } |
3105 | + Actions.CopyImage { |
3106 | + enabled: webview.contextualData.img.toString() |
3107 | + onTriggered: Clipboard.push([webview.contextualData.img]) |
3108 | + } |
3109 | + } |
3110 | + |
3111 | + function isRunningAsANamedWebapp() { |
3112 | + return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0 |
3113 | + } |
3114 | + |
3115 | + function haveValidUrlPatterns() { |
3116 | + return webappUrlPatterns && webappUrlPatterns.length !== 0 |
3117 | + } |
3118 | + |
3119 | + function navigationRequestedDelegate(request) { |
3120 | + if (!request.isMainFrame) { |
3121 | + request.action = WebView.AcceptRequest |
3122 | + return |
3123 | + } |
3124 | + |
3125 | + // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
3126 | + // or if we dont have a list of url patterns specified to filter the |
3127 | + // browsing actions |
3128 | + if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
3129 | + request.action = WebView.AcceptRequest |
3130 | + return |
3131 | + } |
3132 | + |
3133 | + var action = WebView.IgnoreRequest |
3134 | + var url = request.url.toString() |
3135 | + |
3136 | + // The list of url patterns defined by the webapp takes precedence over command line |
3137 | + if (isRunningAsANamedWebapp()) { |
3138 | + if (unityWebapps.model.exists(unityWebapps.name) && |
3139 | + unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
3140 | + request.action = WebView.AcceptRequest |
3141 | + return; |
3142 | + } |
3143 | + } |
3144 | + |
3145 | + // We still take the possible additional patterns specified in the command line |
3146 | + // (the in the case of finer grained ones specifically for the container and not |
3147 | + // as an 'install source' for the webapp). |
3148 | + if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
3149 | + for (var i = 0; i < webappUrlPatterns.length; ++i) { |
3150 | + var pattern = webappUrlPatterns[i] |
3151 | + if (url.match(pattern)) { |
3152 | + action = WebView.AcceptRequest |
3153 | + break |
3154 | + } |
3155 | + } |
3156 | + } |
3157 | + |
3158 | + request.action = action |
3159 | + if (action === WebView.IgnoreRequest) { |
3160 | + console.debug('Opening: ' + url + ' in the browser window.') |
3161 | + Qt.openUrlExternally(url) |
3162 | + } |
3163 | + } |
3164 | + |
3165 | + onNewTabRequested: Qt.openUrlExternally(url) |
3166 | + |
3167 | + // Small shim needed when running as a webapp to wire-up connections |
3168 | + // with the webview (message received, etc…). |
3169 | + // This is being called (and expected) internally by the webapps |
3170 | + // component as a way to bind to a webview lookalike without |
3171 | + // reaching out directly to its internals (see it as an interface). |
3172 | + function getUnityWebappsProxies() { |
3173 | + var eventHandlers = { |
3174 | + onAppRaised: function () { |
3175 | + if (webbrowserWindow) { |
3176 | + try { |
3177 | + webbrowserWindow.raise(); |
3178 | + } catch (e) { |
3179 | + console.debug('Error while raising: ' + e); |
3180 | + } |
3181 | + } |
3182 | + } |
3183 | + }; |
3184 | + return UnityWebAppsUtils.makeProxiesForQtWebViewBindee(webview, eventHandlers) |
3185 | + } |
3186 | +} |
3187 | |
3188 | === added file 'src/app/webcontainer/WebappContainerWebview.qml' |
3189 | --- src/app/webcontainer/WebappContainerWebview.qml 1970-01-01 00:00:00 +0000 |
3190 | +++ src/app/webcontainer/WebappContainerWebview.qml 2014-03-28 17:03:06 +0000 |
3191 | @@ -0,0 +1,151 @@ |
3192 | +/* |
3193 | + * Copyright 2014 Canonical Ltd. |
3194 | + * |
3195 | + * This file is part of webbrowser-app. |
3196 | + * |
3197 | + * webbrowser-app is free software; you can redistribute it and/or modify |
3198 | + * it under the terms of the GNU General Public License as published by |
3199 | + * the Free Software Foundation; version 3. |
3200 | + * |
3201 | + * webbrowser-app is distributed in the hope that it will be useful, |
3202 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3203 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3204 | + * GNU General Public License for more details. |
3205 | + * |
3206 | + * You should have received a copy of the GNU General Public License |
3207 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3208 | + */ |
3209 | + |
3210 | +import QtQuick 2.0 |
3211 | +import Ubuntu.Components 0.1 |
3212 | +import Ubuntu.Unity.Action 1.0 as UnityActions |
3213 | +import Ubuntu.UnityWebApps 0.1 as UnityWebApps |
3214 | +import "../actions" as Actions |
3215 | +import ".." |
3216 | + |
3217 | +Item { |
3218 | + id: containerWebview |
3219 | + |
3220 | + property string url: "" |
3221 | + property bool withOxide: false |
3222 | + property bool developerExtrasEnabled: false |
3223 | + property string webappName: "" |
3224 | + property var currentWebview: webappContainerWebViewLoader.item |
3225 | + property var toolbar: null |
3226 | + property var webappUrlPatterns: null |
3227 | + |
3228 | + Loader { |
3229 | + id: webappContainerWebViewLoader |
3230 | + anchors.fill: parent |
3231 | + sourceComponent: withOxide ? webappContainerWebViewOxide : webappContainerWebViewWebkit |
3232 | + } |
3233 | + |
3234 | + Component { |
3235 | + id: webappContainerWebViewWebkit |
3236 | + |
3237 | + WebViewImplWebkit { |
3238 | + toolbar: containerWebview.toolbar |
3239 | + url: containerWebview.url |
3240 | + webappName: containerWebview.webappName |
3241 | + webappUrlPatterns: containerWebview.webappUrlPatterns |
3242 | + developerExtrasEnabled: containerWebview.developerExtrasEnabled |
3243 | + } |
3244 | + } |
3245 | + |
3246 | + Component { |
3247 | + id: webappContainerWebViewOxide |
3248 | + |
3249 | + WebViewImpl { |
3250 | + id: webview |
3251 | + |
3252 | + url: containerWebview.url |
3253 | + currentWebview: webview |
3254 | + toolbar: containerWebview.toolbar |
3255 | + |
3256 | + contextualActions: ActionList { |
3257 | + Actions.CopyLink { |
3258 | + enabled: webview.contextualData.href.toString() |
3259 | + onTriggered: Clipboard.push([webview.contextualData.href]) |
3260 | + } |
3261 | + Actions.CopyImage { |
3262 | + enabled: webview.contextualData.img.toString() |
3263 | + onTriggered: Clipboard.push([webview.contextualData.img]) |
3264 | + } |
3265 | + } |
3266 | + |
3267 | + function haveValidUrlPatterns() { |
3268 | + return webappUrlPatterns && webappUrlPatterns.length !== 0 |
3269 | + } |
3270 | + |
3271 | + /*function navigationRequestedDelegate(request) { |
3272 | + if (!request.isMainFrame) { |
3273 | + request.action = WebView.AcceptRequest |
3274 | + return |
3275 | + } |
3276 | + |
3277 | + // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
3278 | + // or if we dont have a list of url patterns specified to filter the |
3279 | + // browsing actions |
3280 | + if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
3281 | + request.action = WebView.AcceptRequest |
3282 | + return |
3283 | + } |
3284 | + |
3285 | + var action = WebView.IgnoreRequest |
3286 | + var url = request.url.toString() |
3287 | + |
3288 | + // The list of url patterns defined by the webapp takes precedence over command line |
3289 | + if (isRunningAsANamedWebapp()) { |
3290 | + if (unityWebapps.model.exists(unityWebapps.name) && |
3291 | + unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
3292 | + request.action = WebView.AcceptRequest |
3293 | + return; |
3294 | + } |
3295 | + } |
3296 | + |
3297 | + // We still take the possible additional patterns specified in the command line |
3298 | + // (the in the case of finer grained ones specifically for the container and not |
3299 | + // as an 'install source' for the webapp). |
3300 | + if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
3301 | + for (var i = 0; i < webappUrlPatterns.length; ++i) { |
3302 | + var pattern = webappUrlPatterns[i] |
3303 | + if (url.match(pattern)) { |
3304 | + action = WebView.AcceptRequest |
3305 | + break |
3306 | + } |
3307 | + } |
3308 | + } |
3309 | + |
3310 | + request.action = action |
3311 | + if (action === WebView.IgnoreRequest) { |
3312 | + console.debug('Opening: ' + url + ' in the browser window.') |
3313 | + Qt.openUrlExternally(url) |
3314 | + } |
3315 | + }*/ |
3316 | + |
3317 | + onNewTabRequested: Qt.openUrlExternally(url) |
3318 | + |
3319 | + preferences.localStorageEnabled: true |
3320 | + |
3321 | + // Small shim needed when running as a webapp to wire-up connections |
3322 | + // with the webview (message received, etc…). |
3323 | + // This is being called (and expected) internally by the webapps |
3324 | + // component as a way to bind to a webview lookalike without |
3325 | + // reaching out directly to its internals (see it as an interface). |
3326 | + function getUnityWebappsProxies() { |
3327 | + var eventHandlers = { |
3328 | + onAppRaised: function () { |
3329 | + if (webbrowserWindow) { |
3330 | + try { |
3331 | + webbrowserWindow.raise(); |
3332 | + } catch (e) { |
3333 | + console.debug('Error while raising: ' + e); |
3334 | + } |
3335 | + } |
3336 | + } |
3337 | + }; |
3338 | + return UnityWebAppsUtils.makeProxiesForWebViewBindee(webview, eventHandlers) |
3339 | + } |
3340 | + } |
3341 | + } |
3342 | +} |
3343 | |
3344 | === modified file 'src/app/webcontainer/webapp-container.cpp' |
3345 | --- src/app/webcontainer/webapp-container.cpp 2014-03-20 18:17:12 +0000 |
3346 | +++ src/app/webcontainer/webapp-container.cpp 2014-03-28 17:03:06 +0000 |
3347 | @@ -24,10 +24,32 @@ |
3348 | // Qt |
3349 | #include <QtCore/QCoreApplication> |
3350 | #include <QtCore/QDebug> |
3351 | +#include <QtCore/QFile> |
3352 | #include <QtCore/QFileInfo> |
3353 | +#include <QtCore/QtGlobal> |
3354 | #include <QtCore/QRegularExpression> |
3355 | #include <QtCore/QTextStream> |
3356 | #include <QtQuick/QQuickWindow> |
3357 | +#include <QtQml/QQmlComponent> |
3358 | + |
3359 | + |
3360 | +namespace |
3361 | +{ |
3362 | + |
3363 | +QString currentArchitecturePathName() |
3364 | +{ |
3365 | +#if defined(Q_PROCESSOR_X86_32) |
3366 | + return QLatin1String("i386-linux-gnu"); |
3367 | +#elif defined(Q_PROCESSOR_X86_64) |
3368 | + return QLatin1String("x86_64-linux-gnu"); |
3369 | +#elif defined(Q_PROCESSOR_ARM) |
3370 | + return QLatin1String("arm-linux-gnueabihf"); |
3371 | +#else |
3372 | +#error Unable to determine target architecture |
3373 | +#endif |
3374 | +} |
3375 | + |
3376 | +} |
3377 | |
3378 | WebappContainer::WebappContainer(int& argc, char** argv) |
3379 | : BrowserApplication(argc, argv) |
3380 | @@ -50,7 +72,13 @@ |
3381 | m_window->setProperty("webappName", name); |
3382 | m_window->setProperty("backForwardButtonsVisible", m_arguments.contains("--enable-back-forward")); |
3383 | m_window->setProperty("addressBarVisible", m_arguments.contains("--enable-addressbar")); |
3384 | + |
3385 | + bool oxide = withOxide(); |
3386 | + qDebug() << "Using" << (oxide ? "Oxide" : "QtWebkit") << "as the web engine backend"; |
3387 | + m_window->setProperty("oxide", oxide); |
3388 | + |
3389 | m_window->setProperty("webappUrlPatterns", webappUrlPatterns()); |
3390 | + |
3391 | // When a webapp is being launched by name, the URL is pulled from its 'homepage'. |
3392 | if (name.isEmpty()) { |
3393 | QList<QUrl> urls = this->urls(); |
3394 | @@ -58,6 +86,9 @@ |
3395 | m_window->setProperty("url", urls.first()); |
3396 | } |
3397 | } |
3398 | + |
3399 | + m_component->completeCreate(); |
3400 | + |
3401 | return true; |
3402 | } else { |
3403 | return false; |
3404 | @@ -84,6 +115,31 @@ |
3405 | out << " --enable-addressbar enable the display of the address bar" << endl; |
3406 | } |
3407 | |
3408 | +bool WebappContainer::withOxide() const |
3409 | +{ |
3410 | + Q_FOREACH(const QString& argument, m_arguments) { |
3411 | + if (argument == "--webkit") { |
3412 | + // force webkit |
3413 | + return false; |
3414 | + } |
3415 | + if (argument == "--oxide") { |
3416 | + // force oxide |
3417 | + return true; |
3418 | + } |
3419 | + } |
3420 | + |
3421 | + // Use a runtime hint to transparently know if oxide |
3422 | + // can be used as a backend without the user/dev having |
3423 | + // to update its app or change something in the Exec args. |
3424 | + // Version 1.1 of ubuntu apparmor policy allows this file to |
3425 | + // be accessed whereas v1.0 only knows about qtwebkit. |
3426 | + QString oxideHintLocation = |
3427 | + QString("/usr/lib/%1/oxide-qt/oxide-renderer") |
3428 | + .arg(currentArchitecturePathName()); |
3429 | + |
3430 | + return QFile(oxideHintLocation).open(QIODevice::ReadOnly); |
3431 | +} |
3432 | + |
3433 | QString WebappContainer::webappModelSearchPath() const |
3434 | { |
3435 | Q_FOREACH(const QString& argument, m_arguments) { |
3436 | |
3437 | === modified file 'src/app/webcontainer/webapp-container.h' |
3438 | --- src/app/webcontainer/webapp-container.h 2014-03-14 14:51:22 +0000 |
3439 | +++ src/app/webcontainer/webapp-container.h 2014-03-28 17:03:06 +0000 |
3440 | @@ -39,6 +39,7 @@ |
3441 | QString webappModelSearchPath() const; |
3442 | QString webappName() const; |
3443 | QStringList webappUrlPatterns() const; |
3444 | + bool withOxide() const; |
3445 | }; |
3446 | |
3447 | #endif // __WEBAPP_CONTAINER_H__ |
3448 | |
3449 | === modified file 'src/app/webcontainer/webapp-container.qml' |
3450 | --- src/app/webcontainer/webapp-container.qml 2014-03-14 14:51:22 +0000 |
3451 | +++ src/app/webcontainer/webapp-container.qml 2014-03-28 17:03:06 +0000 |
3452 | @@ -30,6 +30,7 @@ |
3453 | property alias webappName: browser.webappName |
3454 | property alias webappModelSearchPath: browser.webappModelSearchPath |
3455 | property alias webappUrlPatterns: browser.webappUrlPatterns |
3456 | + property alias oxide: browser.oxide |
3457 | |
3458 | contentOrientation: browser.screenOrientation |
3459 | |
3460 | |
3461 | === modified file 'tests/autopilot/webbrowser_app/tests/test_tabs.py' |
3462 | --- tests/autopilot/webbrowser_app/tests/test_tabs.py 2014-02-06 04:31:01 +0000 |
3463 | +++ tests/autopilot/webbrowser_app/tests/test_tabs.py 2014-03-28 17:03:06 +0000 |
3464 | @@ -17,6 +17,7 @@ |
3465 | from __future__ import absolute_import |
3466 | |
3467 | import time |
3468 | +import unittest |
3469 | from testtools.matchers import Equals |
3470 | from autopilot.matchers import Eventually |
3471 | |
3472 | @@ -140,6 +141,8 @@ |
3473 | address_bar = self.main_window.get_address_bar() |
3474 | self.assertThat(address_bar.activeFocus, Eventually(Equals(True))) |
3475 | |
3476 | + # FIXME: re-enable when implemented in oxide |
3477 | + @unittest.skip("not implemented in oxide yet") |
3478 | def test_open_target_blank_in_new_tab(self): |
3479 | url = self.base_url + "/blanktargetlink" |
3480 | self.go_to_url(url) |
3481 | @@ -149,6 +152,8 @@ |
3482 | self.assertThat(self.main_window.currentIndex, Eventually(Equals(1))) |
3483 | self.assert_current_url(self.base_url + "/aleaiactaest") |
3484 | |
3485 | + # FIXME: re-enable when implemented in oxide |
3486 | + @unittest.skip("not implemented in oxide yet") |
3487 | def test_open_iframe_target_blank_in_new_tab(self): |
3488 | url = self.base_url + "/fulliframewithblanktargetlink" |
3489 | self.go_to_url(url) |
3490 | |
3491 | === modified file 'tests/unittests/qml/CMakeLists.txt' |
3492 | --- tests/unittests/qml/CMakeLists.txt 2014-03-12 15:27:10 +0000 |
3493 | +++ tests/unittests/qml/CMakeLists.txt 2014-03-28 17:03:06 +0000 |
3494 | @@ -1,8 +1,15 @@ |
3495 | +set(XVFB_COMMAND) |
3496 | +find_program(XVFBRUN xvfb-run) |
3497 | +if(XVFBRUN) |
3498 | + set(XVFB_COMMAND ${XVFBRUN} -s "-screen 0 640x480x24" -a) |
3499 | +else() |
3500 | + message(WARNING "Cannot find xvfb-run.") |
3501 | +endif() |
3502 | + |
3503 | set(TEST tst_QmlTests) |
3504 | add_executable(${TEST} tst_QmlTests.cpp) |
3505 | qt5_use_modules(${TEST} Core Qml Quick Test QuickTest) |
3506 | -add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -import ${CMAKE_BINARY_DIR}/src) |
3507 | -set_tests_properties(${TEST} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal") |
3508 | +add_test(${TEST} ${XVFB_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -import ${CMAKE_BINARY_DIR}/src) |
3509 | |
3510 | # copy qml files under test to build dir |
3511 | set(out_qml_files) |
3512 | @@ -13,7 +20,7 @@ |
3513 | COMMAND ${CMAKE_COMMAND} -E copy_if_different ${webbrowser-common_SOURCE_DIR}/${qmlFile} ${CMAKE_CURRENT_BINARY_DIR}/undertest/${qmlFile}) |
3514 | list(APPEND out_qml_files undertest/${qmlFile}) |
3515 | endforeach(qmlFile) |
3516 | -set(privateApiQmlFiles UserAgent.qml ua-overrides.js) |
3517 | +set(privateApiQmlFiles UserAgent01.qml UserAgent02.qml ua-overrides.js) |
3518 | foreach(qmlFile ${privateApiQmlFiles}) |
3519 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/undertest/${qmlFile} |
3520 | DEPENDS ${webbrowser-plugin_SOURCE_DIR}/${qmlFile} |
3521 | |
3522 | === added file 'tests/unittests/qml/tst_UbuntuWebView01.qml' |
3523 | --- tests/unittests/qml/tst_UbuntuWebView01.qml 1970-01-01 00:00:00 +0000 |
3524 | +++ tests/unittests/qml/tst_UbuntuWebView01.qml 2014-03-28 17:03:06 +0000 |
3525 | @@ -0,0 +1,46 @@ |
3526 | +/* |
3527 | + * Copyright 2013 Canonical Ltd. |
3528 | + * |
3529 | + * This file is part of webbrowser-app. |
3530 | + * |
3531 | + * webbrowser-app is free software; you can redistribute it and/or modify |
3532 | + * it under the terms of the GNU General Public License as published by |
3533 | + * the Free Software Foundation; version 3. |
3534 | + * |
3535 | + * webbrowser-app is distributed in the hope that it will be useful, |
3536 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3537 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3538 | + * GNU General Public License for more details. |
3539 | + * |
3540 | + * You should have received a copy of the GNU General Public License |
3541 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3542 | + */ |
3543 | + |
3544 | +import QtQuick 2.0 |
3545 | +import QtTest 1.0 |
3546 | +import Ubuntu.Components.Extras.Browser 0.1 |
3547 | + |
3548 | +TestCase { |
3549 | + name: "UbuntuWebView" |
3550 | + |
3551 | + function test_custom_UA_override() { |
3552 | + compare(webview1.getUAString(), undefined) |
3553 | + // passing a 'url' parameter to getUAString() |
3554 | + // (as was the API before) shouldn’t hurt: |
3555 | + compare(webview1.getUAString("http://example.com"), undefined) |
3556 | + verify(webview1.experimental.userAgent !== undefined) |
3557 | + compare(webview2.experimental.userAgent, "custom UA") |
3558 | + } |
3559 | + |
3560 | + UbuntuWebView { |
3561 | + id: webview1 |
3562 | + } |
3563 | + |
3564 | + UbuntuWebView { |
3565 | + id: webview2 |
3566 | + |
3567 | + function getUAString(url) { |
3568 | + return "custom UA" |
3569 | + } |
3570 | + } |
3571 | +} |
3572 | |
3573 | === renamed file 'tests/unittests/qml/tst_UbuntuWebView.qml' => 'tests/unittests/qml/tst_UbuntuWebView02.qml' |
3574 | --- tests/unittests/qml/tst_UbuntuWebView.qml 2014-03-14 17:26:10 +0000 |
3575 | +++ tests/unittests/qml/tst_UbuntuWebView02.qml 2014-03-28 17:03:06 +0000 |
3576 | @@ -18,18 +18,15 @@ |
3577 | |
3578 | import QtQuick 2.0 |
3579 | import QtTest 1.0 |
3580 | -import Ubuntu.Components.Extras.Browser 0.1 |
3581 | +import Ubuntu.Components.Extras.Browser 0.2 |
3582 | |
3583 | TestCase { |
3584 | name: "UbuntuWebView" |
3585 | |
3586 | function test_custom_UA_override() { |
3587 | compare(webview1.getUAString(), undefined) |
3588 | - // passing a 'url' parameter to getUAString() |
3589 | - // (as was the API before) shouldn’t hurt: |
3590 | - compare(webview1.getUAString("http://example.com"), undefined) |
3591 | - verify(webview1.experimental.userAgent !== undefined) |
3592 | - compare(webview2.experimental.userAgent, "custom UA") |
3593 | + verify(webview1.context.userAgent !== undefined) |
3594 | + compare(webview2.context.userAgent, "custom UA") |
3595 | } |
3596 | |
3597 | UbuntuWebView { |
3598 | |
3599 | === removed file 'tests/unittests/qml/tst_UserAgent.qml' |
3600 | --- tests/unittests/qml/tst_UserAgent.qml 2014-03-12 15:27:10 +0000 |
3601 | +++ tests/unittests/qml/tst_UserAgent.qml 1970-01-01 00:00:00 +0000 |
3602 | @@ -1,82 +0,0 @@ |
3603 | -/* |
3604 | - * Copyright 2013 Canonical Ltd. |
3605 | - * |
3606 | - * This file is part of webbrowser-app. |
3607 | - * |
3608 | - * webbrowser-app is free software; you can redistribute it and/or modify |
3609 | - * it under the terms of the GNU General Public License as published by |
3610 | - * the Free Software Foundation; version 3. |
3611 | - * |
3612 | - * webbrowser-app is distributed in the hope that it will be useful, |
3613 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3614 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3615 | - * GNU General Public License for more details. |
3616 | - * |
3617 | - * You should have received a copy of the GNU General Public License |
3618 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3619 | - */ |
3620 | - |
3621 | -import QtQuick 2.0 |
3622 | -import QtTest 1.0 |
3623 | -import "undertest" |
3624 | - |
3625 | -TestCase { |
3626 | - name: "UserAgent" |
3627 | - |
3628 | - function test_get_domain_data() { |
3629 | - return [ |
3630 | - {url: "http://ubuntu.com", domain: "ubuntu.com"}, |
3631 | - {url: "http://www.ubuntu.com", domain: "www.ubuntu.com"}, |
3632 | - {url: "http://ubuntu.com/", domain: "ubuntu.com"}, |
3633 | - {url: "http://www.ubuntu.com/", domain: "www.ubuntu.com"}, |
3634 | - {url: "ubuntu.com", domain: "ubuntu.com"}, |
3635 | - {url: "ubuntu.com/", domain: "ubuntu.com"}, |
3636 | - {url: "ubuntu.com/phone", domain: "ubuntu.com"}, |
3637 | - {url: "http://ubuntu.com/phone", domain: "ubuntu.com"}, |
3638 | - {url: "www.ubuntu.com/phone", domain: "www.ubuntu.com"}, |
3639 | - {url: "http://ubuntu.com/phone/index.html", domain: "ubuntu.com"}, |
3640 | - {url: "ubuntu.com/phone/index.html", domain: "ubuntu.com"}, |
3641 | - {url: "www.ubuntu.com/phone/index.html", domain: "www.ubuntu.com"}, |
3642 | - {url: "http://ubuntu.com/phone/index.html?foo=bar&baz=bleh", domain: "ubuntu.com"}, |
3643 | - ] |
3644 | - } |
3645 | - function test_get_domain(data) { |
3646 | - compare(userAgent.getDomain(data.url), data.domain) |
3647 | - } |
3648 | - |
3649 | - function test_get_domains_data() { |
3650 | - return [ |
3651 | - {domain: "ubuntu.com", domains: ["ubuntu.com", "com"]}, |
3652 | - {domain: "test.example.org", domains: ["test.example.org", "example.org", "org"]}, |
3653 | - ] |
3654 | - } |
3655 | - function test_get_domains(data) { |
3656 | - compare(userAgent.getDomains(data.domain), data.domains) |
3657 | - } |
3658 | - |
3659 | - function test_get_ua_string_data() { |
3660 | - return [ |
3661 | - {url: "http://ubuntu.com", ua: userAgent.defaultUA}, |
3662 | - {url: "http://example.org", ua: "full override"}, |
3663 | - {url: "http://example.com/test", ua: "Mozilla/5.0 (Ubuntu Edge; Mobile) WebKit/537.21"}, |
3664 | - {url: "http://www.google.com/", ua: "Mozilla/5.0 (Ubuntu; ble) WebKit/537.21"}, |
3665 | - {url: "https://mail.google.com/", ua: "Mozilla/5.0 (Ubuntu; Touch) WebKit/537.21"}, |
3666 | - ] |
3667 | - } |
3668 | - function test_get_ua_string(data) { |
3669 | - compare(userAgent.getUAString(data.url), data.ua) |
3670 | - } |
3671 | - |
3672 | - UserAgent { |
3673 | - id: userAgent |
3674 | - |
3675 | - defaultUA: "Mozilla/5.0 (Ubuntu; Mobile) WebKit/537.21" |
3676 | - |
3677 | - overrides: { |
3678 | - "example.org": "full override", |
3679 | - "example.com": ["Ubuntu", "Ubuntu Edge"], |
3680 | - "google.com": [/mobi/i, "b"], |
3681 | - "mail.google.com": [/mobile/i, "Touch"], |
3682 | - } |
3683 | - } |
3684 | -} |
3685 | |
3686 | === added file 'tests/unittests/qml/tst_UserAgent01.qml' |
3687 | --- tests/unittests/qml/tst_UserAgent01.qml 1970-01-01 00:00:00 +0000 |
3688 | +++ tests/unittests/qml/tst_UserAgent01.qml 2014-03-28 17:03:06 +0000 |
3689 | @@ -0,0 +1,82 @@ |
3690 | +/* |
3691 | + * Copyright 2013 Canonical Ltd. |
3692 | + * |
3693 | + * This file is part of webbrowser-app. |
3694 | + * |
3695 | + * webbrowser-app is free software; you can redistribute it and/or modify |
3696 | + * it under the terms of the GNU General Public License as published by |
3697 | + * the Free Software Foundation; version 3. |
3698 | + * |
3699 | + * webbrowser-app is distributed in the hope that it will be useful, |
3700 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3701 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3702 | + * GNU General Public License for more details. |
3703 | + * |
3704 | + * You should have received a copy of the GNU General Public License |
3705 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3706 | + */ |
3707 | + |
3708 | +import QtQuick 2.0 |
3709 | +import QtTest 1.0 |
3710 | +import "undertest" |
3711 | + |
3712 | +TestCase { |
3713 | + name: "UserAgent" |
3714 | + |
3715 | + function test_get_domain_data() { |
3716 | + return [ |
3717 | + {url: "http://ubuntu.com", domain: "ubuntu.com"}, |
3718 | + {url: "http://www.ubuntu.com", domain: "www.ubuntu.com"}, |
3719 | + {url: "http://ubuntu.com/", domain: "ubuntu.com"}, |
3720 | + {url: "http://www.ubuntu.com/", domain: "www.ubuntu.com"}, |
3721 | + {url: "ubuntu.com", domain: "ubuntu.com"}, |
3722 | + {url: "ubuntu.com/", domain: "ubuntu.com"}, |
3723 | + {url: "ubuntu.com/phone", domain: "ubuntu.com"}, |
3724 | + {url: "http://ubuntu.com/phone", domain: "ubuntu.com"}, |
3725 | + {url: "www.ubuntu.com/phone", domain: "www.ubuntu.com"}, |
3726 | + {url: "http://ubuntu.com/phone/index.html", domain: "ubuntu.com"}, |
3727 | + {url: "ubuntu.com/phone/index.html", domain: "ubuntu.com"}, |
3728 | + {url: "www.ubuntu.com/phone/index.html", domain: "www.ubuntu.com"}, |
3729 | + {url: "http://ubuntu.com/phone/index.html?foo=bar&baz=bleh", domain: "ubuntu.com"}, |
3730 | + ] |
3731 | + } |
3732 | + function test_get_domain(data) { |
3733 | + compare(userAgent.getDomain(data.url), data.domain) |
3734 | + } |
3735 | + |
3736 | + function test_get_domains_data() { |
3737 | + return [ |
3738 | + {domain: "ubuntu.com", domains: ["ubuntu.com", "com"]}, |
3739 | + {domain: "test.example.org", domains: ["test.example.org", "example.org", "org"]}, |
3740 | + ] |
3741 | + } |
3742 | + function test_get_domains(data) { |
3743 | + compare(userAgent.getDomains(data.domain), data.domains) |
3744 | + } |
3745 | + |
3746 | + function test_get_ua_string_data() { |
3747 | + return [ |
3748 | + {url: "http://ubuntu.com", ua: userAgent.defaultUA}, |
3749 | + {url: "http://example.org", ua: "full override"}, |
3750 | + {url: "http://example.com/test", ua: "Mozilla/5.0 (Ubuntu Edge; Mobile) WebKit/537.21"}, |
3751 | + {url: "http://www.google.com/", ua: "Mozilla/5.0 (Ubuntu; ble) WebKit/537.21"}, |
3752 | + {url: "https://mail.google.com/", ua: "Mozilla/5.0 (Ubuntu; Touch) WebKit/537.21"}, |
3753 | + ] |
3754 | + } |
3755 | + function test_get_ua_string(data) { |
3756 | + compare(userAgent.getUAString(data.url), data.ua) |
3757 | + } |
3758 | + |
3759 | + UserAgent01 { |
3760 | + id: userAgent |
3761 | + |
3762 | + defaultUA: "Mozilla/5.0 (Ubuntu; Mobile) WebKit/537.21" |
3763 | + |
3764 | + overrides: { |
3765 | + "example.org": "full override", |
3766 | + "example.com": ["Ubuntu", "Ubuntu Edge"], |
3767 | + "google.com": [/mobi/i, "b"], |
3768 | + "mail.google.com": [/mobile/i, "Touch"], |
3769 | + } |
3770 | + } |
3771 | +} |
FAILED: Continuous integration, rev:491 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 671/ jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty/ 4342/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty- touch/3941/ console jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- amd64-ci/ 173 jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- armhf-ci/ 173 jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- armhf-ci/ 173/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- i386-ci/ 173 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-trusty/ 3763/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/4441 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/4441/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- armhf/3943 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- armhf/3943/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- runner- mako/6220/ console s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 5353
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 671/rebuild
http://