Merge lp:~abreu-alexandre/webbrowser-app/support-oxide-and-qtwebkit into lp:~osomon/webbrowser-app/with-oxide

Proposed by Alexandre Abreu on 2014-03-26
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
Reviewer Review Type Date Requested Status
Olivier Tilloy 2014-03-26 Needs Fixing on 2014-03-28
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,

To post a comment you must log in.
488. By Alexandre Abreu on 2014-03-26

merge trunk

489. By Alexandre Abreu on 2014-03-26

fixes

490. By Alexandre Abreu on 2014-03-26

Add build deps

Olivier Tilloy (osomon) wrote :

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?

review: Needs Fixing
491. By Alexandre Abreu on 2014-03-27

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::withOxide(), what about adding recognition for a "--oxide" flag to force the use of oxide, for testing purposes (that would be handy for me on my development workstation where I don’t have oxide installed system-wide - I use a locally compiled version) ?

Olivier Tilloy (osomon) wrote :

632 + // to update its app or change somehting in the Exec args.

typo: s/somehting/something/

Olivier Tilloy (osomon) wrote :

In WebappContainer::withOxide(), can you make the comment extra explicit by 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.

492. By Alexandre Abreu on 2014-03-27

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::withOxide(), can you make the comment extra explicit by
> 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/something/

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/lib/arm-linux-gnueabihf/oxide-qt/chrome-sandbox

QFile::exists() is probably not good enough to check access rights.
I have tried the following:

    return QFile(oxideHintLocation).open(QIODevice::ReadOnly);

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?

review: Needs Fixing
Jamie Strandboge (jdstrand) wrote :

So, 1.0 of the policy doesn't block the access. I'll update the apparmor-easyprof-ubuntu policy to make sure it does.

493. By Alexandre Abreu on 2014-03-28

simplify oxide detection

Olivier Tilloy (osomon) wrote :

currentArchitecturePathName() should probably be marked static.

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: containerWebview.toolbar

494. By Alexandre Abreu on 2014-03-28

Fixes

Olivier Tilloy (osomon) wrote :

287 + experimental.preferences.developerExtrasEnabled: developerExtrasEnabled

"developerExtrasEnabled" is not defined in this context (this might actually work because it is defined in a parent context, but it breaks encapsulation, thus making the code hard to read and to maintain).
Can you make it a property of the WebViewImplWebkit and ensure it’s set from the caller?

495. By Alexandre Abreu on 2014-03-28

Fixes

496. By Alexandre Abreu on 2014-03-28

Fixes

Olivier Tilloy (osomon) wrote :

In src/app/webcontainer/WebApp.qml:

    property alias developerExtrasEnabled: webview.developerExtrasEnabled

I don’t think this will work, because WebApp is an instance of BrowserView which already defines a top-level "developerExtrasEnabled" property.

497. By Alexandre Abreu on 2014-03-28

Fix developer extra enabled

Alexandre Abreu (abreu-alexandre) wrote :

> In src/app/webcontainer/WebApp.qml:
>
> property alias developerExtrasEnabled: webview.developerExtrasEnabled
>
> I don’t think this will work, because WebApp is an instance of BrowserView
> which already defines a top-level "developerExtrasEnabled" property.

right, done

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 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

Subscribers

People subscribed via source and target branches