Merge lp:~abreu-alexandre/unity-webapps-qml/application-api into lp:unity-webapps-qml

Proposed by Alexandre Abreu
Status: Merged
Merged at revision: 102
Proposed branch: lp:~abreu-alexandre/unity-webapps-qml/application-api
Merge into: lp:unity-webapps-qml
Diff against target: 1421 lines (+1185/-9)
20 files modified
examples/api-bindings/alarm/www/index.html (+4/-0)
examples/api-bindings/content-hub-exporter/www/index.html (+4/-0)
examples/api-bindings/content-hub/www/index.html (+4/-0)
examples/api-bindings/online-accounts/www/index.html (+4/-0)
examples/api-bindings/runtime-api/main.qml.in (+32/-0)
examples/api-bindings/runtime-api/www/index.html (+22/-0)
examples/api-bindings/runtime-api/www/js/app.js (+57/-0)
src/Ubuntu/UnityWebApps/UnityWebApps.pro (+22/-7)
src/Ubuntu/UnityWebApps/UnityWebApps.qml (+3/-0)
src/Ubuntu/UnityWebApps/bindings/runtime-api/backend/runtime-api.js (+171/-0)
src/Ubuntu/UnityWebApps/bindings/runtime-api/client/runtime-api.js (+256/-0)
src/Ubuntu/UnityWebApps/plugin/application-api.cpp (+287/-0)
src/Ubuntu/UnityWebApps/plugin/application-api.h (+75/-0)
src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.cpp (+139/-0)
src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.h (+62/-0)
src/Ubuntu/UnityWebApps/plugin/plugin.pro (+6/-2)
src/Ubuntu/UnityWebApps/plugin/qml-plugin.cpp (+15/-0)
src/Ubuntu/UnityWebApps/unity-webapps-api.js.in (+2/-0)
tests/unit/test_plugin/tst_plugin.cpp (+19/-0)
tests/unit/test_plugin/tst_plugin.h (+1/-0)
To merge this branch: bzr merge lp:~abreu-alexandre/unity-webapps-qml/application-api
Reviewer Review Type Date Requested Status
Alberto Mardegan (community) Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+212727@code.launchpad.net

Commit message

Add application api

Description of the change

Add application api

To post a comment you must log in.
Revision history for this message
Alberto Mardegan (mardy) wrote :

I tested it and it's mostly working. A few comments:

getPlatformInfos: I think it's better to call it "getPlatformInfo" without the final "s". Anyway, this just returns the name of the QPA plugin, so I'd rather rename the method to "getPlatformName" or keep the current name and make it return a dictionary, currently having only one field "name" which contains the platform name. But I'd take the second approach only if you really plan to add more info there in the future.

The example expects the onActivated() and onDeactivated() signal to carry a parameter, but they don't.

All the methods are asynchronous and take a callback; even the applicationName() function is asynchronous, even if the result is immediately available. I'm not familiar with HTML5 development so this might be perfectly fine, I just point this out because coming from the C++ world this sounds rather strange (and a bit inconvenient).

Naming: it's better to use the same convention for all the getters: either start their name always with a "get", or never. Most of the methods you added start with "get", but "applicationName" doesn't.

getInputMethod(): it's not very clear what this function does; maybe rename it to "getInputMethodName"?

nameFromScreenOrientation(): you are only use two possible values, "Landscape" and "Portrait", while Qt supports 4. I guess that most apps don't care about distinguishing between the extra modes, but maybe some do (to be sure that the mic is on a specific side, for instance)?

Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

> I tested it and it's mostly working. A few comments:
>
> getPlatformInfos: I think it's better to call it "getPlatformInfo" without the
> final "s". Anyway, this just returns the name of the QPA plugin, so I'd rather
> rename the method to "getPlatformName" or keep the current name and make it
> return a dictionary, currently having only one field "name" which contains the
> platform name. But I'd take the second approach only if you really plan to add
> more info there in the future.

done,

> The example expects the onActivated() and onDeactivated() signal to carry a
> parameter, but they don't.

done,

> All the methods are asynchronous and take a callback; even the
> applicationName() function is asynchronous, even if the result is immediately
> available. I'm not familiar with HTML5 development so this might be perfectly
> fine, I just point this out because coming from the C++ world this sounds
> rather strange (and a bit inconvenient).

right, agree, took another approach,

> Naming: it's better to use the same convention for all the getters: either
> start their name always with a "get", or never. Most of the methods you added
> start with "get", but "applicationName" doesn't.

done,

> getInputMethod(): it's not very clear what this function does; maybe rename it
> to "getInputMethodName"?

done,

> nameFromScreenOrientation(): you are only use two possible values, "Landscape"
> and "Portrait", while Qt supports 4. I guess that most apps don't care about
> distinguishing between the extra modes, but maybe some do (to be sure that the
> mic is on a specific side, for instance)?

right, agree, done

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
102. By Alexandre Abreu

merge trunk

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

I think there's a problem with how the getters are implemented. Let's take getScreenOrientation() for example: when the client calls this method, it will retrieve the application name which was setup, which is correct. If the application registers a callback with onScreenOrientationChanged(), then this._screenOrientation will always get updated propertly, so getScreenOrientation() will always return the proper value; however, if the application doesn't call onScreenOrientationChanged(), this._screenOrientation will never be updated and getScreenOrientation() will always return the old value.

I'm not sure how expensive the switch betwenn client and backend is, so depending on that:

1) If the switch is not very expensive: don't cache any values in the client, always request the properties directly from the backend.

2) If the switch is very expensive, do as you are doing, but register an internal callback to the cached properties in the Application constructor. Something like:

  var self = this;
  this._name = content.name;
  this._proxy.call('onApplicationNameChanged', [function(name) {self._name = name; }]);

(In the latter case we might even want to avoid passing through the backend when the client calls onApplicationNameChanged(): we could make it store the function callback into an array (this._applicationNameListeners) and in the callback registered in the Application constructor we could then invoke all the callbacks in this._applicationNameListeners, after having updated "self._name = name")

Can you also make the getInputMethodName return the value immediately?

Other than that, it all looks good to me!

review: Needs Fixing
Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

> I think there's a problem with how the getters are implemented. Let's take
> getScreenOrientation() for example: when the client calls this method, it will
> retrieve the application name which was setup, which is correct. If the
> application registers a callback with onScreenOrientationChanged(), then
> this._screenOrientation will always get updated propertly, so
> getScreenOrientation() will always return the proper value; however, if the
> application doesn't call onScreenOrientationChanged(), this._screenOrientation
> will never be updated and getScreenOrientation() will always return the old
> value.
>
> I'm not sure how expensive the switch betwenn client and backend is, so
> depending on that:
>
> 1) If the switch is not very expensive: don't cache any values in the client,
> always request the properties directly from the backend.
>
> 2) If the switch is very expensive, do as you are doing, but register an
> internal callback to the cached properties in the Application constructor.
> Something like:
>
> var self = this;
> this._name = content.name;
> this._proxy.call('onApplicationNameChanged', [function(name) {self._name =
> name; }]);
>
> (In the latter case we might even want to avoid passing through the backend
> when the client calls onApplicationNameChanged(): we could make it store the
> function callback into an array (this._applicationNameListeners) and in the
> callback registered in the Application constructor we could then invoke all
> the callbacks in this._applicationNameListeners, after having updated
> "self._name = name")
>
>
> Can you also make the getInputMethodName return the value immediately?

all done

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'examples/api-bindings/alarm/www/index.html'
--- examples/api-bindings/alarm/www/index.html 2014-01-22 20:38:52 +0000
+++ examples/api-bindings/alarm/www/index.html 2014-03-26 15:53:02 +0000
@@ -1,5 +1,9 @@
1<!DOCTYPE html>
1<html>2<html>
23
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
3 <head>7 <head>
4 <title>Content Hub example</title>8 <title>Content Hub example</title>
5 <script src="./js/app.js"></script>9 <script src="./js/app.js"></script>
610
=== modified file 'examples/api-bindings/content-hub-exporter/www/index.html'
--- examples/api-bindings/content-hub-exporter/www/index.html 2014-01-31 01:44:10 +0000
+++ examples/api-bindings/content-hub-exporter/www/index.html 2014-03-26 15:53:02 +0000
@@ -1,5 +1,9 @@
1<!DOCTYPE html>
1<html>2<html>
23
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
3 <head>7 <head>
4 <title>Content Hub Exporter example</title>8 <title>Content Hub Exporter example</title>
5 <script src="./js/app.js"></script>9 <script src="./js/app.js"></script>
610
=== modified file 'examples/api-bindings/content-hub/www/index.html'
--- examples/api-bindings/content-hub/www/index.html 2014-02-08 14:48:32 +0000
+++ examples/api-bindings/content-hub/www/index.html 2014-03-26 15:53:02 +0000
@@ -1,5 +1,9 @@
1<!DOCTYPE html>
1<html>2<html>
23
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
3 <head>7 <head>
4 <title>Content Hub example</title>8 <title>Content Hub example</title>
5 <script src="./js/app.js"></script>9 <script src="./js/app.js"></script>
610
=== modified file 'examples/api-bindings/online-accounts/www/index.html'
--- examples/api-bindings/online-accounts/www/index.html 2014-02-26 13:21:37 +0000
+++ examples/api-bindings/online-accounts/www/index.html 2014-03-26 15:53:02 +0000
@@ -1,5 +1,9 @@
1<!DOCTYPE html>
1<html>2<html>
23
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
3 <head>7 <head>
4 <title>Content Hub example</title>8 <title>Content Hub example</title>
5 <script src="./js/app.js"></script>9 <script src="./js/app.js"></script>
610
=== added directory 'examples/api-bindings/runtime-api'
=== added file 'examples/api-bindings/runtime-api/main.qml.in'
--- examples/api-bindings/runtime-api/main.qml.in 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/runtime-api/main.qml.in 2014-03-26 15:53:02 +0000
@@ -0,0 +1,32 @@
1import QtQuick 2.0
2import QtWebKit 3.0
3import QtWebKit.experimental 1.0
4import Ubuntu.Components 0.1
5import Ubuntu.UnityWebApps 0.1
6
7MainView {
8 id: root
9 focus: true
10 applicationName: \"runtime-api\"
11
12 width: units.gu(100)
13 height: units.gu(100)
14
15 WebView {
16 id: webview
17 anchors.fill: parent
18 url: \"file://$$OUT_PWD/runtime-api/www/index.html\"
19
20 experimental.preferences.navigatorQtObjectEnabled: true
21 experimental.preferences.developerExtrasEnabled: true
22
23 function getUnityWebappsProxies() {
24 return UnityWebAppsUtils.makeProxiesForQtWebViewBindee(webview);
25 }
26
27 UnityWebApps {
28 id: webapps
29 bindee: webview
30 }
31 }
32}
033
=== added directory 'examples/api-bindings/runtime-api/www'
=== added file 'examples/api-bindings/runtime-api/www/index.html'
--- examples/api-bindings/runtime-api/www/index.html 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/runtime-api/www/index.html 2014-03-26 15:53:02 +0000
@@ -0,0 +1,22 @@
1<!DOCTYPE html>
2<html>
3
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
7 <head>
8 <title>Runtime Api example</title>
9 <script src="./js/app.js"></script>
10 </head>
11
12 <body>
13
14 <div>
15 Results:
16 <div id="results">
17 </div>
18 </div>
19
20 </body>
21
22</html>
023
=== added directory 'examples/api-bindings/runtime-api/www/js'
=== added file 'examples/api-bindings/runtime-api/www/js/app.js'
--- examples/api-bindings/runtime-api/www/js/app.js 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/runtime-api/www/js/app.js 2014-03-26 15:53:02 +0000
@@ -0,0 +1,57 @@
1window.onload = function() {
2 function setResult(message) {
3 var results = document.getElementById('results');
4 results.innerHTML += message + '<br>';
5 }
6
7 var last = 0;
8 if (localStorage.getItem("lastkilled") !== null)
9 last = localStorage.getItem("lastkilled");
10
11 setResult('last killed: ' + last);
12
13 var api = external.getUnityObject('1.0');
14
15 api.RuntimeApi.getApplication(function(application) {
16 setResult('application name: ' + application.getApplicationName());
17 setResult('application info: ' + JSON.stringify(application.getPlatformInfo()));
18
19 application.getInputMethodName(function(name) {
20 if (name.length == 0)
21 setResult('input method: no OSK available');
22 else
23 setResult('input method: ' + name);
24 });
25
26 setResult('screen orientation: ' + application.getScreenOrientation());
27
28 application.onScreenOrientationChanged(function(name) {
29 setResult('Event: orientation changed - ' + name);
30 });
31
32 application.onAboutToQuit(function(killed) {
33 localStorage.setItem("lastkilled", last + 1);
34
35 console.log('killed: ' + killed)
36
37 setResult('onAboutToQuit: ' + killed);
38 });
39
40 application.onDeactivated(function() {
41 setResult('Event: application deactivated');
42 });
43
44 application.onActivated(function() {
45 setResult('Event: application activated');
46 });
47
48 application.onInputMethodVisibilityChanged(function(visibility) {
49 setResult('Event: onInputMethodVisibilityChanged - ' + visibility);
50 });
51
52 application.setupUriHandler(function(uris) {
53 setResult('Event: received URI to open w/ UriHandler - ' + JSON.stringify(uris));
54 });
55
56 });
57};
058
=== modified file 'src/Ubuntu/UnityWebApps/UnityWebApps.pro'
--- src/Ubuntu/UnityWebApps/UnityWebApps.pro 2014-01-17 15:51:27 +0000
+++ src/Ubuntu/UnityWebApps/UnityWebApps.pro 2014-03-26 15:53:02 +0000
@@ -21,10 +21,13 @@
21#21#
22# deployment directives22# deployment directives
23#23#
24JS_FILES = $$system(ls *.js) \24PLUGIN_JS_FILES = \
25 $${UNITY_API_JS_FILE} \25 $$system(ls *.js) \
26 $${UNITY_API_JS_FILE}
27
28CLIENT_JS_FILES = \
26 $$system(ls ./common/*/*.js) \29 $$system(ls ./common/*/*.js) \
27 $$system(ls ./bindings/*/*/*.js)30 $$system(ls ./bindings/*/client/*.js)
2831
29QML_FILES = $$system(ls *.qml)32QML_FILES = $$system(ls *.qml)
3033
@@ -32,7 +35,9 @@
32QMAKE_SUBSTITUTES += qmldir.in35QMAKE_SUBSTITUTES += qmldir.in
3336
34OTHER_FILES += $$QML_FILES \37OTHER_FILES += $$QML_FILES \
35 $$JS_FILES \38 $$PLUGIN_JS_FILES \
39 $$CLIENT_JS_FILES \
40 $$system(ls ./bindings/*/backend/*.js) \
36 qmldir.in \41 qmldir.in \
37 unity-webapps-api.js.in \42 unity-webapps-api.js.in \
38 $${UNITY_API_JS_FILE}43 $${UNITY_API_JS_FILE}
@@ -44,9 +49,19 @@
4449
45qmldir_file.path = $$installPath50qmldir_file.path = $$installPath
46qmldir_file.files = $$QMLDIR_FILE51qmldir_file.files = $$QMLDIR_FILE
52
47qml_files.path = $$installPath53qml_files.path = $$installPath
48qml_files.files = $$QML_FILES54qml_files.files = $$QML_FILES
55
49js_files.path = $$installPath56js_files.path = $$installPath
50js_files.files = $$JS_FILES57js_files.files = $$PLUGIN_JS_FILES
5158
52INSTALLS += qmldir_file qml_files js_files59runtime_api_binding_backend_js_files.path = $$installPath/bindings/runtime-api/backend/
60runtime_api_binding_backend_js_files.files = ./bindings/runtime-api/backend/runtime-api.js
61
62INSTALLS += qmldir_file \
63 qml_files \
64 js_files \
65 runtime_api_binding_backend_js_files \
66
67
5368
=== modified file 'src/Ubuntu/UnityWebApps/UnityWebApps.qml'
--- src/Ubuntu/UnityWebApps/UnityWebApps.qml 2014-03-17 17:25:53 +0000
+++ src/Ubuntu/UnityWebApps/UnityWebApps.qml 2014-03-26 15:53:02 +0000
@@ -21,6 +21,7 @@
21import "UnityWebApps.js" as UnityWebAppsJs21import "UnityWebApps.js" as UnityWebAppsJs
22import "UnityWebAppsUtils.js" as UnityWebAppsJsUtils22import "UnityWebAppsUtils.js" as UnityWebAppsJsUtils
23import "UnityWebAppsBackendComponents.js" as UnityBackends23import "UnityWebAppsBackendComponents.js" as UnityBackends
24import "./bindings/runtime-api/backend/runtime-api.js" as RuntimeApiBackend
2425
2526
26/*!27/*!
@@ -649,6 +650,8 @@
649 return UnityBackends.createContentHubApi(UnityBackends.backendDelegate)650 return UnityBackends.createContentHubApi(UnityBackends.backendDelegate)
650 }),651 }),
651652
653 RuntimeApi: RuntimeApiBackend.createRuntimeApi(UnityBackends.backendDelegate),
654
652 Launcher: {655 Launcher: {
653 setCount: function (count) {656 setCount: function (count) {
654 if (!initialized)657 if (!initialized)
655658
=== added directory 'src/Ubuntu/UnityWebApps/bindings/runtime-api'
=== added directory 'src/Ubuntu/UnityWebApps/bindings/runtime-api/backend'
=== added file 'src/Ubuntu/UnityWebApps/bindings/runtime-api/backend/runtime-api.js'
--- src/Ubuntu/UnityWebApps/bindings/runtime-api/backend/runtime-api.js 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/bindings/runtime-api/backend/runtime-api.js 2014-03-26 15:53:02 +0000
@@ -0,0 +1,171 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19.import Ubuntu.UnityWebApps 0.1 as UnityWebAppsBridge
20.import Ubuntu.Components 0.1 as ComponentsBridge
21
22
23/**
24 *
25 * Runtime API backend binding
26 *
27 */
28function createRuntimeApi(backendDelegate) {
29 var PLUGIN_URI = 'Ubuntu.UnityWebApps';
30 var VERSION = 0.1;
31
32 var applicationApiInstance = UnityWebAppsBridge.ApplicationApi;
33
34 function Application() {
35 // no need to have a specific id since this class is mostly a passtrough one
36 this._id = 0;
37 };
38 Application.prototype = {
39
40 // object methods
41 serialize: function() {
42 var self = this;
43 return {
44 type: 'object-proxy',
45 apiid: 'RuntimeApi',
46 objecttype: 'Application',
47 objectid: this._id,
48
49 content: {
50 name: applicationApiInstance.applicationName,
51 platform: applicationApiInstance.applicationPlatform,
52 writableLocation: applicationApiInstance.applicationDataPath,
53 screenOrientation: applicationApiInstance.screenOrientation,
54 }
55 }
56 },
57
58 getApplicationName: function(callback) {
59 if (callback && typeof(callback) === 'function')
60 callback(applicationApiInstance.applicationName);
61 },
62 onApplicationNameChanged: function(callback) {
63 if (callback && typeof(callback) === 'function')
64 applicationApiInstance.applicationNameChanged.connect(function() {
65 callback(applicationApiInstance.applicationName);
66 });
67 },
68
69 getApplicationWritableLocation: function(callback) {
70 if (callback && typeof(callback) === 'function')
71 callback(applicationApiInstance.applicationDataPath);
72 },
73
74 getPlatformInfo: function(callback) {
75 if (callback && typeof(callback) === 'function') {
76 var info = {};
77 info.name = applicationApiInstance.applicationPlatform;
78 callback(info);
79 }
80 },
81
82 setInputMethodVisible: function(visible, callback) {
83 applicationApiInstance.setInputMethodVisible(visible);
84 if (callback && typeof(callback) === 'function')
85 callback();
86 },
87 getInputMethodName: function(callback) {
88 if (callback && typeof(callback) === 'function')
89 callback(applicationApiInstance.getInputMethodName());
90 },
91 onInputMethodVisibilityChanged: function(callback) {
92 if (callback && typeof(callback) === 'function')
93 Qt.inputMethod.onVisibleChanged.connect(function() {
94 callback(Qt.inputMethod.visible)
95 });
96 },
97
98 onAboutToQuit: function(callback) {
99 if (callback && typeof(callback) === 'function')
100 applicationApiInstance.applicationAboutToQuit.connect(function(killed) {
101 callback(killed);
102 });
103 },
104
105 setupUriHandler: function(callback) {
106 if (callback && typeof(callback) === 'function')
107 var urihandler = ComponentsBridge.UriHandler;
108 urihandler.opened.connect(function(uris, data) {
109 var translatedUris = []
110 for (var idx in uris) {
111 translatedUris.push(uris[idx])
112 }
113 callback(translatedUris);
114 });
115 },
116
117 onDeactivated: function(callback) {
118 if (callback && typeof(callback) === 'function')
119 applicationApiInstance.applicationDeactivated.connect(callback);
120 },
121
122 onActivated: function(callback) {
123 if (callback && typeof(callback) === 'function')
124 applicationApiInstance.applicationActivated.connect(callback);
125 },
126
127 getScreenOrientation: function(callback) {
128 if (callback && typeof(callback) === 'function')
129 callback(applicationApiInstance.screenOrientation);
130 },
131 onScreenOrientationChanged: function(callback) {
132 if (callback && typeof(callback) === 'function')
133 applicationApiInstance.applicationScreenOrientationChanged.connect(callback);
134 },
135 };
136
137 function _constructorFromName(className) {
138 var constructorPerName = {
139 "Application": Application,
140 };
141 return className in constructorPerName
142 ? constructorPerName[className]
143 : null;
144 }
145
146 return {
147 getApplication: function(callback) {
148 var application = new Application();
149 callback(application.serialize());
150 },
151
152 // Internal
153
154 dispatchToObject: function(infos) {
155 var args = infos.args;
156 var callback = infos.callback;
157 var method_name = infos.method_name;
158 var objectid = infos.objectid;
159 var class_name = infos.class_name;
160
161 if (callback)
162 args.push(callback);
163
164 var Constructor = _constructorFromName(class_name);
165
166 var instance = new Constructor(objectid);
167
168 instance[method_name].apply(instance, args);
169 }
170 };
171}
0172
=== added directory 'src/Ubuntu/UnityWebApps/bindings/runtime-api/client'
=== added file 'src/Ubuntu/UnityWebApps/bindings/runtime-api/client/runtime-api.js'
--- src/Ubuntu/UnityWebApps/bindings/runtime-api/client/runtime-api.js 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/bindings/runtime-api/client/runtime-api.js 2014-03-26 15:53:02 +0000
@@ -0,0 +1,256 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20/**
21 * RuntimeApi gives access to the application runtime information and management.
22
23 * @module RuntimeApi
24 */
25function createRuntimeApi(backendBridge) {
26 var PLUGIN_URI = 'RuntimeApi';
27
28 function Application(id, content) {
29 this._proxy = backendBridge.createRemoteObject(
30 PLUGIN_URI, 'Application', id);
31
32 this._name = content.name;
33 this._platform = content.platform;
34 this._writableLocation = content.writableLocation;
35 this._screenOrientation = content.screenOrientation;
36 };
37 Application.prototype = {
38
39 /**
40 * Retrieves the application name.
41 *
42 * @method getApplicationName
43 * @return {String} application name
44 */
45 getApplicationName: function() {
46 return this._name;
47 },
48
49 /**
50 * Sets up a callback that is to be called when the application's name changed.
51 *
52 * @method onApplicationNameChanged
53 * @param callback {Function(String)} Function to be called when the application's name has changed.
54 */
55 onApplicationNameChanged: function(callback) {
56 var self = this;
57 this._proxy.call('onApplicationNameChanged'
58 , [function(name) {self._name = name; callback(name); }]);
59 },
60
61 /**
62 * Retrieves the fileystem location where the application is allowed to write its data in.
63 *
64 * @method getApplicationWritableLocation
65 * @return {String} application writable location path
66 */
67 getApplicationWritableLocation: function() {
68 return this._writableLocation;
69 },
70
71 /**
72 * Retrieves current platform information.
73 *
74 * @method getPlatformInfos
75 * @return {Object} platform information as a dictionary with the following keys:
76 * - name: the platform name
77 */
78 getPlatformInfo: function() {
79 return this._platform;
80 },
81
82 /**
83 * Sets up a callback that is to be called when the application is about to quit.
84 *
85 * @method onAboutToQuit
86 * @param callback {Function()} Function to be called when the application is about to quit.
87 */
88 onAboutToQuit: function(callback) {
89 this._proxy.call('onAboutToQuit'
90 , [callback]);
91 },
92
93 /**
94 * Sets up a callback that is to be called when the application has been deactivated (background).
95 *
96 * @method onDeactivated
97 * @param callback {Function()} Function to be called when the application has been deactivated.
98 */
99 onDeactivated: function(callback) {
100 this._proxy.call('onDeactivated'
101 , [callback]);
102 },
103
104 /**
105 * Sets up a callback that is to be called when the application has been activated (from background).
106 *
107 * @method onActivated
108 * @param callback {Function()} Function to be called when the application has been activated.
109 */
110 onActivated: function(callback) {
111 this._proxy.call('onActivated'
112 , [callback]);
113 },
114
115 /**
116 * Retrieves the current screen orientation.
117 *
118 * @method getScreenOrientation
119 * @return {ScreenOrientation} current screen orientation.
120 */
121 getScreenOrientation: function() {
122 return this._screenOrientation;
123 },
124
125 /**
126 * Sets up a callback that is to be called when the application's screen has changed its orientation.
127 *
128 * @method onScreenOrientationChanged
129 * @param callback {Function(ScreenOrientation)} Function to be called when the application's screen orientation has changed.
130 */
131 onScreenOrientationChanged: function(callback) {
132 var self = this;
133 this._proxy.call('onScreenOrientationChanged'
134 , [function(orientation) {self._screenOrientation = orientation; callback(orientation); }]);
135 },
136
137 /**
138 * Sets up a URI handler. The application can be sent URIs to open.
139 *
140 * @method setupUriHandler
141 * @param callback {Function([String])} Function to be called with the current list of uris to open
142 */
143 setupUriHandler: function(callback) {
144 this._proxy.call('setupUriHandler'
145 , [callback]);
146 },
147
148 /**
149 * Retrieves the current input method's name. The name varies depending on the platform
150 * e.g. maliit can be part of the name for a maliit based Virtual Keyboard (possibly mangled
151 * with e.g. 'phablet'), when a keyboard is there the name can be empty, ...
152 *
153 * @method getInputMethodName
154 * @param callback {Function(String)} Function to be called with the current input method name
155 */
156 getInputMethodName: function(callback) {
157 this._proxy.call('getInputMethodName'
158 , []
159 , callback);
160 },
161
162 /**
163 * Sets up a callback that is to be called when the On Screen Keyboard visibility has changed.
164 *
165 * @method onInputMethodVisibilityChanged
166 * @param callback {Function(Bool)} Function to be called when the On Screen Keyboard visibility has changed (received the visibility as an arg).
167 */
168 onInputMethodVisibilityChanged: function(callback) {
169 this._proxy.call('onInputMethodVisibilityChanged'
170 , [callback]);
171 }
172 };
173
174 function _constructorFromName(className) {
175 var constructorPerName = {
176 "Application": Application,
177 };
178 return className in constructorPerName
179 ? constructorPerName[className]
180 : null;
181 };
182
183
184/**
185 * The RuntimeApi object
186
187 * @class RuntimeApi
188 * @constructor
189 * @example
190
191 var api = external.getUnityObject('1.0');
192 api.RuntimeApi.getApplication(function(application) {
193 console.log('Application name: ' + application.getApplicationName());
194 });
195 */
196 return {
197 /**
198 Enumeration of the available types of ScreenOrientation.
199
200 Values:
201
202 Landscape: The application screen is in landscape mode
203
204 InvertedLandscape: The application screen is in inverted landscape mode
205
206 Portrait: The application screen is in portrait mode
207
208 InvertedPortrait: The application screen is in inverted portrait mode
209
210 Unknown: The application screen is in an unknown mode
211
212 @static
213 @property ScreenOrientation {Object}
214
215 @example
216
217 var api = external.getUnityObject('1.0');
218 var orientation = api.RuntimeApi.ScreenOrientation;
219 // use orientation.Landscape or orientation.Portrait
220 */
221 ScreenOrientation: {
222 Landscape: "Landscape",
223
224 InvertedLandscape: "InvertedLandscape",
225
226 Portrait: "Portrait",
227
228 InvertedPortrait: "InvertedPortrait",
229
230 Unknwon: "Unknown",
231 },
232
233 /**
234 * Creates an Application object.
235 *
236 * @method getApplication
237 * @param callback {Function (Application)}
238 */
239 getApplication: function(callback) {
240 backendBridge.call('RuntimeApi.getApplication'
241 , []
242 , callback);
243 },
244
245 /**
246 * @private
247 *
248 */
249 createObjectWrapper: function(objectType, objectId, content) {
250 var Constructor = _constructorFromName(objectType);
251 return new Constructor(objectId, content);
252 },
253 };
254};
255
256
0257
=== added file 'src/Ubuntu/UnityWebApps/plugin/application-api.cpp'
--- src/Ubuntu/UnityWebApps/plugin/application-api.cpp 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/plugin/application-api.cpp 2014-03-26 15:53:02 +0000
@@ -0,0 +1,287 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "application-api.h"
20
21#include "application-signal-to-qt-bridge.h"
22
23#include <QDebug>
24#include <QGuiApplication>
25#include <QScreen>
26#include <QDir>
27#include <QtCore/QCoreApplication>
28#include <QtCore/QStandardPaths>
29#include <signal.h>
30
31
32namespace
33{
34
35QString
36nameFromScreenOrientation (Qt::ScreenOrientation orientation)
37{
38 switch (orientation)
39 {
40 case Qt::InvertedLandscapeOrientation:
41 return QString("InvertedLandscape");
42
43 case Qt::LandscapeOrientation:
44 return QString("Landscape");
45
46 case Qt::PortraitOrientation:
47 return QString("Portrait");
48
49 case Qt::InvertedPortraitOrientation:
50 return QString("InvertedPortrait");
51
52 case Qt::PrimaryOrientation:
53 return QString("Primary");
54
55 default:
56 break;
57 }
58
59 return QString("Unknown");
60}
61
62}
63
64class ApplicationApiEventListener : public QObject
65{
66 Q_OBJECT
67
68public:
69 ApplicationApiEventListener(QObject * parent)
70 : QObject(parent)
71 {
72 if (QGuiApplication::instance())
73 QGuiApplication::instance()->installEventFilter(this);
74 }
75 ~ApplicationApiEventListener()
76 {
77 if (QGuiApplication::instance())
78 QGuiApplication::instance()->removeEventFilter(this);
79 }
80
81 bool eventFilter(QObject *obj,
82 QEvent *event)
83 {
84 switch (event->type())
85 {
86 case QEvent::ApplicationActivate:
87 Q_EMIT activated();
88 break;
89 case QEvent::ApplicationDeactivate:
90 Q_EMIT deactivated();
91 break;
92 default:
93 break;
94 }
95 return QObject::eventFilter(obj, event);
96 }
97
98Q_SIGNALS:
99
100 void activated();
101 void deactivated();
102};
103
104
105class ApplicationApiPrivate: public QObject
106{
107 Q_OBJECT
108
109public:
110 ApplicationApiPrivate(QObject * parent)
111 : QObject(parent),
112 _applicationEventListener(new ApplicationApiEventListener(this)),
113 _applicationSignalBridge(new ApplicationSignalToQtBridge(this))
114 {}
115 ~ApplicationApiPrivate()
116 {
117 delete _applicationEventListener;
118 delete _applicationSignalBridge;
119 }
120
121 ApplicationApiEventListener * _applicationEventListener;
122 ApplicationSignalToQtBridge * _applicationSignalBridge;
123};
124
125
126ApplicationApi::ApplicationApi(QObject *parent) :
127 QObject(parent),
128 d_ptr(new ApplicationApiPrivate(this))
129
130{
131 Q_D(ApplicationApi);
132
133 QObject::connect(QCoreApplication::instance(),
134 &QCoreApplication::aboutToQuit,
135 this,
136 &ApplicationApi::aboutToQuit);
137
138 QObject::connect(d->_applicationEventListener,
139 &ApplicationApiEventListener::activated,
140 this,
141 &ApplicationApi::activated);
142
143 QObject::connect(d->_applicationEventListener,
144 &ApplicationApiEventListener::deactivated,
145 this,
146 &ApplicationApi::deactivated);
147
148 QObject::connect(d->_applicationSignalBridge,
149 &ApplicationSignalToQtBridge::onSignalRaised,
150 this,
151 &ApplicationApi::signalReceived);
152
153 // We explictly handle the SIGTERM signal case that is being sent
154 // on Touch to an application being killed by the platform.
155 // Upstart sends this signal when the application is closed from app scope.
156 d->_applicationSignalBridge->addSignalHandlerFor(SIGTERM);
157
158 QScreen * screen = QGuiApplication::primaryScreen();
159 if (screen)
160 {
161 QObject::connect(screen,
162 &QScreen::orientationChanged,
163 this,
164 &ApplicationApi::screenOrientationChanged);
165 }
166}
167
168ApplicationApi::~ApplicationApi()
169{
170 Q_D(ApplicationApi);
171
172 QObject::disconnect(QCoreApplication::instance(),
173 &QCoreApplication::aboutToQuit,
174 this,
175 &ApplicationApi::aboutToQuit);
176
177 QObject::disconnect(d->_applicationEventListener,
178 &ApplicationApiEventListener::activated,
179 this,
180 &ApplicationApi::activated);
181
182 QObject::disconnect(d->_applicationEventListener,
183 &ApplicationApiEventListener::deactivated,
184 this,
185 &ApplicationApi::deactivated);
186
187 QObject::disconnect(d->_applicationSignalBridge,
188 &ApplicationSignalToQtBridge::onSignalRaised,
189 this,
190 &ApplicationApi::signalReceived);
191
192 QScreen * screen = QGuiApplication::primaryScreen();
193 if (screen)
194 {
195 QObject::disconnect(screen,
196 &QScreen::orientationChanged,
197 this,
198 &ApplicationApi::screenOrientationChanged);
199 }
200
201 delete d_ptr;
202}
203
204QString ApplicationApi::getApplicationName() const
205{
206 if ( ! qgetenv("APP_ID").isEmpty())
207 return qgetenv("APP_ID");
208
209 return QCoreApplication::applicationName();
210}
211
212QString ApplicationApi::getApplicationDataPath() const
213{
214 QDir dataLocation(
215 QStandardPaths::writableLocation(
216 QStandardPaths::DataLocation));
217
218 if (!dataLocation.exists()) {
219 QDir::root().mkpath(dataLocation.absolutePath());
220 }
221
222 return dataLocation.absolutePath();
223}
224
225QString ApplicationApi::getApplicationScreenOrientation() const
226{
227 QScreen * screen = QGuiApplication::primaryScreen();
228
229 return nameFromScreenOrientation(screen->primaryOrientation());
230}
231
232QString ApplicationApi::getInputMethodName() const
233{
234 return QString(getenv("QT_IM_MODULE"));
235}
236
237void ApplicationApi::setInputMethodVisible(bool visible)
238{
239 QGuiApplication::inputMethod()->setVisible(visible);
240 if (visible)
241 QGuiApplication::inputMethod()->show();
242 else
243 QGuiApplication::inputMethod()->hide();
244}
245
246QString ApplicationApi::getApplicationPlatform() const
247{
248 return QGuiApplication::platformName();
249}
250
251void ApplicationApi::aboutToQuit()
252{
253 Q_EMIT applicationAboutToQuit(false);
254}
255
256void ApplicationApi::activated()
257{
258 Q_EMIT applicationActivated();
259}
260
261void ApplicationApi::deactivated()
262{
263 Q_EMIT applicationDeactivated();
264}
265
266void ApplicationApi::signalReceived(int type)
267{
268 if (type != SIGTERM && type != SIGINT)
269 return;
270
271 bool killed = (type == SIGTERM);
272
273 Q_EMIT applicationAboutToQuit(killed);
274
275 QCoreApplication::quit();
276}
277
278void ApplicationApi::screenOrientationChanged(Qt::ScreenOrientation orientation)
279{
280 Q_EMIT applicationScreenOrientationChanged(
281 nameFromScreenOrientation(
282 orientation));
283}
284
285
286#include "application-api.moc"
287
0288
=== added file 'src/Ubuntu/UnityWebApps/plugin/application-api.h'
--- src/Ubuntu/UnityWebApps/plugin/application-api.h 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/plugin/application-api.h 2014-03-26 15:53:02 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef UNITY_WEBAPPS_APPLICATIONAPI_H
20#define UNITY_WEBAPPS_APPLICATIONAPI_H
21
22#include <QObject>
23
24class ApplicationApiPrivate;
25
26class ApplicationApi : public QObject
27{
28 Q_OBJECT
29 Q_PROPERTY(QString applicationName READ getApplicationName NOTIFY applicationNameChanged)
30 Q_PROPERTY(QString screenOrientation READ getApplicationScreenOrientation NOTIFY applicationScreenOrientationChanged)
31 Q_PROPERTY(QString applicationDataPath READ getApplicationDataPath)
32 Q_PROPERTY(QString applicationPlatform READ getApplicationPlatform)
33
34
35public:
36 explicit ApplicationApi(QObject *parent = 0);
37 ~ApplicationApi();
38
39 QString getApplicationName() const;
40
41 QString getApplicationDataPath() const;
42
43 QString getApplicationPlatform() const;
44
45 QString getApplicationScreenOrientation() const;
46
47 Q_INVOKABLE QString getInputMethodName() const;
48 Q_INVOKABLE void setInputMethodVisible(bool);
49
50
51Q_SIGNALS:
52
53 void applicationNameChanged();
54 void applicationAboutToQuit(bool killed);
55 void applicationDeactivated();
56 void applicationActivated();
57 void applicationScreenOrientationChanged(QString);
58
59
60public Q_SLOTS:
61
62 void aboutToQuit();
63 void deactivated();
64 void activated();
65 void screenOrientationChanged(Qt::ScreenOrientation);
66 void signalReceived(int type);
67
68
69private:
70
71 ApplicationApiPrivate *d_ptr;
72 Q_DECLARE_PRIVATE(ApplicationApi)
73};
74
75#endif // UNITY_WEBAPPS_APPLICATIONAPI_H
076
=== added file 'src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.cpp'
--- src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.cpp 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.cpp 2014-03-26 15:53:02 +0000
@@ -0,0 +1,139 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "application-signal-to-qt-bridge.h"
20
21#include <QDebug>
22#include <QSocketNotifier>
23
24#include <sys/socket.h>
25#include <signal.h>
26#include <unistd.h>
27
28/**
29 * @brief The ApplicationSignalToQtBridgePrivate class
30 *
31 * It does the job described here:
32 *
33 * https://qt-project.org/doc/qt-5.0/qtdoc/unix-signals.html
34 *
35 * and bridges Unix signal handlers & qt objects in a proper
36 * way.
37 *
38 */
39
40class ApplicationSignalToQtBridgePrivate: public QObject
41{
42 Q_OBJECT
43
44public:
45 ApplicationSignalToQtBridgePrivate(QObject * parent)
46 : QObject(parent),
47 _signalSocketNotifier(NULL)
48 {}
49 ~ApplicationSignalToQtBridgePrivate()
50 {
51 delete _signalSocketNotifier;
52 }
53
54 QSocketNotifier * _signalSocketNotifier;
55};
56
57
58int ApplicationSignalToQtBridge::signalSocketPair[2];
59
60ApplicationSignalToQtBridge::ApplicationSignalToQtBridge(QObject *parent)
61 : QObject(parent)
62 , d_ptr(new ApplicationSignalToQtBridgePrivate(this))
63{}
64
65ApplicationSignalToQtBridge::~ApplicationSignalToQtBridge()
66{
67 delete d_ptr;
68}
69
70void ApplicationSignalToQtBridge::setupQtSignalListener()
71{
72 Q_D(ApplicationSignalToQtBridge);
73
74 if (0 != ::socketpair(AF_UNIX, SOCK_STREAM, 0, signalSocketPair))
75 {
76 qFatal("Couldn't create HUP socketpair");
77 }
78
79 d->_signalSocketNotifier =
80 new QSocketNotifier (signalSocketPair[1],
81 QSocketNotifier::Read,
82 this);
83
84 connect(d->_signalSocketNotifier,
85 SIGNAL(activated(int)),
86 this,
87 SLOT(handleSignal(int)));
88}
89
90bool ApplicationSignalToQtBridge::addSignalHandlerFor(int type)
91{
92 Q_D(ApplicationSignalToQtBridge);
93
94 if ( ! d->_signalSocketNotifier)
95 setupQtSignalListener();
96
97 struct sigaction sa;
98
99 sa.sa_handler = ApplicationSignalToQtBridge::signalHandler;
100 sigemptyset (&sa.sa_mask);
101 sa.sa_flags = 0;
102 sa.sa_flags |= SA_RESTART;
103
104 return sigaction (type, &sa, 0) > 0;
105}
106
107void ApplicationSignalToQtBridge::signalHandler(int type)
108{
109 if (0 != signalSocketPair[0])
110 {
111 size_t size =
112 ::write (signalSocketPair[0],
113 &type,
114 sizeof(type));
115 Q_UNUSED(size);
116 }
117}
118
119void ApplicationSignalToQtBridge::handleSignal(int socket)
120{
121 Q_D(ApplicationSignalToQtBridge);
122
123 Q_UNUSED(socket);
124
125 d->_signalSocketNotifier->setEnabled(false);
126
127 int type = 0;
128 size_t size =
129 ::read (signalSocketPair[1], &type, sizeof(type));
130 Q_UNUSED(size);
131
132 Q_EMIT onSignalRaised(type);
133
134 d->_signalSocketNotifier->setEnabled(true);
135}
136
137
138#include "application-signal-to-qt-bridge.moc"
139
0140
=== added file 'src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.h'
--- src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.h 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/UnityWebApps/plugin/application-signal-to-qt-bridge.h 2014-03-26 15:53:02 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of unity-webapps-qml.
5 *
6 * unity-webapps-qml is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * unity-webapps-qml is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef APPLICATIONSIGNALTOQTBRIDGE_H
20#define APPLICATIONSIGNALTOQTBRIDGE_H
21
22#include <QObject>
23
24
25class ApplicationSignalToQtBridgePrivate;
26
27class ApplicationSignalToQtBridge : public QObject
28{
29 Q_OBJECT
30
31public:
32
33 explicit ApplicationSignalToQtBridge (QObject *parent = 0);
34 ~ApplicationSignalToQtBridge ();
35
36 bool addSignalHandlerFor(int type);
37
38
39public Q_SLOTS:
40
41 void handleSignal(int type);
42
43
44Q_SIGNALS:
45
46 void onSignalRaised(int type);
47
48
49private:
50
51 void setupQtSignalListener();
52
53 // Unix signal handlers.
54 static void signalHandler(int type);
55
56 static int signalSocketPair[2];
57
58 ApplicationSignalToQtBridgePrivate *d_ptr;
59 Q_DECLARE_PRIVATE(ApplicationSignalToQtBridge)
60};
61
62#endif // APPLICATIONSIGNALTOQTBRIDGE_H
063
=== modified file 'src/Ubuntu/UnityWebApps/plugin/plugin.pro'
--- src/Ubuntu/UnityWebApps/plugin/plugin.pro 2014-01-17 15:51:27 +0000
+++ src/Ubuntu/UnityWebApps/plugin/plugin.pro 2014-03-26 15:53:02 +0000
@@ -40,7 +40,9 @@
40 unity-webapps-desktop-infos.cpp \40 unity-webapps-desktop-infos.cpp \
41 unity-webapps-icon-utils.cpp \41 unity-webapps-icon-utils.cpp \
42 callback.cpp \42 callback.cpp \
43 abstract-item-model-adaptor.cpp43 abstract-item-model-adaptor.cpp \
44 application-api.cpp \
45 application-signal-to-qt-bridge.cpp
4446
45HEADERS += \47HEADERS += \
46 qml-plugin.h \48 qml-plugin.h \
@@ -57,7 +59,9 @@
57 unity-webapps-desktop-infos.h \59 unity-webapps-desktop-infos.h \
58 unity-webapps-icon-utils.h \60 unity-webapps-icon-utils.h \
59 callback.h \61 callback.h \
60 abstract-item-model-adaptor.h62 abstract-item-model-adaptor.h \
63 application-api.h \
64 application-signal-to-qt-bridge.h
6165
62DEFINES += \66DEFINES += \
63 API_URI=\\\"$${API_URI}\\\"67 API_URI=\\\"$${API_URI}\\\"
6468
=== modified file 'src/Ubuntu/UnityWebApps/plugin/qml-plugin.cpp'
--- src/Ubuntu/UnityWebApps/plugin/qml-plugin.cpp 2014-01-17 15:51:27 +0000
+++ src/Ubuntu/UnityWebApps/plugin/qml-plugin.cpp 2014-03-26 15:53:02 +0000
@@ -17,6 +17,10 @@
17 */17 */
1818
19#include "qml-plugin.h"19#include "qml-plugin.h"
20
21#include <QtQml/QQmlEngine>
22#include <QtQml/QQmlContext>
23
20#include "unity-webapps-api.h"24#include "unity-webapps-api.h"
21#include "unity-webapps-api-notifications.h"25#include "unity-webapps-api-notifications.h"
22#include "unity-webapps-api-messaging-menu.h"26#include "unity-webapps-api-messaging-menu.h"
@@ -26,11 +30,19 @@
26#include "unity-webapps-app-model.h"30#include "unity-webapps-app-model.h"
27#include "unity-webapps-app-infos.h"31#include "unity-webapps-app-infos.h"
2832
33#include "application-api.h"
29#include "abstract-item-model-adaptor.h"34#include "abstract-item-model-adaptor.h"
30#include "callback.h"35#include "callback.h"
3136
32#include <qqml.h>37#include <qqml.h>
3338
39static QObject *createApplicationApi(QQmlEngine *engine, QJSEngine *scriptEngine)
40{
41 Q_UNUSED(engine);
42 Q_UNUSED(scriptEngine);
43
44 return new ApplicationApi();
45}
3446
35void WebappsQmlPlugin::registerTypes(const char *uri)47void WebappsQmlPlugin::registerTypes(const char *uri)
36{48{
@@ -49,5 +61,8 @@
4961
50 // TODO bump version62 // TODO bump version
51 qmlRegisterType<AbstractItemModelAdaptor> (uri, 0, 1, "AbstractItemModelAdaptor");63 qmlRegisterType<AbstractItemModelAdaptor> (uri, 0, 1, "AbstractItemModelAdaptor");
64
65 //
66 qmlRegisterSingletonType<ApplicationApi>(uri, 0, 1, "ApplicationApi", createApplicationApi);
52}67}
5368
5469
=== modified file 'src/Ubuntu/UnityWebApps/unity-webapps-api.js.in'
--- src/Ubuntu/UnityWebApps/unity-webapps-api.js.in 2014-03-18 17:26:34 +0000
+++ src/Ubuntu/UnityWebApps/unity-webapps-api.js.in 2014-03-26 15:53:02 +0000
@@ -33,6 +33,7 @@
33 //@include ./bindings/alarm-api/client/alarm-api.js33 //@include ./bindings/alarm-api/client/alarm-api.js
34 //@include ./bindings/content-hub/client/content-hub.js34 //@include ./bindings/content-hub/client/content-hub.js
35 //@include ./bindings/online-accounts/client/online-accounts.js35 //@include ./bindings/online-accounts/client/online-accounts.js
36 //@include ./bindings/runtime-api/client/runtime-api.js
36 //@include ./common/js/unity-backend-messaging-proxy.js37 //@include ./common/js/unity-backend-messaging-proxy.js
37 //@include ./common/js/unity-binding-proxy.js38 //@include ./common/js/unity-binding-proxy.js
38 //@include ./common/js/unity-binding-bridge.js39 //@include ./common/js/unity-binding-bridge.js
@@ -280,6 +281,7 @@
280 OnlineAccounts: createOnlineAccountsApi(backend),281 OnlineAccounts: createOnlineAccountsApi(backend),
281 AlarmApi: createAlarmApi(backend),282 AlarmApi: createAlarmApi(backend),
282 ContentHub: createContentHubApi(backend),283 ContentHub: createContentHubApi(backend),
284 RuntimeApi: createRuntimeApi(backend),
283 };285 };
284286
285 return api;287 return api;
286288
=== modified file 'tests/unit/test_plugin/tst_plugin.cpp'
--- tests/unit/test_plugin/tst_plugin.cpp 2014-01-21 19:58:04 +0000
+++ tests/unit/test_plugin/tst_plugin.cpp 2014-03-26 15:53:02 +0000
@@ -25,6 +25,8 @@
25#include <QSignalSpy>25#include <QSignalSpy>
26#include <QJsonDocument>26#include <QJsonDocument>
27#include <QVariantMap>27#include <QVariantMap>
28#include <QProcess>
29#include <QProcessEnvironment>
2830
29#include "plugin/unity-webapps-api.h"31#include "plugin/unity-webapps-api.h"
30#include "plugin/abstract-item-model-adaptor.h"32#include "plugin/abstract-item-model-adaptor.h"
@@ -172,5 +174,22 @@
172 delete model;174 delete model;
173}175}
174176
177void PluginTest::testApplicationSignalHandler()
178{
179 QProcess testApp;
180 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
181
182 env.insert("APP_ID", "application-api");
183
184 testApp.setProcessEnvironment(env);
185 testApp.start("qmlscene -I ../../../src ../../../examples/api-bindings/application-api/main.qml");
186 testApp.waitForStarted();
187
188 testApp.terminate();
189 testApp.waitForFinished();
190
191 QVERIFY(true);
192}
193
175#include "tst_plugin.moc"194#include "tst_plugin.moc"
176195
177196
=== modified file 'tests/unit/test_plugin/tst_plugin.h'
--- tests/unit/test_plugin/tst_plugin.h 2014-01-17 15:51:27 +0000
+++ tests/unit/test_plugin/tst_plugin.h 2014-03-26 15:53:02 +0000
@@ -35,6 +35,7 @@
35 void testLoadPlugin();35 void testLoadPlugin();
36 void testInit();36 void testInit();
37 void testAbstractItemModelAdaptor();37 void testAbstractItemModelAdaptor();
38 void testApplicationSignalHandler();
38};39};
3940
40#endif // TST_PLUGIN_H41#endif // TST_PLUGIN_H

Subscribers

People subscribed via source and target branches

to all changes: