Merge lp:~abreu-alexandre/webbrowser-app/support-oxide-and-qtwebkit into lp:~osomon/webbrowser-app/with-oxide
- support-oxide-and-qtwebkit
- Merge into with-oxide
Status: | Merged |
---|---|
Merged at revision: | 492 |
Proposed branch: | lp:~abreu-alexandre/webbrowser-app/support-oxide-and-qtwebkit |
Merge into: | lp:~osomon/webbrowser-app/with-oxide |
Diff against target: |
664 lines (+392/-103) 10 files modified
debian/control (+1/-0) src/app/browserapplication.cpp (+1/-1) src/app/browserapplication.h (+1/-1) src/app/webbrowser/webbrowser-app.cpp (+3/-0) src/app/webcontainer/WebApp.qml (+18/-101) 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) |
To merge this branch: | bzr merge lp:~abreu-alexandre/webbrowser-app/support-oxide-and-qtwebkit |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Olivier Tilloy | Needs Fixing | ||
Review via email: mp+212850@code.launchpad.net |
Commit message
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,
Description of the change
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,
- 488. By Alexandre Abreu
-
merge trunk
- 489. By Alexandre Abreu
-
fixes
- 490. By Alexandre Abreu
-
Add build deps
- 491. By Alexandre Abreu
-
fixes
Olivier Tilloy (osomon) wrote : | # |
At line 33 of the diff, an extra blank line was added, can it be reverted?
Olivier Tilloy (osomon) wrote : | # |
563 +#include <unistd.h>
Is this include statement really needed?
Olivier Tilloy (osomon) wrote : | # |
In WebappContainer
Olivier Tilloy (osomon) wrote : | # |
632 + // to update its app or change somehting in the Exec args.
typo: s/somehting/
Olivier Tilloy (osomon) wrote : | # |
In WebappContainer
I just want to make sure when I read this code again in 6 months from now I’ll understand right away why we wrote it and how it works.
- 492. By Alexandre Abreu
-
fixes
Alexandre Abreu (abreu-alexandre) wrote : | # |
> At line 33 of the diff, an extra blank line was added, can it be reverted?
done
Alexandre Abreu (abreu-alexandre) wrote : | # |
> In WebappContainer
> explaining that this works under confinement because version 1.1 of the ubuntu
> apparmor policy allows access to this file, whereas version 1.0 knows only of
> QtWebKit.
>
> I just want to make sure when I read this code again in 6 months from now I’ll
> understand right away why we wrote it and how it works.
done
Alexandre Abreu (abreu-alexandre) wrote : | # |
> 632 + // to update its app or change somehting in the Exec args.
>
> typo: s/somehting/
done
Alexandre Abreu (abreu-alexandre) wrote : | # |
> 563 +#include <unistd.h>
>
> Is this include statement really needed?
done
Olivier Tilloy (osomon) wrote : | # |
This doesn’t work here on my device: I’ve installed packages built from this branch (which pulled in oxide), and running a webapp that has version 1.0 of the policy fails, I’m seeing this in the log:
Using Oxide as the web engine backend
and then:
LaunchProcess: failed to execvp:
/usr/
QFile::exists() is probably not good enough to check access rights.
I have tried the following:
return QFile(oxideHint
which is closer to your original solution, but I’m still getting the same issue. Could it be that version 1.0 of the policy doesn’t prevent from reading this file? Can you check with Jamie?
Jamie Strandboge (jdstrand) wrote : | # |
So, 1.0 of the policy doesn't block the access. I'll update the apparmor-
- 493. By Alexandre Abreu
-
simplify oxide detection
Olivier Tilloy (osomon) wrote : | # |
currentArchitec
Olivier Tilloy (osomon) wrote : | # |
441 + id: webview
this id seems to be unused
Olivier Tilloy (osomon) wrote : | # |
457 + toolbar: panel.panel
This doesn’t look correct. Shouldn’t it be:
toolbar: containerWebvie
- 494. By Alexandre Abreu
-
Fixes
Olivier Tilloy (osomon) wrote : | # |
287 + experimental.
"developerExtra
Can you make it a property of the WebViewImplWebkit and ensure it’s set from the caller?
- 495. By Alexandre Abreu
-
Fixes
- 496. By Alexandre Abreu
-
Fixes
Olivier Tilloy (osomon) wrote : | # |
In src/app/
property alias developerExtras
I don’t think this will work, because WebApp is an instance of BrowserView which already defines a top-level "developerExtra
- 497. By Alexandre Abreu
-
Fix developer extra enabled
Alexandre Abreu (abreu-alexandre) wrote : | # |
> In src/app/
>
> property alias developerExtras
>
> I don’t think this will work, because WebApp is an instance of BrowserView
> which already defines a top-level "developerExtra
right, done
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-03-18 15:18:34 +0000 |
3 | +++ debian/control 2014-03-28 16:05:34 +0000 |
4 | @@ -51,6 +51,7 @@ |
5 | Depends: ${misc:Depends}, |
6 | ${shlibs:Depends}, |
7 | unity-webapps-qml, |
8 | + libqt5webkit5-qmlwebkitplugin, |
9 | webbrowser-app (= ${binary:Version}), |
10 | Description: Ubuntu web applications container |
11 | A lightweight webapps container tailored for Ubuntu, based on the Webkit |
12 | |
13 | === modified file 'src/app/browserapplication.cpp' |
14 | --- src/app/browserapplication.cpp 2014-03-17 22:16:59 +0000 |
15 | +++ src/app/browserapplication.cpp 2014-03-28 16:05:34 +0000 |
16 | @@ -140,7 +140,7 @@ |
17 | m_webbrowserWindowProxy = new WebBrowserWindow(); |
18 | context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy); |
19 | |
20 | - QObject* browser = m_component->create(); |
21 | + QObject* browser = m_component->beginCreate(context); |
22 | m_window = qobject_cast<QQuickWindow*>(browser); |
23 | m_webbrowserWindowProxy->setWindow(m_window); |
24 | |
25 | |
26 | === modified file 'src/app/browserapplication.h' |
27 | --- src/app/browserapplication.h 2014-03-17 22:16:59 +0000 |
28 | +++ src/app/browserapplication.h 2014-03-28 16:05:34 +0000 |
29 | @@ -49,11 +49,11 @@ |
30 | QStringList m_arguments; |
31 | QQmlEngine* m_engine; |
32 | QQuickWindow* m_window; |
33 | + QQmlComponent* m_component; |
34 | |
35 | private: |
36 | QString appId() const; |
37 | |
38 | - QQmlComponent* m_component; |
39 | WebBrowserWindow *m_webbrowserWindowProxy; |
40 | }; |
41 | |
42 | |
43 | === modified file 'src/app/webbrowser/webbrowser-app.cpp' |
44 | --- src/app/webbrowser/webbrowser-app.cpp 2014-03-13 09:04:26 +0000 |
45 | +++ src/app/webbrowser/webbrowser-app.cpp 2014-03-28 16:05:34 +0000 |
46 | @@ -89,6 +89,9 @@ |
47 | Q_FOREACH(const QUrl& url, urls) { |
48 | QMetaObject::invokeMethod(browser, "newTab", Q_ARG(QVariant, url), Q_ARG(QVariant, true)); |
49 | } |
50 | + |
51 | + m_component->completeCreate(); |
52 | + |
53 | return true; |
54 | } else { |
55 | return false; |
56 | |
57 | === modified file 'src/app/webcontainer/WebApp.qml' |
58 | --- src/app/webcontainer/WebApp.qml 2014-03-26 13:29:24 +0000 |
59 | +++ src/app/webcontainer/WebApp.qml 2014-03-28 16:05:34 +0000 |
60 | @@ -27,20 +27,23 @@ |
61 | BrowserView { |
62 | id: webapp |
63 | |
64 | - currentWebview: webview |
65 | + currentWebview: webview.currentWebview |
66 | |
67 | property alias url: webview.url |
68 | - property string webappName: "" |
69 | + |
70 | property string webappModelSearchPath: "" |
71 | - property var webappUrlPatterns: null |
72 | + |
73 | + property alias oxide: webview.withOxide |
74 | + property alias webappName: webview.webappName |
75 | + property alias webappUrlPatterns: webview.webappUrlPatterns |
76 | |
77 | actions: [ |
78 | Actions.Back { |
79 | - enabled: backForwardButtonsVisible && currentWebview.canGoBack |
80 | + enabled: backForwardButtonsVisible && webview.currentWebview && webview.currentWebview.canGoBack |
81 | onTriggered: webview.goBack() |
82 | }, |
83 | Actions.Forward { |
84 | - enabled: backForwardButtonsVisible && currentWebview.canGoForward |
85 | + enabled: backForwardButtonsVisible && webview.currentWebview && webview.currentWebview.canGoForward |
86 | onTriggered: webview.goForward() |
87 | }, |
88 | Actions.Reload { |
89 | @@ -56,10 +59,8 @@ |
90 | // The UITK is trying too hard to be clever about the header and toolbar. |
91 | flickable: null |
92 | |
93 | - WebViewImpl { |
94 | + WebappContainerWebview { |
95 | id: webview |
96 | - |
97 | - currentWebview: webview |
98 | toolbar: panel.panel |
99 | |
100 | anchors { |
101 | @@ -68,97 +69,17 @@ |
102 | top: parent.top |
103 | } |
104 | height: parent.height - osk.height |
105 | - |
106 | - contextualActions: ActionList { |
107 | - Actions.CopyLink { |
108 | - enabled: webview.contextualData.href.toString() |
109 | - onTriggered: Clipboard.push([webview.contextualData.href]) |
110 | - } |
111 | - Actions.CopyImage { |
112 | - enabled: webview.contextualData.img.toString() |
113 | - onTriggered: Clipboard.push([webview.contextualData.img]) |
114 | - } |
115 | - } |
116 | - |
117 | - function haveValidUrlPatterns() { |
118 | - return webappUrlPatterns && webappUrlPatterns.length !== 0 |
119 | - } |
120 | - |
121 | - /*function navigationRequestedDelegate(request) { |
122 | - if (!request.isMainFrame) { |
123 | - request.action = WebView.AcceptRequest |
124 | - return |
125 | - } |
126 | - |
127 | - // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
128 | - // or if we dont have a list of url patterns specified to filter the |
129 | - // browsing actions |
130 | - if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
131 | - request.action = WebView.AcceptRequest |
132 | - return |
133 | - } |
134 | - |
135 | - var action = WebView.IgnoreRequest |
136 | - var url = request.url.toString() |
137 | - |
138 | - // The list of url patterns defined by the webapp takes precedence over command line |
139 | - if (isRunningAsANamedWebapp()) { |
140 | - if (unityWebapps.model.exists(unityWebapps.name) && |
141 | - unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
142 | - request.action = WebView.AcceptRequest |
143 | - return; |
144 | - } |
145 | - } |
146 | - |
147 | - // We still take the possible additional patterns specified in the command line |
148 | - // (the in the case of finer grained ones specifically for the container and not |
149 | - // as an 'install source' for the webapp). |
150 | - if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
151 | - for (var i = 0; i < webappUrlPatterns.length; ++i) { |
152 | - var pattern = webappUrlPatterns[i] |
153 | - if (url.match(pattern)) { |
154 | - action = WebView.AcceptRequest |
155 | - break |
156 | - } |
157 | - } |
158 | - } |
159 | - |
160 | - request.action = action |
161 | - if (action === WebView.IgnoreRequest) { |
162 | - console.debug('Opening: ' + url + ' in the browser window.') |
163 | - Qt.openUrlExternally(url) |
164 | - } |
165 | - }*/ |
166 | - |
167 | - onNewTabRequested: Qt.openUrlExternally(url) |
168 | - |
169 | - preferences.localStorageEnabled: true |
170 | - |
171 | - // Small shim needed when running as a webapp to wire-up connections |
172 | - // with the webview (message received, etc…). |
173 | - // This is being called (and expected) internally by the webapps |
174 | - // component as a way to bind to a webview lookalike without |
175 | - // reaching out directly to its internals (see it as an interface). |
176 | - function getUnityWebappsProxies() { |
177 | - var eventHandlers = { |
178 | - onAppRaised: function () { |
179 | - if (webbrowserWindow) { |
180 | - try { |
181 | - webbrowserWindow.raise(); |
182 | - } catch (e) { |
183 | - console.debug('Error while raising: ' + e); |
184 | - } |
185 | - } |
186 | - } |
187 | - }; |
188 | - return UnityWebAppsUtils.makeProxiesForWebViewBindee(webview, eventHandlers) |
189 | - } |
190 | + developerExtrasEnabled: webapp.developerExtrasEnabled |
191 | } |
192 | |
193 | ErrorSheet { |
194 | anchors.fill: webview |
195 | - visible: webview.lastLoadFailed |
196 | - url: webview.url |
197 | + visible: { |
198 | + if (webview.lastLoadFailed !== undefined) |
199 | + return webview.lastLoadFailed |
200 | + return webview.currentWebview && webview.currentWebview.lastLoadFailed |
201 | + } |
202 | + url: webview.currentWebview.url |
203 | onRefreshClicked: webview.reload() |
204 | } |
205 | } |
206 | @@ -166,7 +87,7 @@ |
207 | PanelLoader { |
208 | id: panel |
209 | |
210 | - currentWebview: webview |
211 | + currentWebview: webview.currentWebview |
212 | chromeless: webapp.chromeless |
213 | |
214 | backForwardButtonsVisible: webapp.backForwardButtonsVisible |
215 | @@ -183,12 +104,8 @@ |
216 | UnityWebApps.UnityWebApps { |
217 | id: unityWebapps |
218 | name: webappName |
219 | - bindee: currentWebview |
220 | + bindee: webview.currentWebview |
221 | actionsContext: actionManager.globalContext |
222 | model: UnityWebApps.UnityWebappsAppModel { searchPath: webappModelSearchPath } |
223 | } |
224 | - |
225 | - function isRunningAsANamedWebapp() { |
226 | - return webappName && typeof(webappName) === 'string' && webappName.length != 0 |
227 | - } |
228 | } |
229 | |
230 | === added file 'src/app/webcontainer/WebViewImplWebkit.qml' |
231 | --- src/app/webcontainer/WebViewImplWebkit.qml 1970-01-01 00:00:00 +0000 |
232 | +++ src/app/webcontainer/WebViewImplWebkit.qml 2014-03-28 16:05:34 +0000 |
233 | @@ -0,0 +1,159 @@ |
234 | +/* |
235 | + * Copyright 2013 Canonical Ltd. |
236 | + * |
237 | + * This file is part of webbrowser-app. |
238 | + * |
239 | + * webbrowser-app is free software; you can redistribute it and/or modify |
240 | + * it under the terms of the GNU General Public License as published by |
241 | + * the Free Software Foundation; version 3. |
242 | + * |
243 | + * webbrowser-app is distributed in the hope that it will be useful, |
244 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
245 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
246 | + * GNU General Public License for more details. |
247 | + * |
248 | + * You should have received a copy of the GNU General Public License |
249 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
250 | + */ |
251 | + |
252 | +import QtQuick 2.0 |
253 | +import QtWebKit 3.1 |
254 | +import QtWebKit.experimental 1.0 |
255 | +import Ubuntu.Components 0.1 |
256 | +import Ubuntu.Components.Extras.Browser 0.1 |
257 | +import Ubuntu.UnityWebApps 0.1 as UnityWebApps |
258 | +import Ubuntu.Components.Popups 0.1 |
259 | +import "../actions" as Actions |
260 | +import ".." |
261 | + |
262 | +UbuntuWebView { |
263 | + id: webview |
264 | + |
265 | + property bool developerExtrasEnabled: false |
266 | + property var currentWebview: webview |
267 | + property var toolbar: null |
268 | + property string webappName: "" |
269 | + property var webappUrlPatterns: null |
270 | + |
271 | + experimental.certificateVerificationDialog: CertificateVerificationDialog {} |
272 | + experimental.authenticationDialog: AuthenticationDialog {} |
273 | + experimental.proxyAuthenticationDialog: ProxyAuthenticationDialog {} |
274 | + experimental.alertDialog: AlertDialog {} |
275 | + experimental.confirmDialog: ConfirmDialog {} |
276 | + experimental.promptDialog: PromptDialog {} |
277 | + |
278 | + selectionActions: ActionList { |
279 | + Actions.Copy { |
280 | + onTriggered: selection.copy() |
281 | + } |
282 | + } |
283 | + |
284 | + property bool lastLoadFailed: false |
285 | + onLoadingChanged: { |
286 | + lastLoadFailed = (loadRequest.status === WebView.LoadFailedStatus) |
287 | + } |
288 | + |
289 | + experimental.preferences.developerExtrasEnabled: developerExtrasEnabled |
290 | + |
291 | + experimental.onPermissionRequested: { |
292 | + if (permission.type === PermissionRequest.Geolocation) { |
293 | + if (webview.toolbar) { |
294 | + webview.toolbar.close() |
295 | + } |
296 | + var text = i18n.tr("This page wants to know your device’s location.") |
297 | + PopupUtils.open(Qt.resolvedUrl("PermissionRequest.qml"), |
298 | + webview.currentWebview, |
299 | + {"permission": permission, "text": text}) |
300 | + } |
301 | + // TODO: handle other types of permission requests |
302 | + // TODO: we might want to store the answer to avoid requesting |
303 | + // the permission everytime the user visits this site. |
304 | + } |
305 | + |
306 | + contextualActions: ActionList { |
307 | + Actions.CopyLink { |
308 | + enabled: webview.contextualData.href.toString() |
309 | + onTriggered: Clipboard.push([webview.contextualData.href]) |
310 | + } |
311 | + Actions.CopyImage { |
312 | + enabled: webview.contextualData.img.toString() |
313 | + onTriggered: Clipboard.push([webview.contextualData.img]) |
314 | + } |
315 | + } |
316 | + |
317 | + function isRunningAsANamedWebapp() { |
318 | + return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0 |
319 | + } |
320 | + |
321 | + function haveValidUrlPatterns() { |
322 | + return webappUrlPatterns && webappUrlPatterns.length !== 0 |
323 | + } |
324 | + |
325 | + function navigationRequestedDelegate(request) { |
326 | + if (!request.isMainFrame) { |
327 | + request.action = WebView.AcceptRequest |
328 | + return |
329 | + } |
330 | + |
331 | + // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
332 | + // or if we dont have a list of url patterns specified to filter the |
333 | + // browsing actions |
334 | + if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
335 | + request.action = WebView.AcceptRequest |
336 | + return |
337 | + } |
338 | + |
339 | + var action = WebView.IgnoreRequest |
340 | + var url = request.url.toString() |
341 | + |
342 | + // The list of url patterns defined by the webapp takes precedence over command line |
343 | + if (isRunningAsANamedWebapp()) { |
344 | + if (unityWebapps.model.exists(unityWebapps.name) && |
345 | + unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
346 | + request.action = WebView.AcceptRequest |
347 | + return; |
348 | + } |
349 | + } |
350 | + |
351 | + // We still take the possible additional patterns specified in the command line |
352 | + // (the in the case of finer grained ones specifically for the container and not |
353 | + // as an 'install source' for the webapp). |
354 | + if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
355 | + for (var i = 0; i < webappUrlPatterns.length; ++i) { |
356 | + var pattern = webappUrlPatterns[i] |
357 | + if (url.match(pattern)) { |
358 | + action = WebView.AcceptRequest |
359 | + break |
360 | + } |
361 | + } |
362 | + } |
363 | + |
364 | + request.action = action |
365 | + if (action === WebView.IgnoreRequest) { |
366 | + console.debug('Opening: ' + url + ' in the browser window.') |
367 | + Qt.openUrlExternally(url) |
368 | + } |
369 | + } |
370 | + |
371 | + onNewTabRequested: Qt.openUrlExternally(url) |
372 | + |
373 | + // Small shim needed when running as a webapp to wire-up connections |
374 | + // with the webview (message received, etc…). |
375 | + // This is being called (and expected) internally by the webapps |
376 | + // component as a way to bind to a webview lookalike without |
377 | + // reaching out directly to its internals (see it as an interface). |
378 | + function getUnityWebappsProxies() { |
379 | + var eventHandlers = { |
380 | + onAppRaised: function () { |
381 | + if (webbrowserWindow) { |
382 | + try { |
383 | + webbrowserWindow.raise(); |
384 | + } catch (e) { |
385 | + console.debug('Error while raising: ' + e); |
386 | + } |
387 | + } |
388 | + } |
389 | + }; |
390 | + return UnityWebAppsUtils.makeProxiesForQtWebViewBindee(webview, eventHandlers) |
391 | + } |
392 | +} |
393 | |
394 | === added file 'src/app/webcontainer/WebappContainerWebview.qml' |
395 | --- src/app/webcontainer/WebappContainerWebview.qml 1970-01-01 00:00:00 +0000 |
396 | +++ src/app/webcontainer/WebappContainerWebview.qml 2014-03-28 16:05:34 +0000 |
397 | @@ -0,0 +1,151 @@ |
398 | +/* |
399 | + * Copyright 2014 Canonical Ltd. |
400 | + * |
401 | + * This file is part of webbrowser-app. |
402 | + * |
403 | + * webbrowser-app is free software; you can redistribute it and/or modify |
404 | + * it under the terms of the GNU General Public License as published by |
405 | + * the Free Software Foundation; version 3. |
406 | + * |
407 | + * webbrowser-app is distributed in the hope that it will be useful, |
408 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
409 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
410 | + * GNU General Public License for more details. |
411 | + * |
412 | + * You should have received a copy of the GNU General Public License |
413 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
414 | + */ |
415 | + |
416 | +import QtQuick 2.0 |
417 | +import Ubuntu.Components 0.1 |
418 | +import Ubuntu.Unity.Action 1.0 as UnityActions |
419 | +import Ubuntu.UnityWebApps 0.1 as UnityWebApps |
420 | +import "../actions" as Actions |
421 | +import ".." |
422 | + |
423 | +Item { |
424 | + id: containerWebview |
425 | + |
426 | + property string url: "" |
427 | + property bool withOxide: false |
428 | + property bool developerExtrasEnabled: false |
429 | + property string webappName: "" |
430 | + property var currentWebview: webappContainerWebViewLoader.item |
431 | + property var toolbar: null |
432 | + property var webappUrlPatterns: null |
433 | + |
434 | + Loader { |
435 | + id: webappContainerWebViewLoader |
436 | + anchors.fill: parent |
437 | + sourceComponent: withOxide ? webappContainerWebViewOxide : webappContainerWebViewWebkit |
438 | + } |
439 | + |
440 | + Component { |
441 | + id: webappContainerWebViewWebkit |
442 | + |
443 | + WebViewImplWebkit { |
444 | + toolbar: containerWebview.toolbar |
445 | + url: containerWebview.url |
446 | + webappName: containerWebview.webappName |
447 | + webappUrlPatterns: containerWebview.webappUrlPatterns |
448 | + developerExtrasEnabled: containerWebview.developerExtrasEnabled |
449 | + } |
450 | + } |
451 | + |
452 | + Component { |
453 | + id: webappContainerWebViewOxide |
454 | + |
455 | + WebViewImpl { |
456 | + id: webview |
457 | + |
458 | + url: containerWebview.url |
459 | + currentWebview: webview |
460 | + toolbar: containerWebview.toolbar |
461 | + |
462 | + contextualActions: ActionList { |
463 | + Actions.CopyLink { |
464 | + enabled: webview.contextualData.href.toString() |
465 | + onTriggered: Clipboard.push([webview.contextualData.href]) |
466 | + } |
467 | + Actions.CopyImage { |
468 | + enabled: webview.contextualData.img.toString() |
469 | + onTriggered: Clipboard.push([webview.contextualData.img]) |
470 | + } |
471 | + } |
472 | + |
473 | + function haveValidUrlPatterns() { |
474 | + return webappUrlPatterns && webappUrlPatterns.length !== 0 |
475 | + } |
476 | + |
477 | + /*function navigationRequestedDelegate(request) { |
478 | + if (!request.isMainFrame) { |
479 | + request.action = WebView.AcceptRequest |
480 | + return |
481 | + } |
482 | + |
483 | + // Pass-through if we are not running as a named webapp (--webapp='Gmail') |
484 | + // or if we dont have a list of url patterns specified to filter the |
485 | + // browsing actions |
486 | + if ( ! haveValidUrlPatterns() && ! isRunningAsANamedWebapp()) { |
487 | + request.action = WebView.AcceptRequest |
488 | + return |
489 | + } |
490 | + |
491 | + var action = WebView.IgnoreRequest |
492 | + var url = request.url.toString() |
493 | + |
494 | + // The list of url patterns defined by the webapp takes precedence over command line |
495 | + if (isRunningAsANamedWebapp()) { |
496 | + if (unityWebapps.model.exists(unityWebapps.name) && |
497 | + unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) { |
498 | + request.action = WebView.AcceptRequest |
499 | + return; |
500 | + } |
501 | + } |
502 | + |
503 | + // We still take the possible additional patterns specified in the command line |
504 | + // (the in the case of finer grained ones specifically for the container and not |
505 | + // as an 'install source' for the webapp). |
506 | + if (webappUrlPatterns && webappUrlPatterns.length !== 0) { |
507 | + for (var i = 0; i < webappUrlPatterns.length; ++i) { |
508 | + var pattern = webappUrlPatterns[i] |
509 | + if (url.match(pattern)) { |
510 | + action = WebView.AcceptRequest |
511 | + break |
512 | + } |
513 | + } |
514 | + } |
515 | + |
516 | + request.action = action |
517 | + if (action === WebView.IgnoreRequest) { |
518 | + console.debug('Opening: ' + url + ' in the browser window.') |
519 | + Qt.openUrlExternally(url) |
520 | + } |
521 | + }*/ |
522 | + |
523 | + onNewTabRequested: Qt.openUrlExternally(url) |
524 | + |
525 | + preferences.localStorageEnabled: true |
526 | + |
527 | + // Small shim needed when running as a webapp to wire-up connections |
528 | + // with the webview (message received, etc…). |
529 | + // This is being called (and expected) internally by the webapps |
530 | + // component as a way to bind to a webview lookalike without |
531 | + // reaching out directly to its internals (see it as an interface). |
532 | + function getUnityWebappsProxies() { |
533 | + var eventHandlers = { |
534 | + onAppRaised: function () { |
535 | + if (webbrowserWindow) { |
536 | + try { |
537 | + webbrowserWindow.raise(); |
538 | + } catch (e) { |
539 | + console.debug('Error while raising: ' + e); |
540 | + } |
541 | + } |
542 | + } |
543 | + }; |
544 | + return UnityWebAppsUtils.makeProxiesForWebViewBindee(webview, eventHandlers) |
545 | + } |
546 | + } |
547 | + } |
548 | +} |
549 | |
550 | === modified file 'src/app/webcontainer/webapp-container.cpp' |
551 | --- src/app/webcontainer/webapp-container.cpp 2014-03-20 18:17:12 +0000 |
552 | +++ src/app/webcontainer/webapp-container.cpp 2014-03-28 16:05:34 +0000 |
553 | @@ -24,10 +24,32 @@ |
554 | // Qt |
555 | #include <QtCore/QCoreApplication> |
556 | #include <QtCore/QDebug> |
557 | +#include <QtCore/QFile> |
558 | #include <QtCore/QFileInfo> |
559 | +#include <QtCore/QtGlobal> |
560 | #include <QtCore/QRegularExpression> |
561 | #include <QtCore/QTextStream> |
562 | #include <QtQuick/QQuickWindow> |
563 | +#include <QtQml/QQmlComponent> |
564 | + |
565 | + |
566 | +namespace |
567 | +{ |
568 | + |
569 | +QString currentArchitecturePathName() |
570 | +{ |
571 | +#if defined(Q_PROCESSOR_X86_32) |
572 | + return QLatin1String("i386-linux-gnu"); |
573 | +#elif defined(Q_PROCESSOR_X86_64) |
574 | + return QLatin1String("x86_64-linux-gnu"); |
575 | +#elif defined(Q_PROCESSOR_ARM) |
576 | + return QLatin1String("arm-linux-gnueabihf"); |
577 | +#else |
578 | +#error Unable to determine target architecture |
579 | +#endif |
580 | +} |
581 | + |
582 | +} |
583 | |
584 | WebappContainer::WebappContainer(int& argc, char** argv) |
585 | : BrowserApplication(argc, argv) |
586 | @@ -50,7 +72,13 @@ |
587 | m_window->setProperty("webappName", name); |
588 | m_window->setProperty("backForwardButtonsVisible", m_arguments.contains("--enable-back-forward")); |
589 | m_window->setProperty("addressBarVisible", m_arguments.contains("--enable-addressbar")); |
590 | + |
591 | + bool oxide = withOxide(); |
592 | + qDebug() << "Using" << (oxide ? "Oxide" : "QtWebkit") << "as the web engine backend"; |
593 | + m_window->setProperty("oxide", oxide); |
594 | + |
595 | m_window->setProperty("webappUrlPatterns", webappUrlPatterns()); |
596 | + |
597 | // When a webapp is being launched by name, the URL is pulled from its 'homepage'. |
598 | if (name.isEmpty()) { |
599 | QList<QUrl> urls = this->urls(); |
600 | @@ -58,6 +86,9 @@ |
601 | m_window->setProperty("url", urls.first()); |
602 | } |
603 | } |
604 | + |
605 | + m_component->completeCreate(); |
606 | + |
607 | return true; |
608 | } else { |
609 | return false; |
610 | @@ -84,6 +115,31 @@ |
611 | out << " --enable-addressbar enable the display of the address bar" << endl; |
612 | } |
613 | |
614 | +bool WebappContainer::withOxide() const |
615 | +{ |
616 | + Q_FOREACH(const QString& argument, m_arguments) { |
617 | + if (argument == "--webkit") { |
618 | + // force webkit |
619 | + return false; |
620 | + } |
621 | + if (argument == "--oxide") { |
622 | + // force oxide |
623 | + return true; |
624 | + } |
625 | + } |
626 | + |
627 | + // Use a runtime hint to transparently know if oxide |
628 | + // can be used as a backend without the user/dev having |
629 | + // to update its app or change something in the Exec args. |
630 | + // Version 1.1 of ubuntu apparmor policy allows this file to |
631 | + // be accessed whereas v1.0 only knows about qtwebkit. |
632 | + QString oxideHintLocation = |
633 | + QString("/usr/lib/%1/oxide-qt/oxide-renderer") |
634 | + .arg(currentArchitecturePathName()); |
635 | + |
636 | + return QFile(oxideHintLocation).open(QIODevice::ReadOnly); |
637 | +} |
638 | + |
639 | QString WebappContainer::webappModelSearchPath() const |
640 | { |
641 | Q_FOREACH(const QString& argument, m_arguments) { |
642 | |
643 | === modified file 'src/app/webcontainer/webapp-container.h' |
644 | --- src/app/webcontainer/webapp-container.h 2014-03-14 14:51:22 +0000 |
645 | +++ src/app/webcontainer/webapp-container.h 2014-03-28 16:05:34 +0000 |
646 | @@ -39,6 +39,7 @@ |
647 | QString webappModelSearchPath() const; |
648 | QString webappName() const; |
649 | QStringList webappUrlPatterns() const; |
650 | + bool withOxide() const; |
651 | }; |
652 | |
653 | #endif // __WEBAPP_CONTAINER_H__ |
654 | |
655 | === modified file 'src/app/webcontainer/webapp-container.qml' |
656 | --- src/app/webcontainer/webapp-container.qml 2014-03-17 10:16:11 +0000 |
657 | +++ src/app/webcontainer/webapp-container.qml 2014-03-28 16:05:34 +0000 |
658 | @@ -30,6 +30,7 @@ |
659 | property alias webappName: browser.webappName |
660 | property alias webappModelSearchPath: browser.webappModelSearchPath |
661 | property alias webappUrlPatterns: browser.webappUrlPatterns |
662 | + property alias oxide: browser.oxide |
663 | |
664 | contentOrientation: browser.screenOrientation |
665 |
A couple of general remarks before I dive in the code more seriously:
- could you please get rid of the ComponentCreation parameter, thus making the instantiation of the component always a 2-step process? I don’t think we’re gaining anything from having two separate code paths there. See https:/ /code.launchpad .net/~mardy/ webbrowser- app/add- onlineaccount- support- for-container2/ +merge/ 211701 where Alberto did that
- the runtime dep on libqt5webkit5- qmlwebkitplugin should be added to webapp-container, not webbrowser-app
- detecting the architecture would probably be more reliable by testing the definition of Q_PROCESSOR_X86_32, Q_PROCESSOR_X86_64, and Q_PROCESSOR_ARM (include <QtCore/QtGlobal> to make use of them)
- out of curiosity, wouldn’t using the QFile API work to test whether we can access the oxide-renderer binary?