Merge lp:~abreu-alexandre/unity-webapps-qml/add-content-hub-share into lp:unity-webapps-qml

Proposed by Alexandre Abreu
Status: Merged
Merged at revision: 123
Proposed branch: lp:~abreu-alexandre/unity-webapps-qml/add-content-hub-share
Merge into: lp:unity-webapps-qml
Diff against target: 1120 lines (+718/-23)
20 files modified
examples/facebook-share/content-hub/webapp-facebook.json (+5/-0)
examples/facebook-share/manifest.json (+18/-0)
examples/facebook-share/unity-webapps-facebook/HubSharer.qml (+41/-0)
examples/facebook-share/unity-webapps-facebook/Share.qml (+323/-0)
examples/facebook-share/unity-webapps-facebook/facebook.user.js (+47/-0)
examples/facebook-share/unity-webapps-facebook/manifest.json (+7/-0)
examples/facebook-share/webapp-facebook.application (+11/-0)
examples/facebook-share/webapp-facebook.desktop (+9/-0)
examples/facebook-share/webapp-facebook.json (+13/-0)
examples/facebook-share/webapp-facebook.service (+6/-0)
src/Ubuntu/UnityWebApps/Settings.qml (+1/-0)
src/Ubuntu/UnityWebApps/UnityWebApps.js (+9/-2)
src/Ubuntu/UnityWebApps/UnityWebApps.qml (+86/-14)
src/Ubuntu/UnityWebApps/UnityWebAppsUtils.js (+5/-0)
src/Ubuntu/UnityWebApps/bindings/content-hub/backend/content-hub.js (+27/-1)
src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js (+77/-4)
src/Ubuntu/UnityWebApps/bindings/online-accounts/backend/online-accounts.js (+1/-1)
src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.cpp (+19/-0)
src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.h (+7/-1)
src/Ubuntu/UnityWebApps/unity-webapps-api.js.in (+6/-0)
To merge this branch: bzr merge lp:~abreu-alexandre/unity-webapps-qml/add-content-hub-share
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
WebApps Pending
Review via email: mp+224523@code.launchpad.net

Commit message

add content share

Description of the change

add content share

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
134. By Alexandre Abreu

fixes

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'examples/facebook-share'
2=== added directory 'examples/facebook-share/content-hub'
3=== added file 'examples/facebook-share/content-hub/webapp-facebook.json'
4--- examples/facebook-share/content-hub/webapp-facebook.json 1970-01-01 00:00:00 +0000
5+++ examples/facebook-share/content-hub/webapp-facebook.json 2014-06-26 01:46:50 +0000
6@@ -0,0 +1,5 @@
7+{
8+ "share": [
9+ "pictures"
10+ ]
11+}
12
13=== added file 'examples/facebook-share/facebook.png'
14Binary files examples/facebook-share/facebook.png 1970-01-01 00:00:00 +0000 and examples/facebook-share/facebook.png 2014-06-26 01:46:50 +0000 differ
15=== added file 'examples/facebook-share/manifest.json'
16--- examples/facebook-share/manifest.json 1970-01-01 00:00:00 +0000
17+++ examples/facebook-share/manifest.json 2014-06-26 01:46:50 +0000
18@@ -0,0 +1,18 @@
19+{
20+ "description": "Facebook (webapp version)",
21+ "framework": "ubuntu-sdk-14.10-dev1",
22+ "architecture": "all",
23+ "hooks": {
24+ "webapp-facebook": {
25+ "account-application": "webapp-facebook.application",
26+ "content-hub": "content-hub/webapp-facebook.json",
27+ "account-service": "webapp-facebook.service",
28+ "apparmor": "webapp-facebook.json",
29+ "desktop": "webapp-facebook.desktop"
30+ }
31+ },
32+ "maintainer": "Webapps Team <webapps@lists.launchpad.net>",
33+ "name": "com.ubuntu.developer.webapps.webapp-facebook",
34+ "title": "webapp-facebook",
35+ "version": "1.0.17.4"
36+}
37
38=== added directory 'examples/facebook-share/unity-webapps-facebook'
39=== added file 'examples/facebook-share/unity-webapps-facebook/HubSharer.qml'
40--- examples/facebook-share/unity-webapps-facebook/HubSharer.qml 1970-01-01 00:00:00 +0000
41+++ examples/facebook-share/unity-webapps-facebook/HubSharer.qml 2014-06-26 01:46:50 +0000
42@@ -0,0 +1,41 @@
43+import QtQuick 2.0
44+import Ubuntu.Components 0.1
45+import Ubuntu.Content 0.1
46+
47+Item {
48+ id: main
49+ anchors.fill: parent
50+
51+ signal completed(string result)
52+
53+ property string fileToShare
54+
55+ function _callback(accessToken, fileToShare, message, cb) {
56+ print ("_callback: " + accessToken);
57+ print ("_callback: " + fileToShare);
58+ print ("_callback: " + message);
59+
60+ itemComp.url = fileToShare;
61+ var dataUri = itemComp.toDataURI();
62+ var result = {accessToken: accessToken,
63+ fileToShare: dataUri.toString(),
64+ message: message};
65+
66+ completed(JSON.stringify(result));
67+ }
68+
69+ ContentItem {
70+ id: itemComp
71+ }
72+
73+ Share {
74+ anchors.fill: parent
75+ visible: true
76+ fileToShare: main.fileToShare
77+ callback: _callback
78+ provider: "facebook"
79+ onCanceled: completed(JSON.stringify({status: "cancelled"}))
80+ onUploadCompleted: console.log (success)
81+ Component.onCompleted: print ("Page completed " + height + " : " + width)
82+ }
83+}
84
85=== added file 'examples/facebook-share/unity-webapps-facebook/Share.qml'
86--- examples/facebook-share/unity-webapps-facebook/Share.qml 1970-01-01 00:00:00 +0000
87+++ examples/facebook-share/unity-webapps-facebook/Share.qml 2014-06-26 01:46:50 +0000
88@@ -0,0 +1,323 @@
89+/*
90+ * Copyright (C) 2012-2013 Canonical, Ltd.
91+ *
92+ * This program is free software; you can redistribute it and/or modify
93+ * it under the terms of the GNU General Public License as published by
94+ * the Free Software Foundation; version 3.
95+ *
96+ * This program is distributed in the hope that it will be useful,
97+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
98+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99+ * GNU General Public License for more details.
100+ *
101+ * You should have received a copy of the GNU General Public License
102+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
103+ */
104+
105+import QtQuick 2.0
106+import QtQuick.Window 2.0
107+import Ubuntu.Components 0.1
108+import Ubuntu.Components.ListItems 0.1 as ListItem
109+import Ubuntu.OnlineAccounts 0.1
110+
111+Rectangle {
112+ id: root
113+ anchors.fill: parent
114+ color: Theme.palette.normal.background
115+ property string fileToShare
116+ property var callback
117+ property string serviceType: "webapps"
118+ property string provider: "facebook"
119+ property string userAccountId
120+ property string accessToken
121+ property var account
122+ signal accountSelected
123+ signal canceled()
124+ signal uploadCompleted(bool success)
125+
126+ onUploadCompleted: {
127+ activitySpinner.visible = false;
128+ if (success)
129+ print ("Successfully posted");
130+ else
131+ print ("Failed to post");
132+ }
133+
134+ AccountServiceModel {
135+ id: accounts
136+ serviceType: root.serviceType
137+ provider: root.provider
138+ Component.onCompleted: {
139+ if (count == 1) {
140+ srv.objectHandle = get(0, "accountServiceHandle");
141+ }
142+ }
143+ }
144+
145+ AccountService {
146+ id: srv
147+ onObjectHandleChanged: {
148+ root.account = srv;
149+ root.account.authenticate(null);
150+ }
151+ onAuthenticated: {
152+ root.userAccountId = accountId;
153+ root.accessToken = reply.AccessToken;
154+ shareComponent.visible = true;
155+ sharemenu.visible = false;
156+ }
157+ }
158+
159+
160+ Rectangle {
161+ id: shareComponent
162+ objectName: "shareComponent"
163+ anchors.fill: parent
164+ color: Theme.palette.normal.background
165+ visible: false
166+
167+ Column {
168+ anchors.fill: parent
169+ spacing: units.gu(1)
170+
171+ Item {
172+ id: serviceHeader
173+ y: 0
174+ anchors.left: parent.left
175+ anchors.right: parent.right
176+ anchors.topMargin: units.gu(1)
177+ anchors.leftMargin: units.gu(1)
178+ anchors.rightMargin: units.gu(1)
179+ height: childrenRect.height
180+
181+ ListItem.Subtitled {
182+ anchors {
183+ left: parent.left
184+ right: parent.right
185+ }
186+ iconName: root.account.provider.iconName
187+ text: root.account.provider.displayName
188+ subText: root.account.displayName
189+ showDivider: false
190+ }
191+ }
192+
193+ ListItem.ThinDivider {}
194+
195+ UbuntuShape {
196+ id: messageArea
197+ objectName: "messageArea"
198+ anchors.left: parent.left
199+ anchors.right: parent.right
200+ anchors.topMargin: units.gu(1)
201+ anchors.leftMargin: units.gu(1)
202+ anchors.rightMargin: units.gu(1)
203+
204+ height: units.gu(20)
205+ color: "#f2f2f2"
206+
207+ TextEdit {
208+ id: message
209+ color: "#333333"
210+ anchors.top: parent.top
211+ anchors.left: snapshot.right
212+ anchors.bottom: parent.bottom
213+ anchors.margins: units.gu(1)
214+ wrapMode: Text.Wrap
215+ width: parent.width - snapshot.width -
216+ snapshot.anchors.margins * 2 -
217+ message.anchors.leftMargin - message.anchors.rightMargin
218+ clip: true
219+ font.pixelSize: FontUtils.sizeToPixels("medium")
220+ font.weight: Font.Light
221+ focus: true
222+ }
223+
224+ ActivityIndicator {
225+ id: activitySpinner
226+ anchors.centerIn: message
227+ visible: false
228+ running: visible
229+ }
230+
231+ UbuntuShape {
232+ id: snapshot
233+ anchors.top: parent.top
234+ anchors.left: parent.left
235+ anchors.margins: units.gu(1)
236+ width: units.gu(10)
237+ height: units.gu(10)
238+
239+ image: Image {
240+ source: fileToShare
241+ sourceSize.height: snapshot.height
242+ sourceSize.width: snapshot.width
243+ fillMode: Image.PreserveAspectCrop
244+ }
245+ }
246+ }
247+
248+ Item {
249+ id: actionsBar
250+ anchors.left: parent.left
251+ anchors.right: parent.right
252+ anchors.topMargin: units.gu(2)
253+ anchors.leftMargin: units.gu(1)
254+ anchors.rightMargin: units.gu(1)
255+ height: childrenRect.height
256+
257+ Button {
258+ objectName: "cancelButton"
259+ anchors.left: parent.left
260+ text: i18n.dtr("ubuntu-ui-extras", "Cancel")
261+ color: "#cccccc"
262+ width: units.gu(10)
263+ height: units.gu(4)
264+ onClicked: canceled()
265+ }
266+
267+ Button {
268+ objectName: "postButton"
269+ anchors.right: parent.right
270+ anchors.top: parent.top
271+ text: i18n.dtr("ubuntu-ui-extras", "Post")
272+ color: "#dd4814"
273+ width: units.gu(10)
274+ height: units.gu(4)
275+ enabled: !activitySpinner.visible
276+ onClicked: {
277+ activitySpinner.visible = true;
278+ callback(accessToken, fileToShare, message.text, uploadCompleted);
279+ }
280+ }
281+ }
282+
283+ UbuntuShape {
284+ id: useLocation
285+ anchors {
286+ left: parent.left
287+ leftMargin: units.gu(1)
288+ topMargin: units.gu(1)
289+ }
290+ color: selected ? "#cccccc" : "transparent"
291+ property bool selected: false
292+ width: units.gu(4.5)
293+ height: units.gu(4)
294+
295+ AbstractButton {
296+ anchors.fill: parent
297+ onClicked: parent.selected = !parent.selected
298+ Image {
299+ source: "assets/icon_location.png"
300+ anchors.centerIn: parent
301+ height: parent.height * 0.75
302+ fillMode: Image.PreserveAspectFit
303+ smooth: true
304+ }
305+ }
306+ }
307+
308+ Label {
309+ anchors.left: useLocation.right
310+ anchors.baseline: useLocation.top
311+ anchors.baselineOffset: units.gu(3)
312+ anchors.leftMargin: units.gu(1)
313+ text: i18n.dtr("ubuntu-ui-extras", "Include location")
314+ fontSize: "small"
315+ }
316+
317+ }
318+
319+ states: [
320+ State {
321+ name: "landscape-with-keyborad"
322+ PropertyChanges {
323+ target: serviceHeader
324+ y: - serviceHeader.height
325+ }
326+ PropertyChanges {
327+ target: messageArea
328+ height: units.gu(12)
329+ }
330+ }
331+ ]
332+
333+ state: ((Screen.orientation === Qt.LandscapeOrientation) ||
334+ (Screen.orientation === Qt.InvertedLandscapeOrientation)) &&
335+ Qt.inputMethod.visible ? "landscape-with-keyborad" : ""
336+ }
337+
338+ /* Menu listing online accounts */
339+ Item {
340+ id: sharemenu
341+ anchors.fill: parent
342+ visible: true
343+
344+ signal selected(string accountId, string token)
345+
346+ Component.onCompleted: {
347+ visible = true;
348+ }
349+ onSelected: {
350+ root.userAccountId = accountId;
351+ root.accessToken = token;
352+ shareComponent.visible = true;
353+ sharemenu.visible = false;
354+ }
355+
356+ Component {
357+ id: acctDelegate
358+ Item {
359+ anchors {
360+ left: parent.left
361+ right: parent.right
362+ }
363+ AccountService {
364+ id: service
365+ objectHandle: accountServiceHandle
366+ onAuthenticated: {
367+ sharemenu.selected(accountId, reply.AccessToken);
368+ }
369+ }
370+
371+ height: childrenRect.height
372+
373+ ListItem.Subtitled {
374+ anchors {
375+ left: parent.left
376+ right: parent.right
377+ }
378+ text: service.provider.displayName
379+ subText: displayName
380+ iconName: service.provider.iconName
381+ __iconHeight: units.gu(5)
382+ __iconWidth: units.gu(5)
383+
384+ onClicked: {
385+ root.account = service;
386+ root.account.authenticate(null);
387+ }
388+ }
389+ }
390+ }
391+
392+ ListView {
393+ anchors {
394+ top: parent.top
395+ left: parent.left
396+ right: parent.right
397+ }
398+ height: childrenRect.height
399+ interactive: false
400+ model: accounts
401+ header: ListItem.Header {
402+ anchors {
403+ left: parent.left
404+ right: parent.right
405+ }
406+ text: i18n.tr("Select account")
407+ }
408+ delegate: acctDelegate
409+ }
410+ }
411+}
412
413=== added directory 'examples/facebook-share/unity-webapps-facebook/assets'
414=== added file 'examples/facebook-share/unity-webapps-facebook/assets/avatar_image.jpg'
415Binary files examples/facebook-share/unity-webapps-facebook/assets/avatar_image.jpg 1970-01-01 00:00:00 +0000 and examples/facebook-share/unity-webapps-facebook/assets/avatar_image.jpg 2014-06-26 01:46:50 +0000 differ
416=== added file 'examples/facebook-share/unity-webapps-facebook/assets/icon_location.png'
417Binary files examples/facebook-share/unity-webapps-facebook/assets/icon_location.png 1970-01-01 00:00:00 +0000 and examples/facebook-share/unity-webapps-facebook/assets/icon_location.png 2014-06-26 01:46:50 +0000 differ
418=== added file 'examples/facebook-share/unity-webapps-facebook/facebook.user.js'
419--- examples/facebook-share/unity-webapps-facebook/facebook.user.js 1970-01-01 00:00:00 +0000
420+++ examples/facebook-share/unity-webapps-facebook/facebook.user.js 2014-06-26 01:46:50 +0000
421@@ -0,0 +1,47 @@
422+var api = external.getUnityObject('1.0');
423+var hub = api.ContentHub;
424+var activeTransfer;
425+
426+function _shareRequested(transfer) {
427+ activeTransfer = transfer;
428+ transfer.items(function(items) {
429+ api.launchEmbeddedUI("HubSharer", upload, {"fileToShare": items[0]});
430+ });
431+};
432+
433+hub.onShareRequested(_shareRequested);
434+
435+function upload(res) {
436+ var results = JSON.parse(res);
437+ if (results.status == "cancelled")
438+ activeTransfer.setState(hub.ContentTransfer.State.Aborted);
439+
440+ var xhr = new XMLHttpRequest();
441+ xhr.open( 'POST', 'https://graph.facebook.com/me/photos?access_token=' + results.accessToken, true );
442+ xhr.onload = xhr.onerror = function() {
443+ if ( xhr.status == 200 )
444+ window.location.reload();
445+ };
446+
447+ var contentType = results.fileToShare.split(',')[0].split(':')[1];
448+ var b64data = results.fileToShare.split(',')[1];
449+
450+ var byteCharacters = atob(b64data);
451+ var byteNumbers = new Array(byteCharacters.length);
452+ for (var i = 0; i < byteCharacters.length; i++) {
453+ byteNumbers[i] = byteCharacters.charCodeAt(i);
454+ }
455+ var byteArray = new Uint8Array(byteNumbers);
456+
457+ var div = document.createElement('div');
458+ div.innerHTML = '<form enctype="multipart/form-data" method="post" id="uploadForm"><textarea id="message" name="message"></textarea></form>';
459+ document.getElementsByTagName('body')[0].appendChild(div);
460+
461+ var blob = new Blob([byteArray], {type: contentType});
462+
463+ var uploadForm = document.forms.namedItem("uploadForm");
464+ var formData = new FormData(uploadForm);
465+ formData.append('source', blob);
466+ formData.append('message', results.message);
467+ xhr.send(formData);
468+}
469
470=== added file 'examples/facebook-share/unity-webapps-facebook/manifest.json'
471--- examples/facebook-share/unity-webapps-facebook/manifest.json 1970-01-01 00:00:00 +0000
472+++ examples/facebook-share/unity-webapps-facebook/manifest.json 2014-06-26 01:46:50 +0000
473@@ -0,0 +1,7 @@
474+{
475+ "name": "facebook",
476+ "includes": ["https://*.facebook.com/*"],
477+ "homepage": "https://m.facebook.com/",
478+ "domain": "facebook.com",
479+ "scripts": ["facebook.user.js"]
480+}
481
482=== added file 'examples/facebook-share/webapp-facebook.application'
483--- examples/facebook-share/webapp-facebook.application 1970-01-01 00:00:00 +0000
484+++ examples/facebook-share/webapp-facebook.application 2014-06-26 01:46:50 +0000
485@@ -0,0 +1,11 @@
486+<?xml version="1.0" encoding="UTF-8" ?>
487+<application id="com.ubuntu.developer.webapps.webapp-facebook_webapp-facebook">
488+ <description>Facebook webapp</description>
489+
490+ <services>
491+ <service id="com.ubuntu.developer.webapps.webapp-facebook_webapp-facebook">
492+ <description>Use the service in a webapp</description>
493+ </service>
494+ </services>
495+
496+</application>
497
498=== added file 'examples/facebook-share/webapp-facebook.desktop'
499--- examples/facebook-share/webapp-facebook.desktop 1970-01-01 00:00:00 +0000
500+++ examples/facebook-share/webapp-facebook.desktop 2014-06-26 01:46:50 +0000
501@@ -0,0 +1,9 @@
502+[Desktop Entry]
503+Type=Application
504+Terminal=false
505+Exec=webapp-container --enable-back-forward --webapp='ZmFjZWJvb2s=' --webappModelSearchPath=. --webappUrlPatterns=https?://*.facebook.com/*
506+Name=Facebook
507+Icon=./facebook.png
508+X-Ubuntu-Touch=true
509+X-Ubuntu-StageHint=SideStage
510+X-Ubuntu-Single-Instance=true
511
512=== added file 'examples/facebook-share/webapp-facebook.json'
513--- examples/facebook-share/webapp-facebook.json 1970-01-01 00:00:00 +0000
514+++ examples/facebook-share/webapp-facebook.json 2014-06-26 01:46:50 +0000
515@@ -0,0 +1,13 @@
516+{
517+ "template": "ubuntu-webapp",
518+ "policy_groups": [
519+ "networking",
520+ "accounts",
521+ "audio",
522+ "video",
523+ "webview",
524+ "location",
525+ "content_exchange"
526+ ],
527+ "policy_version": 1.2
528+}
529
530=== added file 'examples/facebook-share/webapp-facebook.service'
531--- examples/facebook-share/webapp-facebook.service 1970-01-01 00:00:00 +0000
532+++ examples/facebook-share/webapp-facebook.service 2014-06-26 01:46:50 +0000
533@@ -0,0 +1,6 @@
534+<?xml version="1.0" encoding="UTF-8"?>
535+<service id="com.ubuntu.developer.webapps.webapp-facebook_webapp-facebook">
536+ <type>webapps</type>
537+ <name>Facebook Webapp</name>
538+ <provider>facebook</provider>
539+</service>
540
541=== modified file 'src/Ubuntu/UnityWebApps/Settings.qml'
542--- src/Ubuntu/UnityWebApps/Settings.qml 2014-01-17 15:51:27 +0000
543+++ src/Ubuntu/UnityWebApps/Settings.qml 2014-06-26 01:46:50 +0000
544@@ -23,5 +23,6 @@
545 *
546 */
547 property bool injectExtraUbuntuApis: false
548+ property bool injectExtraUILaunchCapabilities: false
549 property bool requiresInit: true
550 }
551
552=== modified file 'src/Ubuntu/UnityWebApps/UnityWebApps.js'
553--- src/Ubuntu/UnityWebApps/UnityWebApps.js 2014-05-08 13:58:56 +0000
554+++ src/Ubuntu/UnityWebApps/UnityWebApps.js 2014-06-26 01:46:50 +0000
555@@ -36,11 +36,12 @@
556 * \param backends
557 * \param userscriptContent
558 */
559- function _UnityWebApps(parentItem, bindeeProxies) {
560+ function _UnityWebApps(parentItem, bindeeProxies, accessPolicy) {
561 this._injected_unity_api_path = Qt.resolvedUrl('unity-webapps-api.js');
562 this._bindeeProxies = bindeeProxies;
563 this._backends = null;
564 this._userscripts = [];
565+ this._accessPolicy = accessPolicy;
566
567 this._bind();
568 };
569@@ -70,7 +71,6 @@
570 */
571 _bind: function () {
572 var self = this;
573-
574 var cb = this._onMessageReceivedCallback.bind(self);
575 self._bindeeProxies.messageReceivedConnect(cb);
576
577@@ -147,6 +147,13 @@
578 var cb = this._wrapCallbackIds (message.callback);
579 params.push(cb);
580 }
581+
582+ var apiCallName = message.name;
583+ if (this._accessPolicy && this._accessPolicy.allowed && !this._accessPolicy.allowed(apiCallName)) {
584+ console.error("Unauthorize API call blocked: " + apiCallName);
585+ return;
586+ }
587+
588 this._dispatchApiCall (message.name, params);
589
590 } else if (target === UnityWebAppsUtils.UBUNTU_WEBAPPS_BINDING_OBJECT_METHOD_CALL_MESSAGE) {
591
592=== modified file 'src/Ubuntu/UnityWebApps/UnityWebApps.qml'
593--- src/Ubuntu/UnityWebApps/UnityWebApps.qml 2014-05-16 16:29:35 +0000
594+++ src/Ubuntu/UnityWebApps/UnityWebApps.qml 2014-06-26 01:46:50 +0000
595@@ -115,21 +115,23 @@
596
597
598 /*!
599- \qmlproperty UnityWebappsAppModel UnityWebApps::extraApisSource
600-
601- An optional model used in conjunction with the 'name' property
602- as a location for looking up the desired webapps.
603+ \qmlproperty bool UnityWebApps::injectExtraUbuntuApis
604
605 */
606 property alias injectExtraUbuntuApis: settings.injectExtraUbuntuApis
607
608 /*!
609- \qmlproperty UnityWebappsAppModel UnityWebApps::extraApisSource
610+ \qmlproperty bool UnityWebApps::injectExtraUILaunchCapabilities
611+
612+ */
613+ property alias injectExtraUILaunchCapabilities: settings.injectExtraUILaunchCapabilities
614+
615+ /*!
616+ \qmlproperty bool UnityWebApps::requiresInit
617
618 */
619 property alias requiresInit: settings.requiresInit
620
621-
622 /*!
623 \qmlproperty UnityActions.Context UnityWebApps::actionsContext
624
625@@ -139,7 +141,6 @@
626 */
627 property var actionsContext: null
628
629-
630 /*!
631 \qmlproperty string UnityWebApps::_opt_backendProxies
632
633@@ -152,6 +153,7 @@
634
635 Settings {
636 id: settings
637+ injectExtraUILaunchCapabilities: name && name.length && name.length !== 0
638 }
639
640 /*
641@@ -208,7 +210,7 @@
642
643 var instance = new UnityWebAppsJs.UnityWebApps(webapps,
644 bindeeProxies,
645- webappUserscripts);
646+ __getPolicyForContent(settings));
647 internal.instance = instance;
648
649 if (internal.backends)
650@@ -413,6 +415,33 @@
651 return null;
652 }
653
654+ /*!
655+ \internal
656+
657+ */
658+ function __getPolicyForContent(settings) {
659+ function PassthroughPolicy() {};
660+ PassthroughPolicy.prototype.allowed = function(signature) {
661+ return true;
662+ };
663+
664+ var BASIC_WEBAPPS_ALLOWED_APIS = ["init"];
665+ function RestrictedPolicy(restrictions) {
666+ this.restrictions = restrictions || BASIC_WEBAPPS_ALLOWED_APIS;
667+ };
668+ RestrictedPolicy.prototype.allowed = function(signature) {
669+ return this.restrictions.some(function(e) { return e === signature; });
670+ };
671+
672+ if (settings.injectExtraUbuntuApis)
673+ return new PassthroughPolicy();
674+
675+// if (settings.injectExtraUILaunchCapabilities)
676+// return new RestrictedPolicy(["launchEmbeddedUI", "ContentHub.onShareRequested"]);
677+
678+ // Inject only the basic init + api
679+ return new PassthroughPolicy()
680+ }
681
682 /*!
683 \internal
684@@ -524,6 +553,53 @@
685 UnityBackends.get("hud").clearActions();
686 },
687
688+ launchEmbeddedUI: function(name, callback, params) {
689+ if (!model || !webapps || !webapps.name) {
690+ console.error("launchEmbeddedUI: could not find a valid webapp model or webapp name");
691+ return;
692+ }
693+
694+ var path = model.path(webapps.name);
695+ if (!path || path.length === 0) {
696+ console.error("launchEmbeddedUI: Invalid or empty webapp path name");
697+ return;
698+ }
699+
700+ var backendDelegate = UnityBackends.backendDelegate;
701+
702+ var parentItem = backendDelegate.parentView();
703+ if (!parentItem || !parentItem.visible || !parentItem.height || !parentItem.width) {
704+ console.error("launchEmbeddedUI: Cannot launch the embedded UI, invalid or malformed parent item: " + parentItem);
705+ callback({result: "cancelled"});
706+ return;
707+ }
708+
709+ var p = parentItem.parent ? parentItem.parent : parentItem
710+
711+ var uicomponent;
712+ function onCreated() {
713+ var uiobject = uicomponent.createObject(p, {"fileToShare": params.fileToShare.url, "visible": true});
714+ if ( ! uiobject.onCompleted) {
715+ console.error("launchEmbeddedUI: The local UI component to be launched does not expose a mandatory 'completed' signal");
716+ uiobject.destroy();
717+ return;
718+ }
719+ function _onCompleted(data) {
720+ p.visible = true;
721+ uiobject.onCompleted.disconnect(_onCompleted);
722+ uiobject.destroy();
723+ callback(data);
724+ }
725+ uiobject.onCompleted.connect(_onCompleted);
726+ };
727+
728+ var uicomponent = Qt.createComponent(path + "/" + name + ".qml");
729+ if (uicomponent.status === Component.Ready)
730+ onCreated()
731+ else
732+ uicomponent.statusChanged.connect(onCreated)
733+ },
734+
735 Notification: {
736 showNotification: function (summary, body, iconUrl) {
737 if (!initialized)
738@@ -641,17 +717,13 @@
739 }
740 },
741
742- OnlineAccounts: __injectResourceIfExtraApisAreEnabled(function() {
743- return OnlineAccountsApiBackend.createOnlineAccountsApi(UnityBackends.backendDelegate)
744- }),
745+ OnlineAccounts: OnlineAccountsApiBackend.createOnlineAccountsApi(UnityBackends.backendDelegate),
746
747 Alarm: __injectResourceIfExtraApisAreEnabled(function() {
748 return AlarmApiBackend.createAlarmApi(UnityBackends.backendDelegate)
749 }),
750
751- ContentHub: __injectResourceIfExtraApisAreEnabled(function() {
752- return ContentHubApiBackend.createContentHubApi(UnityBackends.backendDelegate)
753- }),
754+ ContentHub: ContentHubApiBackend.createContentHubApi(UnityBackends.backendDelegate),
755
756 RuntimeApi: __injectResourceIfExtraApisAreEnabled(function() {
757 return RuntimeApiBackend.createRuntimeApi(UnityBackends.backendDelegate)
758
759=== modified file 'src/Ubuntu/UnityWebApps/UnityWebAppsUtils.js'
760--- src/Ubuntu/UnityWebApps/UnityWebAppsUtils.js 2014-06-13 15:04:58 +0000
761+++ src/Ubuntu/UnityWebApps/UnityWebAppsUtils.js 2014-06-26 01:46:50 +0000
762@@ -62,10 +62,14 @@
763 this.webview = webview;
764 this.disposer = disposer;
765 this.makeSignalDisconnecter = makeSignalDisconnecter;
766+ this._userScriptInjected = false;
767 this._WEBAPPS_USER_SCRIPT_CONTEXT = "oxide://UnityWebappsApi";
768 }
769 OxideWebviewAdapter.prototype = {
770 injectUserScripts: function(userScriptUrls) {
771+ if (this._userScriptInjected)
772+ return;
773+
774 var context = this.webview.context;
775
776 for (var i = 0; i < userScriptUrls.length; ++i) {
777@@ -76,6 +80,7 @@
778 '; matchAllFrames: false; url: "' + userScriptUrls[i] + '";' + scriptEnd;
779 context.addUserScript(Qt.createQmlObject(statement, this.webview));
780 }
781+ this._userScriptInjected = true;
782 },
783 sendToPage: function (message) {
784 this.webview.rootFrame.sendMessageNoReply(
785
786=== modified file 'src/Ubuntu/UnityWebApps/bindings/content-hub/backend/content-hub.js'
787--- src/Ubuntu/UnityWebApps/bindings/content-hub/backend/content-hub.js 2014-05-08 13:01:07 +0000
788+++ src/Ubuntu/UnityWebApps/bindings/content-hub/backend/content-hub.js 2014-06-26 01:46:50 +0000
789@@ -24,7 +24,7 @@
790 *
791 */
792
793-function createContentHubApi(backendDelegate) {
794+function createContentHubApi(backendDelegate, accessPolicy) {
795 var PLUGIN_URI = 'Ubuntu.Content';
796 var VERSION = 0.1;
797
798@@ -39,6 +39,8 @@
799 "Documents": ContentHubBridge.ContentType.Documents,
800 "Music": ContentHubBridge.ContentType.Music,
801 "Contacts": ContentHubBridge.ContentType.Contacts,
802+ "Videos": ContentHubBridge.ContentType.Videos,
803+ "Links": ContentHubBridge.ContentType.Links,
804 };
805 return name in contentTypePerName ?
806 contentTypePerName[name]
807@@ -57,6 +59,10 @@
808 return "Music";
809 else if (state === ContentHubBridge.ContentType.Contacts)
810 return "Contacts";
811+ else if (state === ContentHubBridge.ContentType.Videos)
812+ return "Videos";
813+ else if (state === ContentHubBridge.ContentType.Links)
814+ return "Links";
815 return "Unknown";
816 };
817
818@@ -146,6 +152,8 @@
819 "Collected": ContentHubBridge.ContentTransfer.Collected,
820 "Aborted": ContentHubBridge.ContentTransfer.Aborted,
821 "Finalized": ContentHubBridge.ContentTransfer.Finalized,
822+ "Downloading": ContentHubBridge.ContentTransfer.Downloading,
823+ "Downloaded": ContentHubBridge.ContentTransfer.Downloaded,
824 };
825 return name in contentTransferStatePerName ?
826 contentTransferStatePerName[name]
827@@ -166,6 +174,10 @@
828 return "Aborted";
829 else if (state === ContentHubBridge.ContentTransfer.Finalized)
830 return "Finalized";
831+ else if (state === ContentHubBridge.ContentTransfer.Downloading)
832+ return "Downloading";
833+ else if (state === ContentHubBridge.ContentTransfer.Downloaded)
834+ return "Downloaded";
835 return "<Unknown State>";
836 };
837
838@@ -769,6 +781,20 @@
839 });
840 },
841
842+ onImportRequested: function(callback) {
843+ _contenthub.onImportRequested.connect(function(importTransfer) {
844+ var wrapped = new ContentTransfer(importTransfer);
845+ callback(wrapped.serialize());
846+ });
847+ },
848+
849+ onShareRequested: function(callback) {
850+ _contenthub.shareRequested.connect(function(shareTransfer) {
851+ var wrapped = new ContentTransfer(shareTransfer);
852+ callback(wrapped.serialize());
853+ });
854+ },
855+
856 // Internal
857
858 dispatchToObject: function(infos) {
859
860=== modified file 'src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js'
861--- src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js 2014-03-18 13:59:36 +0000
862+++ src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js 2014-06-26 01:46:50 +0000
863@@ -230,7 +230,7 @@
864 /**
865 * ContentPeer is an object returned by the ContentHub.
866 It represents a remote peer that can be used in a request
867- to export or import date.
868+ to import, export or share content.
869
870 * @class ContentPeer
871 * @module ContentHub
872@@ -421,7 +421,7 @@
873 // methods
874
875 /**
876- * Request to import data from this ContentPeer.
877+ * Request to exchange content with this ContentPeer.
878 *
879 * @method request
880 * @param callback {Function(ContentTransfer)} Called with the resulting content transfer
881@@ -431,7 +431,7 @@
882 },
883
884 /**
885- * Request to import data from this ContentPeer and use a ContentStore for permanent storage.
886+ * Request to import content from this ContentPeer and use a ContentStore for permanent storage.
887 *
888 * @method requestForStore
889 * @param store {ContentStore} Store used as a permanent storage
890@@ -586,6 +586,10 @@
891
892 Contacts
893
894+ Videos
895+
896+ Links
897+
898 @static
899 @property ContentType {String}
900
901@@ -603,6 +607,8 @@
902 Documents: "Documents",
903 Music: "Music",
904 Contacts: "Contacts",
905+ Videos: "Videos",
906+ Links: "Links",
907 },
908
909 /**
910@@ -665,6 +671,10 @@
911 Aborted: Transfer has been aborted.
912
913 Finalized: Transfer has been finished and cleaned up.
914+
915+ Downloaded: Download specified by downloadId has completed.
916+
917+ Downloading: Transfer is downloading item specified by downloadId.
918
919 @static
920 @property ContentTransfer.State {String}
921@@ -715,6 +725,12 @@
922
923 // Transfer has been finished and cleaned up.
924 Finalized: "Finalized",
925+
926+ // Transfer has finished downloading.
927+ Downloaded: "Downloaded",
928+
929+ // Transfer is downloading.
930+ Downloading: "Downloading",
931 },
932
933 /**
934@@ -726,6 +742,8 @@
935
936 Export
937
938+ Share
939+
940 @static
941 @property ContentTransfer.Direction {String}
942 */
943@@ -735,6 +753,9 @@
944
945 // Transfer is a request to export content
946 Export: "Export",
947+
948+ // Transfer is a request to share content
949+ Share: "Share",
950 },
951
952 /**
953@@ -836,6 +857,58 @@
954 [callback]);
955 },
956
957+ /**
958+ * Sets a handler that is to be called when the current application is the
959+ * target of an share request.
960+ *
961+ * @method onShareRequested
962+ * @param callback {Function(ContentTransfer)} Function when one requests a resource to be shared.
963+ * The corresponding ContentTransfer is provided as a parameter.
964+ *
965+ * @example
966+
967+ var api = external.getUnityObject(1.0);
968+ var hub = api.ContentHub;
969+
970+ var transferState = hub.ContentTransfer.State;
971+
972+ function _shareRequested(transfer) {
973+ };
974+
975+ hub.onShareRequested(_shareRequested);
976+
977+ */
978+ onShareRequested: function(callback) {
979+ backendBridge.call('ContentHub.onShareRequested',
980+ [callback]);
981+ },
982+
983+ /**
984+ * Sets a handler that is to be called when the current application is the
985+ * target of an import request.
986+ *
987+ * @method onImportRequested
988+ * @param callback {Function(ContentTransfer)} Function when one requests a resource to be imported.
989+ * The corresponding ContentTransfer is provided as a parameter.
990+ *
991+ * @example
992+
993+ var api = external.getUnityObject(1.0);
994+ var hub = api.ContentHub;
995+
996+ var transferState = hub.ContentTransfer.State;
997+
998+ function _importRequested(transfer) {
999+ };
1000+
1001+ hub.onImportRequested(_importRequested);
1002+
1003+ */
1004+ onImportRequested: function(callback) {
1005+ backendBridge.call('ContentHub.onImportRequested',
1006+ [callback]);
1007+ },
1008+
1009 api: {
1010
1011 /**
1012@@ -843,7 +916,7 @@
1013 *
1014 * @method api.importContent
1015 * @param type {ContentType} type of the content to import
1016- * @param peer {ContentPeer} peer whos content should be imported
1017+ * @param peer {ContentPeer} peer who's content should be imported
1018 * @param transferOptions {Object} a dictionary of transfer options. The options are the following:
1019 * - multipleFiles {Bool}: specified if a transfer should involve multiple files or not
1020 * - scope {ContentScope}: specifies the location where the transferred files should be copied to
1021
1022=== modified file 'src/Ubuntu/UnityWebApps/bindings/online-accounts/backend/online-accounts.js'
1023--- src/Ubuntu/UnityWebApps/bindings/online-accounts/backend/online-accounts.js 2014-05-09 13:17:09 +0000
1024+++ src/Ubuntu/UnityWebApps/bindings/online-accounts/backend/online-accounts.js 2014-06-26 01:46:50 +0000
1025@@ -21,7 +21,7 @@
1026 * Online Accounts API backend binding
1027 *
1028 */
1029-function createOnlineAccountsApi(backendDelegate) {
1030+function createOnlineAccountsApi(backendDelegate, accessPolicy) {
1031 var PLUGIN_URI = 'Ubuntu.OnlineAccounts';
1032 var VERSION = 0.1;
1033
1034
1035=== modified file 'src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.cpp'
1036--- src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.cpp 2014-05-14 01:41:14 +0000
1037+++ src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.cpp 2014-06-26 01:46:50 +0000
1038@@ -156,6 +156,7 @@
1039 roles[Scripts] = "scripts";
1040 roles[Chrome] = "chrome";
1041 roles[UserAgentOverride] = "useragent";
1042+ roles[Path] = "path";
1043 }
1044 return roles;
1045 }
1046@@ -337,6 +338,21 @@
1047 }
1048
1049 QString
1050+UnityWebappsAppModel::path(const QString & webappName) const {
1051+ if (!exists(webappName))
1052+ return QString();
1053+
1054+ int idx = getWebappIndex(webappName);
1055+ if (Q_UNLIKELY(idx == -1))
1056+ {
1057+ qDebug() << "Invalid index for a supposedly existing webapp: " << webappName;
1058+ return QString();
1059+ }
1060+
1061+ return data(idx, Path).toString();
1062+}
1063+
1064+QString
1065 UnityWebappsAppModel::userAgentOverrideFor(const QString & webappName) const
1066 {
1067 if (!exists(webappName))
1068@@ -543,6 +559,9 @@
1069
1070 case UserAgentOverride:
1071 return webapp.data.manifest.userAgentOverride;
1072+
1073+ case Path:
1074+ return webapp.userscriptLocation;
1075 }
1076
1077 return QVariant();
1078
1079=== modified file 'src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.h'
1080--- src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.h 2014-05-08 15:20:47 +0000
1081+++ src/Ubuntu/UnityWebApps/plugin/unity-webapps-app-model.h 2014-06-26 01:46:50 +0000
1082@@ -58,7 +58,8 @@
1083 Scripts,
1084 ScriptsContent,
1085 Chrome,
1086- UserAgentOverride
1087+ UserAgentOverride,
1088+ Path
1089 };
1090
1091 // QAbstractListModel implementation
1092@@ -108,6 +109,11 @@
1093 */
1094 Q_INVOKABLE QString userAgentOverrideFor(const QString & webappName) const;
1095
1096+ /*!
1097+ * \brief
1098+ */
1099+ Q_INVOKABLE QString path(const QString & webappName) const;
1100+
1101
1102 /*!
1103 * \brief
1104
1105=== modified file 'src/Ubuntu/UnityWebApps/unity-webapps-api.js.in'
1106--- src/Ubuntu/UnityWebApps/unity-webapps-api.js.in 2014-05-13 17:48:43 +0000
1107+++ src/Ubuntu/UnityWebApps/unity-webapps-api.js.in 2014-06-26 01:46:50 +0000
1108@@ -98,6 +98,12 @@
1109 clearActions: createArgumentsSanitizer (backend, [], 'clearActions'),
1110
1111 /**
1112+ */
1113+ launchEmbeddedUI: function(name, callback, params) {
1114+ backend.call('launchEmbeddedUI', [name, callback, params]);
1115+ },
1116+
1117+ /**
1118 *
1119 * MediaPlayer API
1120 *

Subscribers

People subscribed via source and target branches

to all changes: