Merge lp:~ted/url-dispatcher/url-overlay into lp:url-dispatcher/15.10
- url-overlay
- Merge into trunk.15.10
Status: | Merged |
---|---|
Approved by: | Ted Gould |
Approved revision: | 138 |
Merged at revision: | 86 |
Proposed branch: | lp:~ted/url-dispatcher/url-overlay |
Merge into: | lp:url-dispatcher/15.10 |
Prerequisite: | lp:~ted/url-dispatcher/upstart-build-dep |
Diff against target: |
2046 lines (+1506/-41) 34 files modified
CMakeLists.txt (+5/-2) data/CMakeLists.txt (+7/-2) data/url-dispatcher.url-overlay.click-hook.in (+3/-0) debian/control (+2/-1) debian/rules (+5/-0) debian/url-dispatcher.install (+1/-0) service/CMakeLists.txt (+26/-2) service/dispatcher.c (+96/-13) service/dispatcher.h (+6/-3) service/glib-thread.cpp (+179/-0) service/glib-thread.h (+81/-0) service/overlay-tracker-iface.h (+26/-0) service/overlay-tracker-mir.cpp (+153/-0) service/overlay-tracker-mir.h (+49/-0) service/overlay-tracker.cpp (+54/-0) service/overlay-tracker.h (+28/-0) service/recoverable-problem.c (+6/-0) service/service.c (+3/-1) service/url-db.c (+1/-1) service/url-db.h (+1/-1) service/url-overlay.c (+174/-0) tests/CMakeLists.txt (+47/-1) tests/app-id-test.cc (+3/-1) tests/dispatcher-test.cc (+25/-1) tests/exec-tool-test.cc (+118/-0) tests/mir-mock.cpp (+124/-0) tests/mir-mock.h (+36/-0) tests/overlay-dir/com.test.good_application_1.2.3.desktop (+2/-0) tests/overlay-tracker-mock.h (+30/-0) tests/overlay-tracker-test.cpp (+127/-0) tests/service-test.cc (+3/-8) tests/test-config.h.in (+4/-0) tests/ubuntu-app-launch-mock.c (+67/-2) tests/ubuntu-app-launch-mock.h (+14/-2) |
To merge this branch: | bzr merge lp:~ted/url-dispatcher/url-overlay |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Charles Kerr (community) | Approve | ||
Review via email: mp+261415@code.launchpad.net |
This proposal supersedes a proposal from 2015-05-17.
Commit message
Support URL Overlays of content in a trusted session without a desktop file
Description of the change
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:128
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:129
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:130
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:131
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:132
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:133
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:134
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Some questions/comments inline, no blockers though.
Ted Gould (ted) wrote : | # |
On Thu, 2015-06-11 at 17:26 +0000, Charles Kerr wrote:
> Some questions/comments inline, no blockers though.
Great, thanks for reviewing, long MR!
> > + -lpthread
>
> -lpthread reportedly doesn't work on clang, maybe use -pthread instead here?
Oh, didn't realize that. Fixed r135.
> > +ContextThread:
>
> not a blocker, but the 'void' isn't needed in C++ for functions taking no args
Not *needed* but enjoyed. Removed r136.
> > + void removeSession (MirPromptSession * session);
> > +
> > + static void sessionStateCha
> > + void sessionStateChanged (MirPromptSession * session, MirPromptSessio
> > +
> > + static void untrustedHelper
> > + void untrustedHelper
>
> These five should be private
Fixed r137.
> > + OverlayTrackerMir * cpptracker = new OverlayTrackerM
> > + return reinterpret_
>
> I don't think reinterpret_cast<> is needed here; you should be able to upcast implicitly; e.g.
>
> try {
> return new OverlayTrackerM
> }
> catch(...) {
> return nullptr;
> }
We're not actually upcasting here, we're casting to an anonymous C
pointer, so that's why we need it. Trying to merge the C and C++ worlds.
> > + } catch (...) {
> > + return nullptr;
> > + }
> > +}
> > +
> > +void
> > +overlay_
> > + g_return_
> > +
> > + auto cpptracker = reinterpret_
> > + delete cpptracker;
>
> no need to reinterpret_cast here either; "delete tracker" should suffice
Same, OverlayTracker isn't a C++ object so it can't be deleted.
> > + /* Allow disabling for testing, we don't want to report bugs on
> > + our tests ;-) */
> > + if (G_UNLIKELY(
> > + return;
> > + }
> > +
>
> :-)
As an aside I built this into the libwhoopsie version as well. Make sure
to use it :-)
> > GError * error = NULL;
> > gint error_stdin = 0;
> > GPid pid = 0;
> >
> > === modified file 'service/service.c'
> > --- service/service.c 2014-03-14 19:50:37 +0000
> > +++ service/service.c 2015-06-08 20:42:15 +0000
> > @@ -39,13 +39,15 @@
> >
> > guint term_source = g_unix_
> >
> > - dispatcher_
> > + OverlayTracker * tracker = overlay_
> > + dispatcher_
>
> Looks like dispatcher.c is the only user of this tracker; why not make it a private variable there, instantiated by dispatcher_init() and released by dispatcher_
Mostly to make the injection of the mock easier in the dispatcher tests.
It doesn't look as nice in C as it does in C++ when you do that. Would
be nice to change main.c to main.cpp, but this MR is big enough ☺
Also fixed a couple warning I hadn't noticed before, r138.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:138
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2014-10-28 12:46:32 +0000 | |||
3 | +++ CMakeLists.txt 2015-06-12 15:51:31 +0000 | |||
4 | @@ -52,7 +52,7 @@ | |||
5 | 52 | set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Werror") | 52 | set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Werror") |
6 | 53 | endif() | 53 | endif() |
7 | 54 | 54 | ||
9 | 55 | pkg_check_modules(UBUNTU_APP_LAUNCH REQUIRED ubuntu-app-launch-2) | 55 | pkg_check_modules(UBUNTU_APP_LAUNCH REQUIRED ubuntu-app-launch-2>=0.5) |
10 | 56 | include_directories(${UBUNTU_APP_LAUNCH_INCLUDE_DIRS}) | 56 | include_directories(${UBUNTU_APP_LAUNCH_INCLUDE_DIRS}) |
11 | 57 | 57 | ||
12 | 58 | pkg_check_modules(GLIB2 REQUIRED glib-2.0) | 58 | pkg_check_modules(GLIB2 REQUIRED glib-2.0) |
13 | @@ -76,6 +76,9 @@ | |||
14 | 76 | pkg_check_modules(SQLITE REQUIRED sqlite3) | 76 | pkg_check_modules(SQLITE REQUIRED sqlite3) |
15 | 77 | include_directories(${SQLITE_INCLUDE_DIRS}) | 77 | include_directories(${SQLITE_INCLUDE_DIRS}) |
16 | 78 | 78 | ||
17 | 79 | pkg_check_modules(CLICK REQUIRED click-0.4) | ||
18 | 80 | include_directories(${CLICK_INCLUDE_DIRS}) | ||
19 | 81 | |||
20 | 79 | if(${LOCAL_INSTALL}) | 82 | if(${LOCAL_INSTALL}) |
21 | 80 | set(DBUSSERVICEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services/") | 83 | set(DBUSSERVICEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services/") |
22 | 81 | else() | 84 | else() |
23 | @@ -105,7 +108,7 @@ | |||
24 | 105 | if (${enable_tests}) | 108 | if (${enable_tests}) |
25 | 106 | set (GTEST_SOURCE_DIR /usr/src/gtest/src) | 109 | set (GTEST_SOURCE_DIR /usr/src/gtest/src) |
26 | 107 | set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..) | 110 | set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..) |
28 | 108 | set (GTEST_LIBS -lpthread) | 111 | set (GTEST_LIBS -pthread) |
29 | 109 | enable_testing () | 112 | enable_testing () |
30 | 110 | if (${enable_lcov}) | 113 | if (${enable_lcov}) |
31 | 111 | # include(GCov) | 114 | # include(GCov) |
32 | 112 | 115 | ||
33 | === modified file 'data/CMakeLists.txt' | |||
34 | --- data/CMakeLists.txt 2014-08-20 18:58:49 +0000 | |||
35 | +++ data/CMakeLists.txt 2015-06-12 15:51:31 +0000 | |||
36 | @@ -92,8 +92,13 @@ | |||
37 | 92 | # Click Hook | 92 | # Click Hook |
38 | 93 | ########################### | 93 | ########################### |
39 | 94 | 94 | ||
42 | 95 | configure_file("url-dispatcher.click-hook.in" | 95 | configure_file("url-dispatcher.urls.click-hook.in" |
43 | 96 | "${CMAKE_SOURCE_DIR}/debian/url-dispatcher.click-hook" | 96 | "${CMAKE_SOURCE_DIR}/debian/url-dispatcher.urls.click-hook" |
44 | 97 | @ONLY | ||
45 | 98 | ) | ||
46 | 99 | |||
47 | 100 | configure_file("url-dispatcher.url-overlay.click-hook.in" | ||
48 | 101 | "${CMAKE_SOURCE_DIR}/debian/url-dispatcher.url-overlay.click-hook" | ||
49 | 97 | @ONLY | 102 | @ONLY |
50 | 98 | ) | 103 | ) |
51 | 99 | 104 | ||
52 | 100 | 105 | ||
53 | === added file 'data/url-dispatcher.url-overlay.click-hook.in' | |||
54 | --- data/url-dispatcher.url-overlay.click-hook.in 1970-01-01 00:00:00 +0000 | |||
55 | +++ data/url-dispatcher.url-overlay.click-hook.in 2015-06-12 15:51:31 +0000 | |||
56 | @@ -0,0 +1,3 @@ | |||
57 | 1 | Pattern: ${home}/.cache/url-dispatcher/url-overlays/${id}.desktop | ||
58 | 2 | User-Level: yes | ||
59 | 3 | Hook-Name: url-overlay | ||
60 | 0 | 4 | ||
61 | === renamed file 'data/url-dispatcher.click-hook.in' => 'data/url-dispatcher.urls.click-hook.in' | |||
62 | === modified file 'debian/control' | |||
63 | --- debian/control 2015-06-12 15:51:30 +0000 | |||
64 | +++ debian/control 2015-06-12 15:51:31 +0000 | |||
65 | @@ -9,13 +9,14 @@ | |||
66 | 9 | dh-autoreconf, | 9 | dh-autoreconf, |
67 | 10 | gtester2xunit, | 10 | gtester2xunit, |
68 | 11 | intltool, | 11 | intltool, |
69 | 12 | libclick-0.4-dev, | ||
70 | 12 | libdbus-1-dev, | 13 | libdbus-1-dev, |
71 | 13 | libdbustest1-dev (>= 14.04.0), | 14 | libdbustest1-dev (>= 14.04.0), |
72 | 14 | libglib2.0-dev, | 15 | libglib2.0-dev, |
73 | 15 | libjson-glib-dev, | 16 | libjson-glib-dev, |
74 | 16 | libgtest-dev, | 17 | libgtest-dev, |
75 | 17 | libsqlite3-dev, | 18 | libsqlite3-dev, |
77 | 18 | libubuntu-app-launch2-dev (>= 0.3), | 19 | libubuntu-app-launch2-dev (>= 0.5), |
78 | 19 | python3, | 20 | python3, |
79 | 20 | python3-dbusmock, | 21 | python3-dbusmock, |
80 | 21 | python3-fixtures, | 22 | python3-fixtures, |
81 | 22 | 23 | ||
82 | === modified file 'debian/rules' | |||
83 | --- debian/rules 2014-07-20 11:45:00 +0000 | |||
84 | +++ debian/rules 2015-06-12 15:51:31 +0000 | |||
85 | @@ -2,6 +2,7 @@ | |||
86 | 2 | 2 | ||
87 | 3 | export DPKG_GENSYMBOLS_CHECK_LEVEL = 4 | 3 | export DPKG_GENSYMBOLS_CHECK_LEVEL = 4 |
88 | 4 | export G_MESSAGES_DEBUG=all | 4 | export G_MESSAGES_DEBUG=all |
89 | 5 | export URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR=1 | ||
90 | 5 | 6 | ||
91 | 6 | %: | 7 | %: |
92 | 7 | dh $@ --fail-missing --with click | 8 | dh $@ --fail-missing --with click |
93 | @@ -12,3 +13,7 @@ | |||
94 | 12 | mkdir -p debian/url-dispatcher/etc/apport/crashdb.conf.d/ | 13 | mkdir -p debian/url-dispatcher/etc/apport/crashdb.conf.d/ |
95 | 13 | install -m 644 debian/url-dispatcher-crashdb.conf debian/url-dispatcher/etc/apport/crashdb.conf.d/ | 14 | install -m 644 debian/url-dispatcher-crashdb.conf debian/url-dispatcher/etc/apport/crashdb.conf.d/ |
96 | 14 | dh_install --fail-missing | 15 | dh_install --fail-missing |
97 | 16 | |||
98 | 17 | override_dh_click: | ||
99 | 18 | dh_click --name urls | ||
100 | 19 | dh_click --name url-overlay | ||
101 | 15 | 20 | ||
102 | === modified file 'debian/url-dispatcher.install' | |||
103 | --- debian/url-dispatcher.install 2013-06-28 16:35:12 +0000 | |||
104 | +++ debian/url-dispatcher.install 2015-06-12 15:51:31 +0000 | |||
105 | @@ -1,3 +1,4 @@ | |||
106 | 1 | usr/lib/*/url-dispatcher | 1 | usr/lib/*/url-dispatcher |
107 | 2 | usr/lib/*/ubuntu-app-launch/url-overlay/exec-tool | ||
108 | 2 | usr/share/dbus-1 | 3 | usr/share/dbus-1 |
109 | 3 | usr/share/upstart/sessions | 4 | usr/share/upstart/sessions |
110 | 4 | 5 | ||
111 | === modified file 'service/CMakeLists.txt' | |||
112 | --- service/CMakeLists.txt 2014-05-26 12:56:47 +0000 | |||
113 | +++ service/CMakeLists.txt 2015-06-12 15:51:31 +0000 | |||
114 | @@ -2,6 +2,8 @@ | |||
115 | 2 | include(UseConstantBuilder) | 2 | include(UseConstantBuilder) |
116 | 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
117 | 4 | 4 | ||
118 | 5 | add_definitions( -DOVERLAY_SYSTEM_DIRECTORY="${CMAKE_INSTALL_FULL_DATADIR}/url-dispatcher/url-overlays" ) | ||
119 | 6 | |||
120 | 5 | ########################### | 7 | ########################### |
121 | 6 | # Generated Lib | 8 | # Generated Lib |
122 | 7 | ########################### | 9 | ########################### |
123 | @@ -38,15 +40,24 @@ | |||
124 | 38 | 40 | ||
125 | 39 | add_library(dispatcher-lib STATIC | 41 | add_library(dispatcher-lib STATIC |
126 | 40 | dispatcher.h | 42 | dispatcher.h |
128 | 41 | dispatcher.c) | 43 | dispatcher.c |
129 | 44 | glib-thread.h | ||
130 | 45 | glib-thread.cpp | ||
131 | 46 | overlay-tracker.h | ||
132 | 47 | overlay-tracker.cpp | ||
133 | 48 | overlay-tracker-iface.h | ||
134 | 49 | overlay-tracker-mir.h | ||
135 | 50 | overlay-tracker-mir.cpp) | ||
136 | 42 | 51 | ||
137 | 43 | target_link_libraries(dispatcher-lib | 52 | target_link_libraries(dispatcher-lib |
138 | 44 | url-db-lib | 53 | url-db-lib |
139 | 45 | service-generated | 54 | service-generated |
140 | 55 | -pthread | ||
141 | 46 | ${GLIB2_LIBRARIES} | 56 | ${GLIB2_LIBRARIES} |
142 | 47 | ${GOBJECT2_LIBRARIES} | 57 | ${GOBJECT2_LIBRARIES} |
143 | 48 | ${GIO2_LIBRARIES} | 58 | ${GIO2_LIBRARIES} |
144 | 49 | ${SQLITE_LIBRARIES} | 59 | ${SQLITE_LIBRARIES} |
145 | 60 | ${UBUNTU_APP_LAUNCH_LIBRARIES} | ||
146 | 50 | ) | 61 | ) |
147 | 51 | 62 | ||
148 | 52 | ########################### | 63 | ########################### |
149 | @@ -84,7 +95,7 @@ | |||
150 | 84 | 95 | ||
151 | 85 | set_target_properties(service-exec PROPERTIES OUTPUT_NAME "url-dispatcher") | 96 | set_target_properties(service-exec PROPERTIES OUTPUT_NAME "url-dispatcher") |
152 | 86 | 97 | ||
154 | 87 | target_link_libraries(service-exec dispatcher-lib ${UBUNTU_APP_LAUNCH_LIBRARIES}) | 98 | target_link_libraries(service-exec dispatcher-lib) |
155 | 88 | 99 | ||
156 | 89 | ########################### | 100 | ########################### |
157 | 90 | # Update Directory | 101 | # Update Directory |
158 | @@ -95,6 +106,14 @@ | |||
159 | 95 | target_link_libraries(update-directory ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES} url-db-lib) | 106 | target_link_libraries(update-directory ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES} url-db-lib) |
160 | 96 | 107 | ||
161 | 97 | ########################### | 108 | ########################### |
162 | 109 | # URL Overlay Exec Tool | ||
163 | 110 | ########################### | ||
164 | 111 | |||
165 | 112 | add_executable(url-overlay-exec-tool url-overlay.c recoverable-problem.c) | ||
166 | 113 | set_target_properties(url-overlay-exec-tool PROPERTIES OUTPUT_NAME "exec-tool") | ||
167 | 114 | target_link_libraries(url-overlay-exec-tool ${GIO2_LIBRARIES} ${UBUNTU_APP_LAUNCH_LIBRARIES} ${CLICK_LIBRARIES}) | ||
168 | 115 | |||
169 | 116 | ########################### | ||
170 | 98 | # Installation | 117 | # Installation |
171 | 99 | ########################### | 118 | ########################### |
172 | 100 | 119 | ||
173 | @@ -103,3 +122,8 @@ | |||
174 | 103 | RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher" | 122 | RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher" |
175 | 104 | ) | 123 | ) |
176 | 105 | 124 | ||
177 | 125 | install( | ||
178 | 126 | TARGETS url-overlay-exec-tool | ||
179 | 127 | RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/ubuntu-app-launch/url-overlay" | ||
180 | 128 | ) | ||
181 | 129 | |||
182 | 106 | 130 | ||
183 | === modified file 'service/dispatcher.c' | |||
184 | --- service/dispatcher.c 2015-01-23 14:34:30 +0000 | |||
185 | +++ service/dispatcher.c 2015-06-12 15:51:31 +0000 | |||
186 | @@ -26,6 +26,7 @@ | |||
187 | 26 | #include "url-db.h" | 26 | #include "url-db.h" |
188 | 27 | 27 | ||
189 | 28 | /* Globals */ | 28 | /* Globals */ |
190 | 29 | static OverlayTracker * tracker = NULL; | ||
191 | 29 | static GCancellable * cancellable = NULL; | 30 | static GCancellable * cancellable = NULL; |
192 | 30 | static ServiceIfaceComCanonicalURLDispatcher * skel = NULL; | 31 | static ServiceIfaceComCanonicalURLDispatcher * skel = NULL; |
193 | 31 | static GRegex * applicationre = NULL; | 32 | static GRegex * applicationre = NULL; |
194 | @@ -44,7 +45,7 @@ | |||
195 | 44 | 45 | ||
196 | 45 | /* Register our errors */ | 46 | /* Register our errors */ |
197 | 46 | static void | 47 | static void |
199 | 47 | register_dbus_errors (void) | 48 | register_dbus_errors () |
200 | 48 | { | 49 | { |
201 | 49 | g_dbus_error_register_error(url_dispatcher_error_quark(), ERROR_BAD_URL, "com.canonical.URLDispatcher.BadURL"); | 50 | g_dbus_error_register_error(url_dispatcher_error_quark(), ERROR_BAD_URL, "com.canonical.URLDispatcher.BadURL"); |
202 | 50 | g_dbus_error_register_error(url_dispatcher_error_quark(), ERROR_RESTRICTED_URL, "com.canonical.URLDispatcher.RestrictedURL"); | 51 | g_dbus_error_register_error(url_dispatcher_error_quark(), ERROR_RESTRICTED_URL, "com.canonical.URLDispatcher.RestrictedURL"); |
203 | @@ -78,11 +79,7 @@ | |||
204 | 78 | NULL | 79 | NULL |
205 | 79 | }; | 80 | }; |
206 | 80 | 81 | ||
212 | 81 | /* Allow disabling for testing, we don't want to report bugs on | 82 | report_recoverable_problem("url-dispatcher-bad-url", pid, FALSE, additional); |
208 | 82 | our tests ;-) */ | ||
209 | 83 | if (g_getenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR") == NULL) { | ||
210 | 84 | report_recoverable_problem("url-dispatcher-bad-url", pid, FALSE, additional); | ||
211 | 85 | } | ||
213 | 86 | 83 | ||
214 | 87 | g_free(badurl); | 84 | g_free(badurl); |
215 | 88 | 85 | ||
216 | @@ -111,7 +108,7 @@ | |||
217 | 111 | bad_url (GDBusMethodInvocation * invocation, const gchar * url) | 108 | bad_url (GDBusMethodInvocation * invocation, const gchar * url) |
218 | 112 | { | 109 | { |
219 | 113 | const gchar * sender = g_dbus_method_invocation_get_sender(invocation); | 110 | const gchar * sender = g_dbus_method_invocation_get_sender(invocation); |
221 | 114 | GDBusConnection * conn = g_dbus_method_invocation_get_connection(invocation); | 111 | GDBusConnection * conn = g_dbus_method_invocation_get_connection(invocation); /* transfer: none */ |
222 | 115 | 112 | ||
223 | 116 | g_dbus_connection_call(conn, | 113 | g_dbus_connection_call(conn, |
224 | 117 | "org.freedesktop.DBus", | 114 | "org.freedesktop.DBus", |
225 | @@ -213,6 +210,73 @@ | |||
226 | 213 | return TRUE; | 210 | return TRUE; |
227 | 214 | } | 211 | } |
228 | 215 | 212 | ||
229 | 213 | /* Handles setting up the overlay with the URL */ | ||
230 | 214 | gboolean | ||
231 | 215 | dispatcher_send_to_overlay (const gchar * app_id, const gchar * url, GDBusConnection * conn, const gchar * sender) | ||
232 | 216 | { | ||
233 | 217 | GError * error = NULL; | ||
234 | 218 | |||
235 | 219 | /* TODO: Detect if a scope is what we need to overlay on */ | ||
236 | 220 | GVariant * callret = g_dbus_connection_call_sync(conn, | ||
237 | 221 | "org.freedesktop.DBus", | ||
238 | 222 | "/", | ||
239 | 223 | "org.freedesktop.DBus", | ||
240 | 224 | "GetConnectionUnixProcessID", | ||
241 | 225 | g_variant_new("(s)", sender), | ||
242 | 226 | G_VARIANT_TYPE("(u)"), | ||
243 | 227 | G_DBUS_CALL_FLAGS_NONE, | ||
244 | 228 | -1, /* timeout */ | ||
245 | 229 | NULL, /* cancellable */ | ||
246 | 230 | &error); | ||
247 | 231 | |||
248 | 232 | if (error != NULL) { | ||
249 | 233 | g_warning("Unable to get PID for '%s' when processing URL '%s': %s", sender, url, error->message); | ||
250 | 234 | g_error_free(error); | ||
251 | 235 | return FALSE; | ||
252 | 236 | } | ||
253 | 237 | |||
254 | 238 | unsigned int pid = 0; | ||
255 | 239 | g_variant_get_child(callret, 0, "u", &pid); | ||
256 | 240 | g_variant_unref(callret); | ||
257 | 241 | |||
258 | 242 | return overlay_tracker_add(tracker, app_id, pid, url); | ||
259 | 243 | } | ||
260 | 244 | |||
261 | 245 | /* Check to see if this is an overlay AppID */ | ||
262 | 246 | gboolean | ||
263 | 247 | dispatcher_is_overlay (const gchar * appid) | ||
264 | 248 | { | ||
265 | 249 | const gchar * systemdir = NULL; | ||
266 | 250 | gboolean found = FALSE; | ||
267 | 251 | gchar * desktopname = g_strdup_printf("%s.desktop", appid); | ||
268 | 252 | |||
269 | 253 | /* First time, check the environment */ | ||
270 | 254 | if (G_UNLIKELY(systemdir == NULL)) { | ||
271 | 255 | systemdir = g_getenv("URL_DISPATCHER_OVERLAY_DIR"); | ||
272 | 256 | if (systemdir == NULL) { | ||
273 | 257 | systemdir = OVERLAY_SYSTEM_DIRECTORY; | ||
274 | 258 | } | ||
275 | 259 | } | ||
276 | 260 | |||
277 | 261 | /* Check system dir */ | ||
278 | 262 | if (!found) { | ||
279 | 263 | gchar * sysdir = g_build_filename(systemdir, desktopname, NULL); | ||
280 | 264 | found = g_file_test(sysdir, G_FILE_TEST_EXISTS); | ||
281 | 265 | g_free(sysdir); | ||
282 | 266 | } | ||
283 | 267 | |||
284 | 268 | /* Check user dir (clicks) */ | ||
285 | 269 | if (!found) { | ||
286 | 270 | gchar * usrdir = g_build_filename(g_get_user_cache_dir(), "url-dispatcher", "url-overlays", desktopname, NULL); | ||
287 | 271 | found = g_file_test(usrdir, G_FILE_TEST_EXISTS); | ||
288 | 272 | g_free(usrdir); | ||
289 | 273 | } | ||
290 | 274 | |||
291 | 275 | g_free(desktopname); | ||
292 | 276 | |||
293 | 277 | return found; | ||
294 | 278 | } | ||
295 | 279 | |||
296 | 216 | /* Whether we should restrict this appid based on the package name */ | 280 | /* Whether we should restrict this appid based on the package name */ |
297 | 217 | gboolean | 281 | gboolean |
298 | 218 | dispatcher_appid_restrict (const gchar * appid, const gchar * package) | 282 | dispatcher_appid_restrict (const gchar * appid, const gchar * package) |
299 | @@ -277,12 +341,25 @@ | |||
300 | 277 | } | 341 | } |
301 | 278 | 342 | ||
302 | 279 | /* We're cleared to continue */ | 343 | /* We're cleared to continue */ |
304 | 280 | dispatcher_send_to_app(appid, outurl); | 344 | gboolean sent = FALSE; |
305 | 345 | if (!dispatcher_is_overlay(appid)) { | ||
306 | 346 | sent = dispatcher_send_to_app(appid, outurl); | ||
307 | 347 | } else { | ||
308 | 348 | sent = dispatcher_send_to_overlay( | ||
309 | 349 | appid, | ||
310 | 350 | outurl, | ||
311 | 351 | g_dbus_method_invocation_get_connection(invocation), | ||
312 | 352 | g_dbus_method_invocation_get_sender(invocation)); | ||
313 | 353 | } | ||
314 | 281 | g_free(appid); | 354 | g_free(appid); |
315 | 282 | 355 | ||
317 | 283 | g_dbus_method_invocation_return_value(invocation, NULL); | 356 | if (sent) { |
318 | 357 | g_dbus_method_invocation_return_value(invocation, NULL); | ||
319 | 358 | } else { | ||
320 | 359 | bad_url(invocation, url); | ||
321 | 360 | } | ||
322 | 284 | 361 | ||
324 | 285 | return TRUE; | 362 | return sent; |
325 | 286 | } | 363 | } |
326 | 287 | 364 | ||
327 | 288 | /* Test a URL to find it's AppID */ | 365 | /* Test a URL to find it's AppID */ |
328 | @@ -347,6 +424,9 @@ | |||
329 | 347 | gboolean | 424 | gboolean |
330 | 348 | dispatcher_url_to_appid (const gchar * url, gchar ** out_appid, const gchar ** out_url) | 425 | dispatcher_url_to_appid (const gchar * url, gchar ** out_appid, const gchar ** out_url) |
331 | 349 | { | 426 | { |
332 | 427 | g_return_val_if_fail(url != NULL, FALSE); | ||
333 | 428 | g_return_val_if_fail(out_appid != NULL, FALSE); | ||
334 | 429 | |||
335 | 350 | /* Special case the app id */ | 430 | /* Special case the app id */ |
336 | 351 | GMatchInfo * appidmatch = NULL; | 431 | GMatchInfo * appidmatch = NULL; |
337 | 352 | if (g_regex_match(appidre, url, 0, &appidmatch)) { | 432 | if (g_regex_match(appidre, url, 0, &appidmatch)) { |
338 | @@ -398,7 +478,9 @@ | |||
339 | 398 | 478 | ||
340 | 399 | if (*out_appid != NULL) { | 479 | if (*out_appid != NULL) { |
341 | 400 | found = TRUE; | 480 | found = TRUE; |
343 | 401 | *out_url = url; | 481 | if (out_url != NULL) { |
344 | 482 | *out_url = url; | ||
345 | 483 | } | ||
346 | 402 | } | 484 | } |
347 | 403 | 485 | ||
348 | 404 | g_free(protocol); | 486 | g_free(protocol); |
349 | @@ -465,8 +547,9 @@ | |||
350 | 465 | 547 | ||
351 | 466 | /* Initialize all the globals */ | 548 | /* Initialize all the globals */ |
352 | 467 | gboolean | 549 | gboolean |
354 | 468 | dispatcher_init (GMainLoop * mainloop) | 550 | dispatcher_init (GMainLoop * mainloop, OverlayTracker * intracker) |
355 | 469 | { | 551 | { |
356 | 552 | tracker = intracker; | ||
357 | 470 | cancellable = g_cancellable_new(); | 553 | cancellable = g_cancellable_new(); |
358 | 471 | 554 | ||
359 | 472 | urldb = url_db_create_database(); | 555 | urldb = url_db_create_database(); |
360 | @@ -487,7 +570,7 @@ | |||
361 | 487 | 570 | ||
362 | 488 | /* Clean up all the globals */ | 571 | /* Clean up all the globals */ |
363 | 489 | gboolean | 572 | gboolean |
365 | 490 | dispatcher_shutdown (void) | 573 | dispatcher_shutdown () |
366 | 491 | { | 574 | { |
367 | 492 | g_cancellable_cancel(cancellable); | 575 | g_cancellable_cancel(cancellable); |
368 | 493 | 576 | ||
369 | 494 | 577 | ||
370 | === modified file 'service/dispatcher.h' | |||
371 | --- service/dispatcher.h 2014-10-24 18:55:11 +0000 | |||
372 | +++ service/dispatcher.h 2015-06-12 15:51:31 +0000 | |||
373 | @@ -20,15 +20,18 @@ | |||
374 | 20 | #ifndef DISPATCHER_H | 20 | #ifndef DISPATCHER_H |
375 | 21 | #define DISPATCHER_H 1 | 21 | #define DISPATCHER_H 1 |
376 | 22 | 22 | ||
378 | 23 | #include <glib.h> | 23 | #include <gio/gio.h> |
379 | 24 | #include "overlay-tracker.h" | ||
380 | 24 | 25 | ||
381 | 25 | G_BEGIN_DECLS | 26 | G_BEGIN_DECLS |
382 | 26 | 27 | ||
385 | 27 | gboolean dispatcher_init (GMainLoop * mainloop); | 28 | gboolean dispatcher_init (GMainLoop * mainloop, OverlayTracker * tracker); |
386 | 28 | gboolean dispatcher_shutdown (void); | 29 | gboolean dispatcher_shutdown (); |
387 | 29 | gboolean dispatcher_url_to_appid (const gchar * url, gchar ** out_appid, const gchar ** out_url); | 30 | gboolean dispatcher_url_to_appid (const gchar * url, gchar ** out_appid, const gchar ** out_url); |
388 | 30 | gboolean dispatcher_appid_restrict (const gchar * appid, const gchar * package); | 31 | gboolean dispatcher_appid_restrict (const gchar * appid, const gchar * package); |
389 | 32 | gboolean dispatcher_is_overlay (const gchar * appid); | ||
390 | 31 | gboolean dispatcher_send_to_app (const gchar * appid, const gchar * url); | 33 | gboolean dispatcher_send_to_app (const gchar * appid, const gchar * url); |
391 | 34 | gboolean dispatcher_send_to_overlay (const gchar * app_id, const gchar * url, GDBusConnection * conn, const gchar * sender); | ||
392 | 32 | 35 | ||
393 | 33 | G_END_DECLS | 36 | G_END_DECLS |
394 | 34 | 37 | ||
395 | 35 | 38 | ||
396 | === added file 'service/glib-thread.cpp' | |||
397 | --- service/glib-thread.cpp 1970-01-01 00:00:00 +0000 | |||
398 | +++ service/glib-thread.cpp 2015-06-12 15:51:31 +0000 | |||
399 | @@ -0,0 +1,179 @@ | |||
400 | 1 | /* | ||
401 | 2 | * Copyright © 2015 Canonical Ltd. | ||
402 | 3 | * | ||
403 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
404 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
405 | 6 | * by the Free Software Foundation. | ||
406 | 7 | * | ||
407 | 8 | * This program is distributed in the hope that it will be useful, but | ||
408 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
409 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
410 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
411 | 12 | * | ||
412 | 13 | * You should have received a copy of the GNU General Public License along | ||
413 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
414 | 15 | * | ||
415 | 16 | * Authors: | ||
416 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
417 | 18 | */ | ||
418 | 19 | |||
419 | 20 | #include "glib-thread.h" | ||
420 | 21 | |||
421 | 22 | namespace GLib | ||
422 | 23 | { | ||
423 | 24 | |||
424 | 25 | |||
425 | 26 | ContextThread::ContextThread (std::function<void()> beforeLoop, std::function<void()> afterLoop) | ||
426 | 27 | : _context(nullptr) | ||
427 | 28 | , _loop(nullptr) | ||
428 | 29 | { | ||
429 | 30 | _cancel = std::shared_ptr<GCancellable>(g_cancellable_new(), [](GCancellable * cancel) | ||
430 | 31 | { | ||
431 | 32 | if (cancel != nullptr) | ||
432 | 33 | { | ||
433 | 34 | g_cancellable_cancel(cancel); | ||
434 | 35 | g_object_unref(cancel); | ||
435 | 36 | } | ||
436 | 37 | }); | ||
437 | 38 | std::promise<std::pair<std::shared_ptr<GMainContext>, std::shared_ptr<GMainLoop>>> context_promise; | ||
438 | 39 | |||
439 | 40 | /* NOTE: We copy afterLoop but reference beforeLoop. We're blocking so we | ||
440 | 41 | know that beforeLoop will stay valid long enough, but we can't say the | ||
441 | 42 | same for afterLoop */ | ||
442 | 43 | _thread = std::thread([&context_promise, &beforeLoop, afterLoop, this]() -> void | ||
443 | 44 | { | ||
444 | 45 | /* Build up the context and loop for the async events and a place | ||
445 | 46 | for GDBus to send its events back to */ | ||
446 | 47 | auto context = std::shared_ptr<GMainContext>(g_main_context_new(), [](GMainContext * context) | ||
447 | 48 | { | ||
448 | 49 | g_clear_pointer(&context, g_main_context_unref); | ||
449 | 50 | }); | ||
450 | 51 | auto loop = std::shared_ptr<GMainLoop>(g_main_loop_new(context.get(), FALSE), [](GMainLoop * loop) | ||
451 | 52 | { | ||
452 | 53 | g_clear_pointer(&loop, g_main_loop_unref); | ||
453 | 54 | }); | ||
454 | 55 | |||
455 | 56 | g_main_context_push_thread_default(context.get()); | ||
456 | 57 | |||
457 | 58 | beforeLoop(); | ||
458 | 59 | |||
459 | 60 | /* Free's the constructor to continue */ | ||
460 | 61 | auto pair = std::pair<std::shared_ptr<GMainContext>, std::shared_ptr<GMainLoop>>(context, loop); | ||
461 | 62 | context_promise.set_value(pair); | ||
462 | 63 | |||
463 | 64 | if (!g_cancellable_is_cancelled(_cancel.get())) | ||
464 | 65 | { | ||
465 | 66 | g_main_loop_run(loop.get()); | ||
466 | 67 | } | ||
467 | 68 | |||
468 | 69 | afterLoop(); | ||
469 | 70 | }); | ||
470 | 71 | |||
471 | 72 | /* We need to have the context and the mainloop ready before | ||
472 | 73 | other functions on this object can work properly. So we wait | ||
473 | 74 | for them and set them on this thread. */ | ||
474 | 75 | auto context_future = context_promise.get_future(); | ||
475 | 76 | context_future.wait(); | ||
476 | 77 | auto context_value = context_future.get(); | ||
477 | 78 | |||
478 | 79 | _context = context_value.first; | ||
479 | 80 | _loop = context_value.second; | ||
480 | 81 | |||
481 | 82 | if (_context == nullptr || _loop == nullptr) | ||
482 | 83 | { | ||
483 | 84 | throw std::runtime_error("Unable to create GLib Thread"); | ||
484 | 85 | } | ||
485 | 86 | } | ||
486 | 87 | |||
487 | 88 | ContextThread::~ContextThread () | ||
488 | 89 | { | ||
489 | 90 | quit(); | ||
490 | 91 | } | ||
491 | 92 | |||
492 | 93 | void ContextThread::quit () | ||
493 | 94 | { | ||
494 | 95 | g_cancellable_cancel(_cancel.get()); /* Force the cancellation on ongoing tasks */ | ||
495 | 96 | if (_loop != nullptr) | ||
496 | 97 | { | ||
497 | 98 | g_main_loop_quit(_loop.get()); /* Quit the loop */ | ||
498 | 99 | } | ||
499 | 100 | |||
500 | 101 | /* Joining here because we want to ensure that the final afterLoop() | ||
501 | 102 | function is run before returning */ | ||
502 | 103 | if (std::this_thread::get_id() != _thread.get_id()) | ||
503 | 104 | { | ||
504 | 105 | if (_thread.joinable()) | ||
505 | 106 | { | ||
506 | 107 | _thread.join(); | ||
507 | 108 | } | ||
508 | 109 | } | ||
509 | 110 | } | ||
510 | 111 | |||
511 | 112 | bool ContextThread::isCancelled () | ||
512 | 113 | { | ||
513 | 114 | return g_cancellable_is_cancelled(_cancel.get()) == TRUE; | ||
514 | 115 | } | ||
515 | 116 | |||
516 | 117 | std::shared_ptr<GCancellable> ContextThread::getCancellable () | ||
517 | 118 | { | ||
518 | 119 | return _cancel; | ||
519 | 120 | } | ||
520 | 121 | |||
521 | 122 | void ContextThread::simpleSource (std::function<GSource * ()> srcBuilder, std::function<void()> work) | ||
522 | 123 | { | ||
523 | 124 | if (isCancelled()) | ||
524 | 125 | { | ||
525 | 126 | throw std::runtime_error("Trying to execute work on a GLib thread that is shutting down."); | ||
526 | 127 | } | ||
527 | 128 | |||
528 | 129 | /* Copy the work so that we can reuse it */ | ||
529 | 130 | /* Lifecycle is handled with the source pointer when we attach | ||
530 | 131 | it to the context. */ | ||
531 | 132 | auto heapWork = new std::function<void()>(work); | ||
532 | 133 | |||
533 | 134 | auto source = std::shared_ptr<GSource>(srcBuilder(), | ||
534 | 135 | [](GSource * src) | ||
535 | 136 | { | ||
536 | 137 | g_clear_pointer(&src, g_source_unref); | ||
537 | 138 | } | ||
538 | 139 | ); | ||
539 | 140 | g_source_set_callback(source.get(), | ||
540 | 141 | [](gpointer data) -> gboolean | ||
541 | 142 | { | ||
542 | 143 | std::function<void()>* heapWork = reinterpret_cast<std::function<void()> *>(data); | ||
543 | 144 | (*heapWork)(); | ||
544 | 145 | return G_SOURCE_REMOVE; | ||
545 | 146 | }, heapWork, | ||
546 | 147 | [](gpointer data) | ||
547 | 148 | { | ||
548 | 149 | std::function<void()>* heapWork = reinterpret_cast<std::function<void()> *>(data); | ||
549 | 150 | delete heapWork; | ||
550 | 151 | }); | ||
551 | 152 | |||
552 | 153 | g_source_attach(source.get(), _context.get()); | ||
553 | 154 | } | ||
554 | 155 | |||
555 | 156 | void ContextThread::executeOnThread (std::function<void()> work) | ||
556 | 157 | { | ||
557 | 158 | simpleSource(g_idle_source_new, work); | ||
558 | 159 | } | ||
559 | 160 | |||
560 | 161 | void ContextThread::timeout (const std::chrono::milliseconds& length, | ||
561 | 162 | std::function<void()> work) | ||
562 | 163 | { | ||
563 | 164 | simpleSource([length]() | ||
564 | 165 | { | ||
565 | 166 | return g_timeout_source_new(length.count()); | ||
566 | 167 | }, work); | ||
567 | 168 | } | ||
568 | 169 | |||
569 | 170 | void ContextThread::timeoutSeconds (const std::chrono::seconds& length, | ||
570 | 171 | std::function<void()> work) | ||
571 | 172 | { | ||
572 | 173 | simpleSource([length]() | ||
573 | 174 | { | ||
574 | 175 | return g_timeout_source_new_seconds(length.count()); | ||
575 | 176 | }, work); | ||
576 | 177 | } | ||
577 | 178 | |||
578 | 179 | } // ns GLib | ||
579 | 0 | 180 | ||
580 | === added file 'service/glib-thread.h' | |||
581 | --- service/glib-thread.h 1970-01-01 00:00:00 +0000 | |||
582 | +++ service/glib-thread.h 2015-06-12 15:51:31 +0000 | |||
583 | @@ -0,0 +1,81 @@ | |||
584 | 1 | /* | ||
585 | 2 | * Copyright © 2015 Canonical Ltd. | ||
586 | 3 | * | ||
587 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
588 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
589 | 6 | * by the Free Software Foundation. | ||
590 | 7 | * | ||
591 | 8 | * This program is distributed in the hope that it will be useful, but | ||
592 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
593 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
594 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
595 | 12 | * | ||
596 | 13 | * You should have received a copy of the GNU General Public License along | ||
597 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
598 | 15 | * | ||
599 | 16 | * Authors: | ||
600 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
601 | 18 | */ | ||
602 | 19 | |||
603 | 20 | #include <thread> | ||
604 | 21 | #include <future> | ||
605 | 22 | |||
606 | 23 | #include <gio/gio.h> | ||
607 | 24 | |||
608 | 25 | namespace GLib | ||
609 | 26 | { | ||
610 | 27 | |||
611 | 28 | class ContextThread | ||
612 | 29 | { | ||
613 | 30 | std::thread _thread; | ||
614 | 31 | std::shared_ptr<GMainContext> _context; | ||
615 | 32 | std::shared_ptr<GMainLoop> _loop; | ||
616 | 33 | std::shared_ptr<GCancellable> _cancel; | ||
617 | 34 | |||
618 | 35 | public: | ||
619 | 36 | ContextThread (std::function<void()> beforeLoop = [] {}, std::function<void()> afterLoop = [] {}); | ||
620 | 37 | ~ContextThread (); | ||
621 | 38 | |||
622 | 39 | void quit (); | ||
623 | 40 | bool isCancelled (); | ||
624 | 41 | std::shared_ptr<GCancellable> getCancellable (); | ||
625 | 42 | |||
626 | 43 | void executeOnThread (std::function<void()> work); | ||
627 | 44 | template<typename T> auto executeOnThread (std::function<T()> work) -> T | ||
628 | 45 | { | ||
629 | 46 | if (std::this_thread::get_id() == _thread.get_id()) | ||
630 | 47 | { | ||
631 | 48 | /* Don't block if we're on the same thread */ | ||
632 | 49 | return work(); | ||
633 | 50 | } | ||
634 | 51 | |||
635 | 52 | std::promise<T> promise; | ||
636 | 53 | std::function<void()> magicFunc = [&promise, &work] () -> void { | ||
637 | 54 | promise.set_value(work()); | ||
638 | 55 | }; | ||
639 | 56 | |||
640 | 57 | executeOnThread(magicFunc); | ||
641 | 58 | |||
642 | 59 | auto future = promise.get_future(); | ||
643 | 60 | future.wait(); | ||
644 | 61 | return future.get(); | ||
645 | 62 | } | ||
646 | 63 | |||
647 | 64 | void timeout (const std::chrono::milliseconds& length, std::function<void()> work); | ||
648 | 65 | template<class Rep, class Period> void timeout (const std::chrono::duration<Rep, Period>& length, | ||
649 | 66 | std::function<void()> work) | ||
650 | 67 | { | ||
651 | 68 | return timeout(std::chrono::duration_cast<std::chrono::milliseconds>(length), work); | ||
652 | 69 | } | ||
653 | 70 | |||
654 | 71 | void timeoutSeconds (const std::chrono::seconds& length, std::function<void()> work); | ||
655 | 72 | template<class Rep, class Period> void timeoutSeconds (const std::chrono::duration<Rep, Period>& length, | ||
656 | 73 | std::function<void()> work) | ||
657 | 74 | { | ||
658 | 75 | return timeoutSeconds(std::chrono::duration_cast<std::chrono::seconds>(length), work); | ||
659 | 76 | } | ||
660 | 77 | |||
661 | 78 | private: | ||
662 | 79 | void simpleSource (std::function<GSource * ()> srcBuilder, std::function<void()> work); | ||
663 | 80 | }; | ||
664 | 81 | } | ||
665 | 0 | 82 | ||
666 | === added file 'service/overlay-tracker-iface.h' | |||
667 | --- service/overlay-tracker-iface.h 1970-01-01 00:00:00 +0000 | |||
668 | +++ service/overlay-tracker-iface.h 2015-06-12 15:51:31 +0000 | |||
669 | @@ -0,0 +1,26 @@ | |||
670 | 1 | /* | ||
671 | 2 | * Copyright © 2015 Canonical Ltd. | ||
672 | 3 | * | ||
673 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
674 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
675 | 6 | * by the Free Software Foundation. | ||
676 | 7 | * | ||
677 | 8 | * This program is distributed in the hope that it will be useful, but | ||
678 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
679 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
680 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
681 | 12 | * | ||
682 | 13 | * You should have received a copy of the GNU General Public License along | ||
683 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
684 | 15 | * | ||
685 | 16 | * Authors: | ||
686 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
687 | 18 | */ | ||
688 | 19 | |||
689 | 20 | #pragma once | ||
690 | 21 | |||
691 | 22 | class OverlayTrackerIface { | ||
692 | 23 | public: | ||
693 | 24 | virtual ~OverlayTrackerIface() = default; | ||
694 | 25 | virtual bool addOverlay (const char * appid, unsigned long pid, const char * url) = 0; | ||
695 | 26 | }; | ||
696 | 0 | 27 | ||
697 | === added file 'service/overlay-tracker-mir.cpp' | |||
698 | --- service/overlay-tracker-mir.cpp 1970-01-01 00:00:00 +0000 | |||
699 | +++ service/overlay-tracker-mir.cpp 2015-06-12 15:51:31 +0000 | |||
700 | @@ -0,0 +1,153 @@ | |||
701 | 1 | /* | ||
702 | 2 | * Copyright © 2015 Canonical Ltd. | ||
703 | 3 | * | ||
704 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
705 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
706 | 6 | * by the Free Software Foundation. | ||
707 | 7 | * | ||
708 | 8 | * This program is distributed in the hope that it will be useful, but | ||
709 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
710 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
711 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
712 | 12 | * | ||
713 | 13 | * You should have received a copy of the GNU General Public License along | ||
714 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
715 | 15 | * | ||
716 | 16 | * Authors: | ||
717 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
718 | 18 | */ | ||
719 | 19 | |||
720 | 20 | #include "overlay-tracker-mir.h" | ||
721 | 21 | #include <ubuntu-app-launch.h> | ||
722 | 22 | |||
723 | 23 | static const char * HELPER_TYPE = "url-overlay"; | ||
724 | 24 | |||
725 | 25 | OverlayTrackerMir::OverlayTrackerMir () | ||
726 | 26 | : thread([this] { | ||
727 | 27 | /* Setup Helper Observer */ | ||
728 | 28 | ubuntu_app_launch_observer_add_helper_stop(untrustedHelperStoppedStatic, HELPER_TYPE, this); | ||
729 | 29 | }, | ||
730 | 30 | [this] { | ||
731 | 31 | /* Remove Helper Observer */ | ||
732 | 32 | ubuntu_app_launch_observer_delete_helper_stop(untrustedHelperStoppedStatic, HELPER_TYPE, this); | ||
733 | 33 | }) | ||
734 | 34 | { | ||
735 | 35 | mir = std::shared_ptr<MirConnection>([] { | ||
736 | 36 | gchar * path = g_build_filename(g_get_user_runtime_dir(), "mir_socket_trusted", NULL); | ||
737 | 37 | MirConnection * con = mir_connect_sync(path, "url-dispatcher"); | ||
738 | 38 | g_free(path); | ||
739 | 39 | return con; | ||
740 | 40 | }(), | ||
741 | 41 | [] (MirConnection * connection) { | ||
742 | 42 | if (connection != nullptr) | ||
743 | 43 | mir_connection_release(connection); | ||
744 | 44 | }); | ||
745 | 45 | |||
746 | 46 | if (!mir) { | ||
747 | 47 | throw std::runtime_error("Unable to connect to Mir"); | ||
748 | 48 | } | ||
749 | 49 | } | ||
750 | 50 | |||
751 | 51 | /* Enforce a shutdown order, sessions before connection */ | ||
752 | 52 | OverlayTrackerMir::~OverlayTrackerMir () | ||
753 | 53 | { | ||
754 | 54 | thread.executeOnThread<bool>([this] { | ||
755 | 55 | while (!ongoingSessions.empty()) { | ||
756 | 56 | removeSession(std::get<2>(*ongoingSessions.begin()).get()); | ||
757 | 57 | } | ||
758 | 58 | |||
759 | 59 | return true; | ||
760 | 60 | }); | ||
761 | 61 | |||
762 | 62 | mir.reset(); | ||
763 | 63 | } | ||
764 | 64 | |||
765 | 65 | bool | ||
766 | 66 | OverlayTrackerMir::addOverlay (const char * appid, unsigned long pid, const char * url) | ||
767 | 67 | { | ||
768 | 68 | std::string sappid(appid); | ||
769 | 69 | std::string surl(url); | ||
770 | 70 | |||
771 | 71 | return thread.executeOnThread<bool>([this, sappid, pid, surl] { | ||
772 | 72 | g_debug("Setting up over lay for PID %d with '%s'", pid, sappid.c_str()); | ||
773 | 73 | |||
774 | 74 | auto session = std::shared_ptr<MirPromptSession>( | ||
775 | 75 | mir_connection_create_prompt_session_sync(mir.get(), pid, sessionStateChangedStatic, this), | ||
776 | 76 | [] (MirPromptSession * session) { if (session) mir_prompt_session_release_sync(session); }); | ||
777 | 77 | if (!session) { | ||
778 | 78 | g_critical("Unable to create trusted prompt session for %d with appid '%s'", pid, sappid.c_str()); | ||
779 | 79 | return false; | ||
780 | 80 | } | ||
781 | 81 | |||
782 | 82 | std::array<const char *, 2> urls { surl.c_str(), nullptr }; | ||
783 | 83 | auto instance = ubuntu_app_launch_start_session_helper(HELPER_TYPE, session.get(), sappid.c_str(), urls.data()); | ||
784 | 84 | if (instance == nullptr) { | ||
785 | 85 | g_critical("Unable to start helper for %d with appid '%s'", pid, sappid.c_str()); | ||
786 | 86 | return false; | ||
787 | 87 | } | ||
788 | 88 | |||
789 | 89 | ongoingSessions.emplace(std::make_tuple(sappid, std::string(instance), session)); | ||
790 | 90 | g_free(instance); | ||
791 | 91 | return true; | ||
792 | 92 | }); | ||
793 | 93 | } | ||
794 | 94 | |||
795 | 95 | void | ||
796 | 96 | OverlayTrackerMir::sessionStateChangedStatic (MirPromptSession * session, MirPromptSessionState state, void * user_data) | ||
797 | 97 | { | ||
798 | 98 | reinterpret_cast<OverlayTrackerMir *>(user_data)->sessionStateChanged(session, state); | ||
799 | 99 | } | ||
800 | 100 | |||
801 | 101 | void | ||
802 | 102 | OverlayTrackerMir::removeSession (MirPromptSession * session) | ||
803 | 103 | { | ||
804 | 104 | for (auto it = ongoingSessions.begin(); it != ongoingSessions.end(); it++) { | ||
805 | 105 | if (std::get<2>(*it).get() == session) { | ||
806 | 106 | ubuntu_app_launch_stop_multiple_helper(HELPER_TYPE, std::get<0>(*it).c_str(), std::get<1>(*it).c_str()); | ||
807 | 107 | ongoingSessions.erase(it); | ||
808 | 108 | break; | ||
809 | 109 | } | ||
810 | 110 | } | ||
811 | 111 | } | ||
812 | 112 | |||
813 | 113 | void | ||
814 | 114 | OverlayTrackerMir::sessionStateChanged (MirPromptSession * session, MirPromptSessionState state) | ||
815 | 115 | { | ||
816 | 116 | if (state != mir_prompt_session_state_stopped) { | ||
817 | 117 | /* We only care about the stopped state */ | ||
818 | 118 | return; | ||
819 | 119 | } | ||
820 | 120 | |||
821 | 121 | /* Executing on the Mir thread, which is nice and all, but we | ||
822 | 122 | want to get back on our thread */ | ||
823 | 123 | thread.executeOnThread([this, session]() { | ||
824 | 124 | removeSession(session); | ||
825 | 125 | }); | ||
826 | 126 | } | ||
827 | 127 | |||
828 | 128 | void | ||
829 | 129 | OverlayTrackerMir::untrustedHelperStoppedStatic (const gchar * appid, const gchar * instanceid, const gchar * helpertype, gpointer user_data) | ||
830 | 130 | { | ||
831 | 131 | reinterpret_cast<OverlayTrackerMir *>(user_data)->untrustedHelperStopped(appid, instanceid, helpertype); | ||
832 | 132 | } | ||
833 | 133 | |||
834 | 134 | void | ||
835 | 135 | OverlayTrackerMir::untrustedHelperStopped(const gchar * appid, const gchar * instanceid, const gchar * helpertype) | ||
836 | 136 | { | ||
837 | 137 | /* This callback will happen on our thread already, we don't need | ||
838 | 138 | to proxy it on */ | ||
839 | 139 | if (g_strcmp0(helpertype, HELPER_TYPE) != 0) { | ||
840 | 140 | return; | ||
841 | 141 | } | ||
842 | 142 | |||
843 | 143 | /* Making the code in the loop easier to read by using std::string outside */ | ||
844 | 144 | std::string sappid(appid); | ||
845 | 145 | std::string sinstanceid(instanceid); | ||
846 | 146 | |||
847 | 147 | for (auto it = ongoingSessions.begin(); it != ongoingSessions.end(); it++) { | ||
848 | 148 | if (std::get<0>(*it) == sappid && std::get<1>(*it) == sinstanceid) { | ||
849 | 149 | ongoingSessions.erase(it); | ||
850 | 150 | break; | ||
851 | 151 | } | ||
852 | 152 | } | ||
853 | 153 | } | ||
854 | 0 | 154 | ||
855 | === added file 'service/overlay-tracker-mir.h' | |||
856 | --- service/overlay-tracker-mir.h 1970-01-01 00:00:00 +0000 | |||
857 | +++ service/overlay-tracker-mir.h 2015-06-12 15:51:31 +0000 | |||
858 | @@ -0,0 +1,49 @@ | |||
859 | 1 | /* | ||
860 | 2 | * Copyright © 2015 Canonical Ltd. | ||
861 | 3 | * | ||
862 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
863 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
864 | 6 | * by the Free Software Foundation. | ||
865 | 7 | * | ||
866 | 8 | * This program is distributed in the hope that it will be useful, but | ||
867 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
868 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
869 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
870 | 12 | * | ||
871 | 13 | * You should have received a copy of the GNU General Public License along | ||
872 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
873 | 15 | * | ||
874 | 16 | * Authors: | ||
875 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
876 | 18 | */ | ||
877 | 19 | |||
878 | 20 | #pragma once | ||
879 | 21 | |||
880 | 22 | #include <set> | ||
881 | 23 | |||
882 | 24 | #include <mir_toolkit/mir_connection.h> | ||
883 | 25 | #include <mir_toolkit/mir_prompt_session.h> | ||
884 | 26 | |||
885 | 27 | #include "glib-thread.h" | ||
886 | 28 | #include "overlay-tracker-iface.h" | ||
887 | 29 | |||
888 | 30 | class OverlayTrackerMir : public OverlayTrackerIface { | ||
889 | 31 | private: | ||
890 | 32 | GLib::ContextThread thread; | ||
891 | 33 | std::shared_ptr<MirConnection> mir; | ||
892 | 34 | std::set<std::tuple<std::string, std::string, std::shared_ptr<MirPromptSession>>> ongoingSessions; | ||
893 | 35 | |||
894 | 36 | public: | ||
895 | 37 | OverlayTrackerMir (); | ||
896 | 38 | ~OverlayTrackerMir (); | ||
897 | 39 | bool addOverlay (const char * appid, unsigned long pid, const char * url) override; | ||
898 | 40 | |||
899 | 41 | private: | ||
900 | 42 | void removeSession (MirPromptSession * session); | ||
901 | 43 | |||
902 | 44 | static void sessionStateChangedStatic (MirPromptSession * session, MirPromptSessionState state, void * user_data); | ||
903 | 45 | void sessionStateChanged (MirPromptSession * session, MirPromptSessionState state); | ||
904 | 46 | |||
905 | 47 | static void untrustedHelperStoppedStatic (const gchar * appid, const gchar * instanceid, const gchar * helpertype, gpointer user_data); | ||
906 | 48 | void untrustedHelperStopped(const gchar * appid, const gchar * instanceid, const gchar * helpertype); | ||
907 | 49 | }; | ||
908 | 0 | 50 | ||
909 | === added file 'service/overlay-tracker.cpp' | |||
910 | --- service/overlay-tracker.cpp 1970-01-01 00:00:00 +0000 | |||
911 | +++ service/overlay-tracker.cpp 2015-06-12 15:51:31 +0000 | |||
912 | @@ -0,0 +1,54 @@ | |||
913 | 1 | /* | ||
914 | 2 | * Copyright © 2015 Canonical Ltd. | ||
915 | 3 | * | ||
916 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
917 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
918 | 6 | * by the Free Software Foundation. | ||
919 | 7 | * | ||
920 | 8 | * This program is distributed in the hope that it will be useful, but | ||
921 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
922 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
923 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
924 | 12 | * | ||
925 | 13 | * You should have received a copy of the GNU General Public License along | ||
926 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
927 | 15 | * | ||
928 | 16 | * Authors: | ||
929 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
930 | 18 | */ | ||
931 | 19 | |||
932 | 20 | extern "C" { | ||
933 | 21 | #include "overlay-tracker.h" | ||
934 | 22 | } | ||
935 | 23 | |||
936 | 24 | #include "overlay-tracker-iface.h" | ||
937 | 25 | #include "overlay-tracker-mir.h" | ||
938 | 26 | |||
939 | 27 | OverlayTracker * | ||
940 | 28 | overlay_tracker_new () { | ||
941 | 29 | try { | ||
942 | 30 | OverlayTrackerMir * cpptracker = new OverlayTrackerMir(); | ||
943 | 31 | return reinterpret_cast<OverlayTracker *>(cpptracker); | ||
944 | 32 | } catch (...) { | ||
945 | 33 | return nullptr; | ||
946 | 34 | } | ||
947 | 35 | } | ||
948 | 36 | |||
949 | 37 | void | ||
950 | 38 | overlay_tracker_delete (OverlayTracker * tracker) { | ||
951 | 39 | g_return_if_fail(tracker != nullptr); | ||
952 | 40 | |||
953 | 41 | auto cpptracker = reinterpret_cast<OverlayTrackerMir *>(tracker); | ||
954 | 42 | delete cpptracker; | ||
955 | 43 | return; | ||
956 | 44 | } | ||
957 | 45 | |||
958 | 46 | gboolean | ||
959 | 47 | overlay_tracker_add (OverlayTracker * tracker, const char * appid, unsigned long pid, const gchar * url) { | ||
960 | 48 | g_return_val_if_fail(tracker != nullptr, FALSE); | ||
961 | 49 | g_return_val_if_fail(appid != nullptr, FALSE); | ||
962 | 50 | g_return_val_if_fail(pid != 0, FALSE); | ||
963 | 51 | g_return_val_if_fail(url != nullptr, FALSE); | ||
964 | 52 | |||
965 | 53 | return reinterpret_cast<OverlayTrackerIface *>(tracker)->addOverlay(appid, pid, url) ? TRUE : FALSE; | ||
966 | 54 | } | ||
967 | 0 | 55 | ||
968 | === added file 'service/overlay-tracker.h' | |||
969 | --- service/overlay-tracker.h 1970-01-01 00:00:00 +0000 | |||
970 | +++ service/overlay-tracker.h 2015-06-12 15:51:31 +0000 | |||
971 | @@ -0,0 +1,28 @@ | |||
972 | 1 | /* | ||
973 | 2 | * Copyright © 2015 Canonical Ltd. | ||
974 | 3 | * | ||
975 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
976 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
977 | 6 | * by the Free Software Foundation. | ||
978 | 7 | * | ||
979 | 8 | * This program is distributed in the hope that it will be useful, but | ||
980 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
981 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
982 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
983 | 12 | * | ||
984 | 13 | * You should have received a copy of the GNU General Public License along | ||
985 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
986 | 15 | * | ||
987 | 16 | * Authors: | ||
988 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
989 | 18 | */ | ||
990 | 19 | |||
991 | 20 | #pragma once | ||
992 | 21 | #include <glib.h> | ||
993 | 22 | |||
994 | 23 | typedef struct _OverlayTracker OverlayTracker; | ||
995 | 24 | |||
996 | 25 | OverlayTracker * overlay_tracker_new (); | ||
997 | 26 | void overlay_tracker_delete (OverlayTracker * tracker); | ||
998 | 27 | gboolean overlay_tracker_add (OverlayTracker * tracker, const char * appid, unsigned long pid, const char * url); | ||
999 | 28 | |||
1000 | 0 | 29 | ||
1001 | === modified file 'service/recoverable-problem.c' | |||
1002 | --- service/recoverable-problem.c 2014-05-27 16:51:53 +0000 | |||
1003 | +++ service/recoverable-problem.c 2015-06-12 15:51:31 +0000 | |||
1004 | @@ -63,6 +63,12 @@ | |||
1005 | 63 | void | 63 | void |
1006 | 64 | report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, const gchar * additional_properties[]) | 64 | report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, const gchar * additional_properties[]) |
1007 | 65 | { | 65 | { |
1008 | 66 | /* Allow disabling for testing, we don't want to report bugs on | ||
1009 | 67 | our tests ;-) */ | ||
1010 | 68 | if (G_UNLIKELY(g_getenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR") != NULL)) { | ||
1011 | 69 | return; | ||
1012 | 70 | } | ||
1013 | 71 | |||
1014 | 66 | GError * error = NULL; | 72 | GError * error = NULL; |
1015 | 67 | gint error_stdin = 0; | 73 | gint error_stdin = 0; |
1016 | 68 | GPid pid = 0; | 74 | GPid pid = 0; |
1017 | 69 | 75 | ||
1018 | === modified file 'service/service.c' | |||
1019 | --- service/service.c 2014-03-14 19:50:37 +0000 | |||
1020 | +++ service/service.c 2015-06-12 15:51:31 +0000 | |||
1021 | @@ -39,13 +39,15 @@ | |||
1022 | 39 | 39 | ||
1023 | 40 | guint term_source = g_unix_signal_add(SIGTERM, sig_term, mainloop); | 40 | guint term_source = g_unix_signal_add(SIGTERM, sig_term, mainloop); |
1024 | 41 | 41 | ||
1026 | 42 | dispatcher_init(mainloop); | 42 | OverlayTracker * tracker = overlay_tracker_new(); |
1027 | 43 | dispatcher_init(mainloop, tracker); | ||
1028 | 43 | 44 | ||
1029 | 44 | /* Run Main */ | 45 | /* Run Main */ |
1030 | 45 | g_main_loop_run(mainloop); | 46 | g_main_loop_run(mainloop); |
1031 | 46 | 47 | ||
1032 | 47 | /* Clean up globals */ | 48 | /* Clean up globals */ |
1033 | 48 | dispatcher_shutdown(); | 49 | dispatcher_shutdown(); |
1034 | 50 | overlay_tracker_delete(tracker); | ||
1035 | 49 | g_source_remove(term_source); | 51 | g_source_remove(term_source); |
1036 | 50 | g_main_loop_unref(mainloop); | 52 | g_main_loop_unref(mainloop); |
1037 | 51 | 53 | ||
1038 | 52 | 54 | ||
1039 | === modified file 'service/url-db.c' | |||
1040 | --- service/url-db.c 2014-10-31 15:51:23 +0000 | |||
1041 | +++ service/url-db.c 2015-06-12 15:51:31 +0000 | |||
1042 | @@ -24,7 +24,7 @@ | |||
1043 | 24 | #define DB_SCHEMA_VERSION "1" | 24 | #define DB_SCHEMA_VERSION "1" |
1044 | 25 | 25 | ||
1045 | 26 | sqlite3 * | 26 | sqlite3 * |
1047 | 27 | url_db_create_database (void) | 27 | url_db_create_database () |
1048 | 28 | { | 28 | { |
1049 | 29 | const gchar * cachedir = g_getenv("URL_DISPATCHER_CACHE_DIR"); /* Mostly for testing */ | 29 | const gchar * cachedir = g_getenv("URL_DISPATCHER_CACHE_DIR"); /* Mostly for testing */ |
1050 | 30 | 30 | ||
1051 | 31 | 31 | ||
1052 | === modified file 'service/url-db.h' | |||
1053 | --- service/url-db.h 2014-10-24 18:55:11 +0000 | |||
1054 | +++ service/url-db.h 2015-06-12 15:51:31 +0000 | |||
1055 | @@ -25,7 +25,7 @@ | |||
1056 | 25 | 25 | ||
1057 | 26 | G_BEGIN_DECLS | 26 | G_BEGIN_DECLS |
1058 | 27 | 27 | ||
1060 | 28 | sqlite3 * url_db_create_database (void); | 28 | sqlite3 * url_db_create_database (); |
1061 | 29 | gboolean url_db_get_file_motification_time (sqlite3 * db, | 29 | gboolean url_db_get_file_motification_time (sqlite3 * db, |
1062 | 30 | const gchar * filename, | 30 | const gchar * filename, |
1063 | 31 | GTimeVal * timeval); | 31 | GTimeVal * timeval); |
1064 | 32 | 32 | ||
1065 | === added file 'service/url-overlay.c' | |||
1066 | --- service/url-overlay.c 1970-01-01 00:00:00 +0000 | |||
1067 | +++ service/url-overlay.c 2015-06-12 15:51:31 +0000 | |||
1068 | @@ -0,0 +1,174 @@ | |||
1069 | 1 | /* | ||
1070 | 2 | * Copyright © 2014 Canonical Ltd. | ||
1071 | 3 | * | ||
1072 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1073 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1074 | 6 | * by the Free Software Foundation. | ||
1075 | 7 | * | ||
1076 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1077 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1078 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1079 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1080 | 12 | * | ||
1081 | 13 | * You should have received a copy of the GNU General Public License along | ||
1082 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1083 | 15 | * | ||
1084 | 16 | * Authors: | ||
1085 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
1086 | 18 | */ | ||
1087 | 19 | |||
1088 | 20 | #include <glib.h> | ||
1089 | 21 | #include <click.h> | ||
1090 | 22 | #include <ubuntu-app-launch.h> | ||
1091 | 23 | |||
1092 | 24 | #include "recoverable-problem.h" | ||
1093 | 25 | |||
1094 | 26 | gchar * | ||
1095 | 27 | build_exec (const gchar * appid, const gchar * directory) | ||
1096 | 28 | { | ||
1097 | 29 | gchar * appid_desktop = g_strdup_printf("%s.desktop", appid); | ||
1098 | 30 | gchar * desktopfilepath = g_build_filename(directory, appid_desktop, NULL); | ||
1099 | 31 | g_free(appid_desktop); | ||
1100 | 32 | |||
1101 | 33 | if (!g_file_test(desktopfilepath, G_FILE_TEST_EXISTS)) { | ||
1102 | 34 | g_free(desktopfilepath); | ||
1103 | 35 | return NULL; | ||
1104 | 36 | } | ||
1105 | 37 | |||
1106 | 38 | GError * error = NULL; | ||
1107 | 39 | GKeyFile * keyfile = g_key_file_new(); | ||
1108 | 40 | g_key_file_load_from_file(keyfile, desktopfilepath, G_KEY_FILE_NONE, &error); | ||
1109 | 41 | |||
1110 | 42 | if (error != NULL) { | ||
1111 | 43 | g_error("Unable to read url-overlay desktop file '%s': %s", desktopfilepath, error->message); | ||
1112 | 44 | g_free(desktopfilepath); | ||
1113 | 45 | g_key_file_free(keyfile); | ||
1114 | 46 | g_error_free(error); | ||
1115 | 47 | return NULL; | ||
1116 | 48 | } | ||
1117 | 49 | |||
1118 | 50 | g_free(desktopfilepath); | ||
1119 | 51 | |||
1120 | 52 | if (!g_key_file_has_key(keyfile, "Desktop Entry", "Exec", NULL)) { | ||
1121 | 53 | g_error("Desktop file for '%s' in '%s' does not have 'Exec' key", appid, directory); | ||
1122 | 54 | g_key_file_free(keyfile); | ||
1123 | 55 | return NULL; | ||
1124 | 56 | } | ||
1125 | 57 | |||
1126 | 58 | gchar * exec = g_key_file_get_string(keyfile, "Desktop Entry", "Exec", NULL); | ||
1127 | 59 | g_key_file_free(keyfile); | ||
1128 | 60 | |||
1129 | 61 | return exec; | ||
1130 | 62 | } | ||
1131 | 63 | |||
1132 | 64 | gchar * | ||
1133 | 65 | build_dir (const gchar * appid) | ||
1134 | 66 | { | ||
1135 | 67 | GError * error = NULL; | ||
1136 | 68 | gchar * package = NULL; | ||
1137 | 69 | |||
1138 | 70 | /* 'Parse' the App ID */ | ||
1139 | 71 | if (!ubuntu_app_launch_app_id_parse(appid, &package, NULL, NULL)) { | ||
1140 | 72 | g_warning("Unable to parse App ID: '%s'", appid); | ||
1141 | 73 | return NULL; | ||
1142 | 74 | } | ||
1143 | 75 | |||
1144 | 76 | /* Check click to find out where the files are */ | ||
1145 | 77 | ClickDB * db = click_db_new(); | ||
1146 | 78 | |||
1147 | 79 | /* If TEST_CLICK_DB is unset, this reads the system database. */ | ||
1148 | 80 | click_db_read(db, g_getenv("TEST_CLICK_DB"), &error); | ||
1149 | 81 | if (error != NULL) { | ||
1150 | 82 | g_warning("Unable to read Click database: %s", error->message); | ||
1151 | 83 | g_error_free(error); | ||
1152 | 84 | g_free(package); | ||
1153 | 85 | return NULL; | ||
1154 | 86 | } | ||
1155 | 87 | |||
1156 | 88 | /* If TEST_CLICK_USER is unset, this uses the current user name. */ | ||
1157 | 89 | ClickUser * user = click_user_new_for_user(db, g_getenv("TEST_CLICK_USER"), &error); | ||
1158 | 90 | if (error != NULL) { | ||
1159 | 91 | g_warning("Unable to read Click database: %s", error->message); | ||
1160 | 92 | g_error_free(error); | ||
1161 | 93 | g_free(package); | ||
1162 | 94 | g_object_unref(db); | ||
1163 | 95 | return NULL; | ||
1164 | 96 | } | ||
1165 | 97 | |||
1166 | 98 | gchar * pkgdir = click_user_get_path(user, package, &error); | ||
1167 | 99 | |||
1168 | 100 | g_object_unref(user); | ||
1169 | 101 | g_object_unref(db); | ||
1170 | 102 | g_free(package); | ||
1171 | 103 | |||
1172 | 104 | if (error != NULL) { | ||
1173 | 105 | g_warning("Unable to get the Click package directory for %s: %s", package, error->message); | ||
1174 | 106 | g_error_free(error); | ||
1175 | 107 | return NULL; | ||
1176 | 108 | } | ||
1177 | 109 | |||
1178 | 110 | return pkgdir; | ||
1179 | 111 | } | ||
1180 | 112 | |||
1181 | 113 | int | ||
1182 | 114 | main (int argc, char * argv[]) | ||
1183 | 115 | { | ||
1184 | 116 | /* Build up our exec */ | ||
1185 | 117 | const gchar * appid = g_getenv("APP_ID"); | ||
1186 | 118 | if (appid == NULL) { | ||
1187 | 119 | report_recoverable_problem("url-dispatcher-url-overlay-no-appid", 0, TRUE, NULL); | ||
1188 | 120 | return -1; | ||
1189 | 121 | } | ||
1190 | 122 | |||
1191 | 123 | gchar * exec = NULL; | ||
1192 | 124 | |||
1193 | 125 | /* Allow for environment override */ | ||
1194 | 126 | const gchar * envdir = g_getenv("URL_DISPATCHER_OVERLAY_DIR"); | ||
1195 | 127 | if (G_UNLIKELY(envdir != NULL)) { /* Mostly for testing */ | ||
1196 | 128 | exec = build_exec(appid, envdir); | ||
1197 | 129 | } | ||
1198 | 130 | |||
1199 | 131 | /* Try the system directory */ | ||
1200 | 132 | if (exec == NULL) { | ||
1201 | 133 | exec = build_exec(appid, OVERLAY_SYSTEM_DIRECTORY); | ||
1202 | 134 | } | ||
1203 | 135 | |||
1204 | 136 | /* If not there look to the user directory (click) */ | ||
1205 | 137 | if (exec == NULL) { | ||
1206 | 138 | gchar * userdir = g_build_filename(g_get_user_cache_dir(), "url-dispatcher", "url-overlays", NULL); | ||
1207 | 139 | exec = build_exec(appid, userdir); | ||
1208 | 140 | g_free(userdir); | ||
1209 | 141 | } | ||
1210 | 142 | |||
1211 | 143 | if (exec == NULL) { | ||
1212 | 144 | const gchar * props[3] = { | ||
1213 | 145 | "AppID", | ||
1214 | 146 | appid, | ||
1215 | 147 | NULL | ||
1216 | 148 | }; | ||
1217 | 149 | |||
1218 | 150 | report_recoverable_problem("url-dispatcher-url-overlay-bad-appid", 0, TRUE, props); | ||
1219 | 151 | return -1; | ||
1220 | 152 | } | ||
1221 | 153 | |||
1222 | 154 | gchar * dir = build_dir(appid); | ||
1223 | 155 | /* NOTE: Dir will be NULL for system apps */ | ||
1224 | 156 | |||
1225 | 157 | GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1226 | 158 | g_return_val_if_fail(bus != NULL, -1); | ||
1227 | 159 | |||
1228 | 160 | gboolean sended = ubuntu_app_launch_helper_set_exec(exec, dir); | ||
1229 | 161 | g_free(exec); | ||
1230 | 162 | g_free(dir); | ||
1231 | 163 | |||
1232 | 164 | /* Ensuring the messages get on the bus before we quit */ | ||
1233 | 165 | g_dbus_connection_flush_sync(bus, NULL, NULL); | ||
1234 | 166 | g_clear_object(&bus); | ||
1235 | 167 | |||
1236 | 168 | if (sended) { | ||
1237 | 169 | return 0; | ||
1238 | 170 | } else { | ||
1239 | 171 | g_critical("Unable to send exec to Upstart"); | ||
1240 | 172 | return -1; | ||
1241 | 173 | } | ||
1242 | 174 | } | ||
1243 | 0 | 175 | ||
1244 | === modified file 'tests/CMakeLists.txt' | |||
1245 | --- tests/CMakeLists.txt 2015-01-09 16:11:45 +0000 | |||
1246 | +++ tests/CMakeLists.txt 2015-06-12 15:51:31 +0000 | |||
1247 | @@ -34,6 +34,23 @@ | |||
1248 | 34 | ) | 34 | ) |
1249 | 35 | 35 | ||
1250 | 36 | ########################### | 36 | ########################### |
1251 | 37 | # Mir Mock Lib | ||
1252 | 38 | ########################### | ||
1253 | 39 | |||
1254 | 40 | add_library(mir-mock-lib SHARED | ||
1255 | 41 | mir-mock.h | ||
1256 | 42 | mir-mock.cpp) | ||
1257 | 43 | |||
1258 | 44 | target_link_libraries(mir-mock-lib | ||
1259 | 45 | -pthread | ||
1260 | 46 | ${GLIB2_LIBRARIES} | ||
1261 | 47 | ) | ||
1262 | 48 | |||
1263 | 49 | set_target_properties(mir-mock-lib PROPERTIES | ||
1264 | 50 | OUTPUT_NAME "mir-mock" | ||
1265 | 51 | ) | ||
1266 | 52 | |||
1267 | 53 | ########################### | ||
1268 | 37 | # Dispatcher test | 54 | # Dispatcher test |
1269 | 38 | ########################### | 55 | ########################### |
1270 | 39 | 56 | ||
1271 | @@ -55,7 +72,7 @@ | |||
1272 | 55 | 72 | ||
1273 | 56 | include_directories("${CMAKE_BINARY_DIR}/service") | 73 | include_directories("${CMAKE_BINARY_DIR}/service") |
1274 | 57 | 74 | ||
1276 | 58 | add_executable (app-id-test app-id-test.cc "${CMAKE_SOURCE_DIR}/service/dispatcher.c") | 75 | add_executable (app-id-test app-id-test.cc) |
1277 | 59 | target_link_libraries (app-id-test | 76 | target_link_libraries (app-id-test |
1278 | 60 | dispatcher-lib | 77 | dispatcher-lib |
1279 | 61 | mock-lib | 78 | mock-lib |
1280 | @@ -128,3 +145,32 @@ | |||
1281 | 128 | 145 | ||
1282 | 129 | add_test (url-db-test url-db-test) | 146 | add_test (url-db-test url-db-test) |
1283 | 130 | add_subdirectory(url_dispatcher_testability) | 147 | add_subdirectory(url_dispatcher_testability) |
1284 | 148 | |||
1285 | 149 | ########################### | ||
1286 | 150 | # exec tool test | ||
1287 | 151 | ########################### | ||
1288 | 152 | |||
1289 | 153 | add_executable (exec-tool-test exec-tool-test.cc) | ||
1290 | 154 | target_link_libraries (exec-tool-test | ||
1291 | 155 | gtest | ||
1292 | 156 | ${GTEST_LIBS} | ||
1293 | 157 | ${GIO2_LIBRARIES} | ||
1294 | 158 | ${DBUSTEST_LIBRARIES}) | ||
1295 | 159 | |||
1296 | 160 | add_test (exec-tool-test exec-tool-test) | ||
1297 | 161 | |||
1298 | 162 | ########################### | ||
1299 | 163 | # overlay tracker test | ||
1300 | 164 | ########################### | ||
1301 | 165 | |||
1302 | 166 | add_executable (overlay-tracker-test overlay-tracker-test.cpp) | ||
1303 | 167 | target_link_libraries (overlay-tracker-test | ||
1304 | 168 | dispatcher-lib | ||
1305 | 169 | mir-mock-lib | ||
1306 | 170 | mock-lib | ||
1307 | 171 | gtest | ||
1308 | 172 | ${GTEST_LIBS} | ||
1309 | 173 | ${GIO2_LIBRARIES} | ||
1310 | 174 | ${DBUSTEST_LIBRARIES}) | ||
1311 | 175 | |||
1312 | 176 | add_test (overlay-tracker-test overlay-tracker-test) | ||
1313 | 131 | 177 | ||
1314 | === modified file 'tests/app-id-test.cc' | |||
1315 | --- tests/app-id-test.cc 2014-10-28 09:49:29 +0000 | |||
1316 | +++ tests/app-id-test.cc 2015-06-12 15:51:31 +0000 | |||
1317 | @@ -21,6 +21,7 @@ | |||
1318 | 21 | #include <gtest/gtest.h> | 21 | #include <gtest/gtest.h> |
1319 | 22 | #include "dispatcher.h" | 22 | #include "dispatcher.h" |
1320 | 23 | #include "ubuntu-app-launch-mock.h" | 23 | #include "ubuntu-app-launch-mock.h" |
1321 | 24 | #include "overlay-tracker-mock.h" | ||
1322 | 24 | 25 | ||
1323 | 25 | class AppIdTest : public ::testing::Test | 26 | class AppIdTest : public ::testing::Test |
1324 | 26 | { | 27 | { |
1325 | @@ -28,6 +29,7 @@ | |||
1326 | 28 | GTestDBus * testbus = nullptr; | 29 | GTestDBus * testbus = nullptr; |
1327 | 29 | GMainLoop * mainloop = nullptr; | 30 | GMainLoop * mainloop = nullptr; |
1328 | 30 | gchar * cachedir = nullptr; | 31 | gchar * cachedir = nullptr; |
1329 | 32 | OverlayTrackerMock tracker; | ||
1330 | 31 | 33 | ||
1331 | 32 | protected: | 34 | protected: |
1332 | 33 | virtual void SetUp() { | 35 | virtual void SetUp() { |
1333 | @@ -41,7 +43,7 @@ | |||
1334 | 41 | g_test_dbus_up(testbus); | 43 | g_test_dbus_up(testbus); |
1335 | 42 | 44 | ||
1336 | 43 | mainloop = g_main_loop_new(nullptr, FALSE); | 45 | mainloop = g_main_loop_new(nullptr, FALSE); |
1338 | 44 | dispatcher_init(mainloop); | 46 | dispatcher_init(mainloop, reinterpret_cast<OverlayTracker *>(&tracker)); |
1339 | 45 | 47 | ||
1340 | 46 | return; | 48 | return; |
1341 | 47 | } | 49 | } |
1342 | 48 | 50 | ||
1343 | === modified file 'tests/dispatcher-test.cc' | |||
1344 | --- tests/dispatcher-test.cc 2015-01-09 16:11:45 +0000 | |||
1345 | +++ tests/dispatcher-test.cc 2015-06-12 15:51:31 +0000 | |||
1346 | @@ -21,6 +21,7 @@ | |||
1347 | 21 | #include <gtest/gtest.h> | 21 | #include <gtest/gtest.h> |
1348 | 22 | #include "dispatcher.h" | 22 | #include "dispatcher.h" |
1349 | 23 | #include "ubuntu-app-launch-mock.h" | 23 | #include "ubuntu-app-launch-mock.h" |
1350 | 24 | #include "overlay-tracker-mock.h" | ||
1351 | 24 | #include "url-db.h" | 25 | #include "url-db.h" |
1352 | 25 | 26 | ||
1353 | 26 | class DispatcherTest : public ::testing::Test | 27 | class DispatcherTest : public ::testing::Test |
1354 | @@ -31,9 +32,13 @@ | |||
1355 | 31 | gchar * cachedir = nullptr; | 32 | gchar * cachedir = nullptr; |
1356 | 32 | 33 | ||
1357 | 33 | protected: | 34 | protected: |
1358 | 35 | OverlayTrackerMock tracker; | ||
1359 | 36 | GDBusConnection * session = nullptr; | ||
1360 | 37 | |||
1361 | 34 | virtual void SetUp() { | 38 | virtual void SetUp() { |
1362 | 35 | g_setenv("TEST_CLICK_DB", "click-db", TRUE); | 39 | g_setenv("TEST_CLICK_DB", "click-db", TRUE); |
1363 | 36 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); | 40 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
1364 | 41 | g_setenv("URL_DISPATCHER_OVERLAY_DIR", OVERLAY_TEST_DIR, TRUE); | ||
1365 | 37 | 42 | ||
1366 | 38 | cachedir = g_build_filename(CMAKE_BINARY_DIR, "dispatcher-test-cache", nullptr); | 43 | cachedir = g_build_filename(CMAKE_BINARY_DIR, "dispatcher-test-cache", nullptr); |
1367 | 39 | g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); | 44 | g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); |
1368 | @@ -66,8 +71,10 @@ | |||
1369 | 66 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); | 71 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); |
1370 | 67 | g_test_dbus_up(testbus); | 72 | g_test_dbus_up(testbus); |
1371 | 68 | 73 | ||
1372 | 74 | session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1373 | 75 | |||
1374 | 69 | mainloop = g_main_loop_new(nullptr, FALSE); | 76 | mainloop = g_main_loop_new(nullptr, FALSE); |
1376 | 70 | dispatcher_init(mainloop); | 77 | dispatcher_init(mainloop, reinterpret_cast<OverlayTracker *>(&tracker)); |
1377 | 71 | 78 | ||
1378 | 72 | return; | 79 | return; |
1379 | 73 | } | 80 | } |
1380 | @@ -87,6 +94,8 @@ | |||
1381 | 87 | /* let other threads settle */ | 94 | /* let other threads settle */ |
1382 | 88 | g_usleep(500000); | 95 | g_usleep(500000); |
1383 | 89 | 96 | ||
1384 | 97 | g_clear_object(&session); | ||
1385 | 98 | |||
1386 | 90 | g_test_dbus_down(testbus); | 99 | g_test_dbus_down(testbus); |
1387 | 91 | g_object_unref(testbus); | 100 | g_object_unref(testbus); |
1388 | 92 | 101 | ||
1389 | @@ -250,3 +259,18 @@ | |||
1390 | 250 | 259 | ||
1391 | 251 | return; | 260 | return; |
1392 | 252 | } | 261 | } |
1393 | 262 | |||
1394 | 263 | TEST_F(DispatcherTest, OverlayTest) | ||
1395 | 264 | { | ||
1396 | 265 | EXPECT_TRUE(dispatcher_is_overlay("com.test.good_application_1.2.3")); | ||
1397 | 266 | EXPECT_FALSE(dispatcher_is_overlay("com.test.bad_application_1.2.3")); | ||
1398 | 267 | |||
1399 | 268 | EXPECT_TRUE(dispatcher_send_to_overlay ("com.test.good_application_1.2.3", "overlay://ubuntu.com", session, g_dbus_connection_get_unique_name(session))); | ||
1400 | 269 | |||
1401 | 270 | ASSERT_EQ(1, tracker.addedOverlays.size()); | ||
1402 | 271 | EXPECT_EQ("com.test.good_application_1.2.3", std::get<0>(tracker.addedOverlays[0])); | ||
1403 | 272 | EXPECT_EQ(getpid(), std::get<1>(tracker.addedOverlays[0])); | ||
1404 | 273 | EXPECT_EQ("overlay://ubuntu.com", std::get<2>(tracker.addedOverlays[0])); | ||
1405 | 274 | |||
1406 | 275 | return; | ||
1407 | 276 | } | ||
1408 | 253 | 277 | ||
1409 | === added file 'tests/exec-tool-test.cc' | |||
1410 | --- tests/exec-tool-test.cc 1970-01-01 00:00:00 +0000 | |||
1411 | +++ tests/exec-tool-test.cc 2015-06-12 15:51:31 +0000 | |||
1412 | @@ -0,0 +1,118 @@ | |||
1413 | 1 | /** | ||
1414 | 2 | * Copyright © 2013-2015 Canonical, Ltd. | ||
1415 | 3 | * | ||
1416 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1417 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1418 | 6 | * the Free Software Foundation. | ||
1419 | 7 | * | ||
1420 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1421 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1422 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1423 | 11 | * Lesser General Public License for more details. | ||
1424 | 12 | * | ||
1425 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1426 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1427 | 15 | * | ||
1428 | 16 | */ | ||
1429 | 17 | |||
1430 | 18 | #include "test-config.h" | ||
1431 | 19 | |||
1432 | 20 | #include <gio/gio.h> | ||
1433 | 21 | #include <gtest/gtest.h> | ||
1434 | 22 | #include <libdbustest/dbus-test.h> | ||
1435 | 23 | |||
1436 | 24 | class ExecToolTest : public ::testing::Test | ||
1437 | 25 | { | ||
1438 | 26 | protected: | ||
1439 | 27 | DbusTestService * service = nullptr; | ||
1440 | 28 | DbusTestDbusMock * mock = nullptr; | ||
1441 | 29 | DbusTestDbusMockObject * obj = nullptr; | ||
1442 | 30 | GDBusConnection * bus = nullptr; | ||
1443 | 31 | |||
1444 | 32 | virtual void SetUp() { | ||
1445 | 33 | g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE); | ||
1446 | 34 | g_setenv("URL_DISPATCHER_OVERLAY_DIR", OVERLAY_TEST_DIR, TRUE); | ||
1447 | 35 | |||
1448 | 36 | g_setenv("TEST_CLICK_DB", "click-db", TRUE); | ||
1449 | 37 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); | ||
1450 | 38 | |||
1451 | 39 | service = dbus_test_service_new(nullptr); | ||
1452 | 40 | |||
1453 | 41 | /* Upstart Mock */ | ||
1454 | 42 | mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); | ||
1455 | 43 | obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", nullptr); | ||
1456 | 44 | |||
1457 | 45 | dbus_test_dbus_mock_object_add_method(mock, obj, | ||
1458 | 46 | "SetEnv", | ||
1459 | 47 | G_VARIANT_TYPE("(assb)"), | ||
1460 | 48 | NULL, | ||
1461 | 49 | "", | ||
1462 | 50 | NULL); | ||
1463 | 51 | |||
1464 | 52 | dbus_test_task_set_name(DBUS_TEST_TASK(mock), "Upstart"); | ||
1465 | 53 | dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); | ||
1466 | 54 | |||
1467 | 55 | /* Start your engines! */ | ||
1468 | 56 | dbus_test_service_start_tasks(service); | ||
1469 | 57 | |||
1470 | 58 | bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr); | ||
1471 | 59 | g_dbus_connection_set_exit_on_close(bus, FALSE); | ||
1472 | 60 | g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); | ||
1473 | 61 | return; | ||
1474 | 62 | } | ||
1475 | 63 | |||
1476 | 64 | virtual void TearDown() { | ||
1477 | 65 | /* dbustest should probably do this, not sure */ | ||
1478 | 66 | |||
1479 | 67 | g_clear_object(&mock); | ||
1480 | 68 | g_clear_object(&service); | ||
1481 | 69 | |||
1482 | 70 | g_object_unref(bus); | ||
1483 | 71 | |||
1484 | 72 | unsigned int cleartry = 0; | ||
1485 | 73 | while (bus != nullptr && cleartry < 100) { | ||
1486 | 74 | pause(100); | ||
1487 | 75 | cleartry++; | ||
1488 | 76 | } | ||
1489 | 77 | |||
1490 | 78 | return; | ||
1491 | 79 | } | ||
1492 | 80 | |||
1493 | 81 | static gboolean quit_loop (gpointer ploop) { | ||
1494 | 82 | g_main_loop_quit((GMainLoop *)ploop); | ||
1495 | 83 | return FALSE; | ||
1496 | 84 | } | ||
1497 | 85 | |||
1498 | 86 | void pause (int time) { | ||
1499 | 87 | GMainLoop * loop = g_main_loop_new(nullptr, FALSE); | ||
1500 | 88 | g_timeout_add(time, quit_loop, loop); | ||
1501 | 89 | g_main_loop_run(loop); | ||
1502 | 90 | g_main_loop_unref(loop); | ||
1503 | 91 | } | ||
1504 | 92 | }; | ||
1505 | 93 | |||
1506 | 94 | TEST_F(ExecToolTest, SetOverlay) | ||
1507 | 95 | { | ||
1508 | 96 | g_unsetenv("APP_ID"); | ||
1509 | 97 | gint retval = 0; | ||
1510 | 98 | EXPECT_TRUE(g_spawn_command_line_sync(EXEC_TOOL, nullptr, nullptr, &retval, nullptr)); | ||
1511 | 99 | EXPECT_NE(0, retval); | ||
1512 | 100 | |||
1513 | 101 | g_setenv("APP_ID", "com.test.good_application_1.2.3", TRUE); | ||
1514 | 102 | g_setenv("UPSTART_JOB", "fubar", TRUE); | ||
1515 | 103 | EXPECT_TRUE(g_spawn_command_line_sync(EXEC_TOOL, nullptr, nullptr, &retval, nullptr)); | ||
1516 | 104 | EXPECT_EQ(0, retval); | ||
1517 | 105 | |||
1518 | 106 | guint len = 0; | ||
1519 | 107 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL); | ||
1520 | 108 | ASSERT_NE(nullptr, calls); | ||
1521 | 109 | ASSERT_EQ(2, len); | ||
1522 | 110 | |||
1523 | 111 | GVariant * appexecenv = g_variant_get_child_value(calls[0].params, 1); | ||
1524 | 112 | EXPECT_STREQ("APP_EXEC=foobar", g_variant_get_string(appexecenv, nullptr)); | ||
1525 | 113 | g_variant_unref(appexecenv); | ||
1526 | 114 | |||
1527 | 115 | GVariant * appdirenv = g_variant_get_child_value(calls[1].params, 1); | ||
1528 | 116 | EXPECT_STREQ("APP_DIR=" CLICK_DATA_DIR "/.click/users/test-user/com.test.good", g_variant_get_string(appdirenv, nullptr)); | ||
1529 | 117 | g_variant_unref(appdirenv); | ||
1530 | 118 | } | ||
1531 | 0 | 119 | ||
1532 | === added file 'tests/mir-mock.cpp' | |||
1533 | --- tests/mir-mock.cpp 1970-01-01 00:00:00 +0000 | |||
1534 | +++ tests/mir-mock.cpp 2015-06-12 15:51:31 +0000 | |||
1535 | @@ -0,0 +1,124 @@ | |||
1536 | 1 | /** | ||
1537 | 2 | * Copyright © 2015 Canonical, Ltd. | ||
1538 | 3 | * | ||
1539 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1540 | 5 | * the terms of the GNU General Public License version 3, as published by | ||
1541 | 6 | * the Free Software Foundation. | ||
1542 | 7 | * * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1543 | 8 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1544 | 9 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1545 | 10 | * General Public License for more details. | ||
1546 | 11 | * | ||
1547 | 12 | * You should have received a copy of the GNU General Public License | ||
1548 | 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1549 | 14 | * | ||
1550 | 15 | */ | ||
1551 | 16 | |||
1552 | 17 | #include "mir-mock.h" | ||
1553 | 18 | |||
1554 | 19 | #include <vector> | ||
1555 | 20 | #include <iostream> | ||
1556 | 21 | #include <thread> | ||
1557 | 22 | |||
1558 | 23 | MirPromptSession * mir_mock_valid_trust_session = (MirPromptSession *)"In the circle of trust"; | ||
1559 | 24 | static bool valid_trust_connection = true; | ||
1560 | 25 | static int trusted_fd = 1234; | ||
1561 | 26 | MirPromptSession * mir_mock_last_released_session = NULL; | ||
1562 | 27 | pid_t mir_mock_last_trust_pid = 0; | ||
1563 | 28 | void (*mir_mock_last_trust_func)(MirPromptSession *, MirPromptSessionState, void*data) = NULL; | ||
1564 | 29 | void * mir_mock_last_trust_data = NULL; | ||
1565 | 30 | |||
1566 | 31 | MirPromptSession * | ||
1567 | 32 | mir_connection_create_prompt_session_sync(MirConnection *, pid_t pid, void (*func)(MirPromptSession *, MirPromptSessionState, void*data), void * context) { | ||
1568 | 33 | mir_mock_last_trust_pid = pid; | ||
1569 | 34 | mir_mock_last_trust_func = func; | ||
1570 | 35 | mir_mock_last_trust_data = context; | ||
1571 | 36 | |||
1572 | 37 | if (valid_trust_connection) { | ||
1573 | 38 | return mir_mock_valid_trust_session; | ||
1574 | 39 | } else { | ||
1575 | 40 | return nullptr; | ||
1576 | 41 | } | ||
1577 | 42 | } | ||
1578 | 43 | |||
1579 | 44 | void | ||
1580 | 45 | mir_prompt_session_release_sync (MirPromptSession * session) | ||
1581 | 46 | { | ||
1582 | 47 | mir_mock_last_released_session = session; | ||
1583 | 48 | if (session != mir_mock_valid_trust_session) { | ||
1584 | 49 | std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl; | ||
1585 | 50 | exit(1); | ||
1586 | 51 | } | ||
1587 | 52 | } | ||
1588 | 53 | |||
1589 | 54 | MirWaitHandle * | ||
1590 | 55 | mir_prompt_session_new_fds_for_prompt_providers (MirPromptSession * session, unsigned int numfds, mir_client_fd_callback cb, void * data) { | ||
1591 | 56 | if (session != mir_mock_valid_trust_session) { | ||
1592 | 57 | std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl; | ||
1593 | 58 | exit(1); | ||
1594 | 59 | } | ||
1595 | 60 | |||
1596 | 61 | std::thread * thread = new std::thread([session, numfds, cb, data]() { | ||
1597 | 62 | std::vector<int> fdlist(numfds); | ||
1598 | 63 | |||
1599 | 64 | for (unsigned int i = 0; i < numfds; i++) | ||
1600 | 65 | fdlist[i] = trusted_fd; | ||
1601 | 66 | |||
1602 | 67 | cb(session, numfds, fdlist.data(), data); | ||
1603 | 68 | }); | ||
1604 | 69 | |||
1605 | 70 | return reinterpret_cast<MirWaitHandle *>(thread); | ||
1606 | 71 | } | ||
1607 | 72 | |||
1608 | 73 | void | ||
1609 | 74 | mir_wait_for (MirWaitHandle * wait) | ||
1610 | 75 | { | ||
1611 | 76 | auto thread = reinterpret_cast<std::thread *>(wait); | ||
1612 | 77 | |||
1613 | 78 | if (thread->joinable()) | ||
1614 | 79 | thread->join(); | ||
1615 | 80 | |||
1616 | 81 | delete thread; | ||
1617 | 82 | } | ||
1618 | 83 | |||
1619 | 84 | static const char * valid_connection_str = "Valid Mir Connection"; | ||
1620 | 85 | static std::pair<std::string, std::string> last_connection; | ||
1621 | 86 | static bool valid_connection = true; | ||
1622 | 87 | |||
1623 | 88 | void | ||
1624 | 89 | mir_mock_connect_return_valid (bool valid) | ||
1625 | 90 | { | ||
1626 | 91 | valid_connection = valid; | ||
1627 | 92 | } | ||
1628 | 93 | |||
1629 | 94 | std::pair<std::string, std::string> | ||
1630 | 95 | mir_mock_connect_last_connect () | ||
1631 | 96 | { | ||
1632 | 97 | return last_connection; | ||
1633 | 98 | } | ||
1634 | 99 | |||
1635 | 100 | MirConnection * | ||
1636 | 101 | mir_connect_sync (char const * server, char const * appname) | ||
1637 | 102 | { | ||
1638 | 103 | last_connection = std::pair<std::string, std::string>(server, appname); | ||
1639 | 104 | |||
1640 | 105 | if (valid_connection) { | ||
1641 | 106 | return (MirConnection *)(valid_connection_str); | ||
1642 | 107 | } else { | ||
1643 | 108 | return nullptr; | ||
1644 | 109 | } | ||
1645 | 110 | } | ||
1646 | 111 | |||
1647 | 112 | void | ||
1648 | 113 | mir_connection_release (MirConnection * con) | ||
1649 | 114 | { | ||
1650 | 115 | if (reinterpret_cast<char *>(con) != valid_connection_str) { | ||
1651 | 116 | std::cerr << "Releasing a Mir Connection that isn't valid" << std::endl; | ||
1652 | 117 | exit(1); | ||
1653 | 118 | } | ||
1654 | 119 | } | ||
1655 | 120 | |||
1656 | 121 | void mir_mock_set_trusted_fd (int fd) | ||
1657 | 122 | { | ||
1658 | 123 | trusted_fd = fd; | ||
1659 | 124 | } | ||
1660 | 0 | 125 | ||
1661 | === added file 'tests/mir-mock.h' | |||
1662 | --- tests/mir-mock.h 1970-01-01 00:00:00 +0000 | |||
1663 | +++ tests/mir-mock.h 2015-06-12 15:51:31 +0000 | |||
1664 | @@ -0,0 +1,36 @@ | |||
1665 | 1 | /** | ||
1666 | 2 | * Copyright © 2015 Canonical, Ltd. | ||
1667 | 3 | * | ||
1668 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1669 | 5 | * the terms of the GNU General Public License version 3, as published by | ||
1670 | 6 | * the Free Software Foundation. | ||
1671 | 7 | * * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1672 | 8 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1673 | 9 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1674 | 10 | * General Public License for more details. | ||
1675 | 11 | * | ||
1676 | 12 | * You should have received a copy of the GNU General Public License | ||
1677 | 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1678 | 14 | * | ||
1679 | 15 | */ | ||
1680 | 16 | |||
1681 | 17 | #ifndef MIR_MOCK_H | ||
1682 | 18 | #define MIR_MOCK_H 1 | ||
1683 | 19 | |||
1684 | 20 | #include <string> | ||
1685 | 21 | #include <utility> | ||
1686 | 22 | |||
1687 | 23 | #include <mir_toolkit/mir_connection.h> | ||
1688 | 24 | #include <mir_toolkit/mir_prompt_session.h> | ||
1689 | 25 | |||
1690 | 26 | void mir_mock_connect_return_valid (bool valid); | ||
1691 | 27 | std::pair<std::string, std::string> mir_mock_connect_last_connect (); | ||
1692 | 28 | void mir_mock_set_trusted_fd (int fd); | ||
1693 | 29 | |||
1694 | 30 | extern MirPromptSession * mir_mock_valid_trust_session; | ||
1695 | 31 | extern MirPromptSession * mir_mock_last_released_session; | ||
1696 | 32 | extern pid_t mir_mock_last_trust_pid; | ||
1697 | 33 | extern void (*mir_mock_last_trust_func)(MirPromptSession *, MirPromptSessionState, void*data); | ||
1698 | 34 | extern void * mir_mock_last_trust_data; | ||
1699 | 35 | |||
1700 | 36 | #endif // MIR_MOCK_H | ||
1701 | 0 | 37 | ||
1702 | === added directory 'tests/overlay-dir' | |||
1703 | === added file 'tests/overlay-dir/com.test.good_application_1.2.3.desktop' | |||
1704 | --- tests/overlay-dir/com.test.good_application_1.2.3.desktop 1970-01-01 00:00:00 +0000 | |||
1705 | +++ tests/overlay-dir/com.test.good_application_1.2.3.desktop 2015-06-12 15:51:31 +0000 | |||
1706 | @@ -0,0 +1,2 @@ | |||
1707 | 1 | [Desktop Entry] | ||
1708 | 2 | Exec=foobar | ||
1709 | 0 | 3 | ||
1710 | === added file 'tests/overlay-tracker-mock.h' | |||
1711 | --- tests/overlay-tracker-mock.h 1970-01-01 00:00:00 +0000 | |||
1712 | +++ tests/overlay-tracker-mock.h 2015-06-12 15:51:31 +0000 | |||
1713 | @@ -0,0 +1,30 @@ | |||
1714 | 1 | /** | ||
1715 | 2 | * Copyright © 2015 Canonical, Ltd. | ||
1716 | 3 | * | ||
1717 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1718 | 5 | * the terms of the GNU General Public License version 3, as published by | ||
1719 | 6 | * the Free Software Foundation. | ||
1720 | 7 | * * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1721 | 8 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1722 | 9 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1723 | 10 | * General Public License for more details. | ||
1724 | 11 | * | ||
1725 | 12 | * You should have received a copy of the GNU General Public License | ||
1726 | 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1727 | 14 | * | ||
1728 | 15 | */ | ||
1729 | 16 | |||
1730 | 17 | #pragma once | ||
1731 | 18 | #include "overlay-tracker-iface.h" | ||
1732 | 19 | #include <utility> | ||
1733 | 20 | |||
1734 | 21 | class OverlayTrackerMock : public OverlayTrackerIface | ||
1735 | 22 | { | ||
1736 | 23 | public: | ||
1737 | 24 | std::vector<std::tuple<std::string, unsigned long, std::string>> addedOverlays; | ||
1738 | 25 | |||
1739 | 26 | bool addOverlay (const char * appid, unsigned long pid, const char * url) { | ||
1740 | 27 | addedOverlays.push_back(std::make_tuple(std::string(appid), pid, std::string(url))); | ||
1741 | 28 | return true; | ||
1742 | 29 | } | ||
1743 | 30 | }; | ||
1744 | 0 | 31 | ||
1745 | === added file 'tests/overlay-tracker-test.cpp' | |||
1746 | --- tests/overlay-tracker-test.cpp 1970-01-01 00:00:00 +0000 | |||
1747 | +++ tests/overlay-tracker-test.cpp 2015-06-12 15:51:31 +0000 | |||
1748 | @@ -0,0 +1,127 @@ | |||
1749 | 1 | /** | ||
1750 | 2 | * Copyright © 2015 Canonical, Ltd. | ||
1751 | 3 | * | ||
1752 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1753 | 5 | * the terms of the GNU General Public License version 3, as published by | ||
1754 | 6 | * the Free Software Foundation. | ||
1755 | 7 | * * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1756 | 8 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1757 | 9 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1758 | 10 | * General Public License for more details. | ||
1759 | 11 | * | ||
1760 | 12 | * You should have received a copy of the GNU General Public License | ||
1761 | 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1762 | 14 | * | ||
1763 | 15 | */ | ||
1764 | 16 | |||
1765 | 17 | #include <random> | ||
1766 | 18 | |||
1767 | 19 | #include "test-config.h" | ||
1768 | 20 | |||
1769 | 21 | #include <gio/gio.h> | ||
1770 | 22 | #include <gtest/gtest.h> | ||
1771 | 23 | #include <libdbustest/dbus-test.h> | ||
1772 | 24 | |||
1773 | 25 | #include "overlay-tracker-mir.h" | ||
1774 | 26 | #include "ubuntu-app-launch-mock.h" | ||
1775 | 27 | #include "mir-mock.h" | ||
1776 | 28 | |||
1777 | 29 | class OverlayTrackerTest : public ::testing::Test | ||
1778 | 30 | { | ||
1779 | 31 | protected: | ||
1780 | 32 | virtual void SetUp() { | ||
1781 | 33 | g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE); | ||
1782 | 34 | |||
1783 | 35 | return; | ||
1784 | 36 | } | ||
1785 | 37 | |||
1786 | 38 | virtual void TearDown() { | ||
1787 | 39 | return; | ||
1788 | 40 | } | ||
1789 | 41 | |||
1790 | 42 | static gboolean quit_loop (gpointer ploop) { | ||
1791 | 43 | g_main_loop_quit((GMainLoop *)ploop); | ||
1792 | 44 | return FALSE; | ||
1793 | 45 | } | ||
1794 | 46 | |||
1795 | 47 | void pause (int time) { | ||
1796 | 48 | GMainLoop * loop = g_main_loop_new(nullptr, FALSE); | ||
1797 | 49 | g_timeout_add(time, quit_loop, loop); | ||
1798 | 50 | g_main_loop_run(loop); | ||
1799 | 51 | g_main_loop_unref(loop); | ||
1800 | 52 | } | ||
1801 | 53 | }; | ||
1802 | 54 | |||
1803 | 55 | TEST_F(OverlayTrackerTest, BasicCreation) { | ||
1804 | 56 | auto tracker = new OverlayTrackerMir(); | ||
1805 | 57 | delete tracker; | ||
1806 | 58 | } | ||
1807 | 59 | |||
1808 | 60 | TEST_F(OverlayTrackerTest, AddOverlay) { | ||
1809 | 61 | auto tracker = new OverlayTrackerMir(); | ||
1810 | 62 | |||
1811 | 63 | auto mirconn = mir_mock_connect_last_connect(); | ||
1812 | 64 | EXPECT_EQ("mir_socket_trusted", mirconn.first.substr(mirconn.first.size() - 18)); | ||
1813 | 65 | EXPECT_EQ("url-dispatcher", mirconn.second); | ||
1814 | 66 | |||
1815 | 67 | EXPECT_TRUE(tracker->addOverlay("app-id", 5, "http://no-name-yet.com")); | ||
1816 | 68 | |||
1817 | 69 | EXPECT_EQ(5, mir_mock_last_trust_pid); | ||
1818 | 70 | |||
1819 | 71 | EXPECT_STREQ("url-overlay", ubuntu_app_launch_mock_last_start_session_helper); | ||
1820 | 72 | EXPECT_STREQ("app-id", ubuntu_app_launch_mock_last_start_session_appid); | ||
1821 | 73 | EXPECT_STREQ("http://no-name-yet.com", ubuntu_app_launch_mock_last_start_session_uris[0]); | ||
1822 | 74 | |||
1823 | 75 | delete tracker; | ||
1824 | 76 | |||
1825 | 77 | EXPECT_STREQ("url-overlay", ubuntu_app_launch_mock_last_stop_helper); | ||
1826 | 78 | EXPECT_STREQ("app-id", ubuntu_app_launch_mock_last_stop_appid); | ||
1827 | 79 | EXPECT_STREQ("instance", ubuntu_app_launch_mock_last_stop_instance); | ||
1828 | 80 | } | ||
1829 | 81 | |||
1830 | 82 | TEST_F(OverlayTrackerTest, OverlayABunch) { | ||
1831 | 83 | OverlayTrackerMir tracker; | ||
1832 | 84 | std::uniform_int_distribution<> randpid(1, 32000); | ||
1833 | 85 | std::mt19937 rand; | ||
1834 | 86 | |||
1835 | 87 | /* Testing adding a bunch of overlays, we're using pretty standard | ||
1836 | 88 | data structures, but let's make sure we didn't break 'em */ | ||
1837 | 89 | for (auto name : std::vector<std::string>{"warty", "hoary", "breezy", "dapper", "edgy", "feisty", "gutsy", "hardy", "intrepid", "jaunty", "karmic", "lucid", "maverick", "natty", "oneiric", "precise", "quantal", "raring", "saucy", "trusty", "utopic", "vivid", "wily"}) { | ||
1838 | 90 | int pid = randpid(rand); | ||
1839 | 91 | tracker.addOverlay(name.c_str(), pid, "http://ubuntu.com/releases"); | ||
1840 | 92 | |||
1841 | 93 | EXPECT_EQ(pid, mir_mock_last_trust_pid); | ||
1842 | 94 | EXPECT_EQ(name, ubuntu_app_launch_mock_last_start_session_appid); | ||
1843 | 95 | } | ||
1844 | 96 | } | ||
1845 | 97 | |||
1846 | 98 | TEST_F(OverlayTrackerTest, UALSignalStop) { | ||
1847 | 99 | OverlayTrackerMir tracker; | ||
1848 | 100 | |||
1849 | 101 | /* Call with the overlay before it is set */ | ||
1850 | 102 | ubuntu_app_launch_mock_observer_helper_stop_func("app-id", "instance", "url-overlay", ubuntu_app_launch_mock_observer_helper_stop_user_data); | ||
1851 | 103 | |||
1852 | 104 | EXPECT_TRUE(tracker.addOverlay("app-id", 5, "http://no-name-yet.com")); | ||
1853 | 105 | |||
1854 | 106 | mir_mock_last_released_session = nullptr; | ||
1855 | 107 | ubuntu_app_launch_mock_observer_helper_stop_func("app-id", "instance", "url-overlay", ubuntu_app_launch_mock_observer_helper_stop_user_data); | ||
1856 | 108 | EXPECT_NE(nullptr, mir_mock_last_released_session); | ||
1857 | 109 | } | ||
1858 | 110 | |||
1859 | 111 | TEST_F(OverlayTrackerTest, MirSignalStop) { | ||
1860 | 112 | OverlayTrackerMir tracker; | ||
1861 | 113 | |||
1862 | 114 | EXPECT_TRUE(tracker.addOverlay("app-id", 5, "http://no-name-yet.com")); | ||
1863 | 115 | |||
1864 | 116 | /* Try a badie */ | ||
1865 | 117 | mir_mock_last_trust_func((MirPromptSession *)1337, mir_prompt_session_state_stopped, mir_mock_last_trust_data); | ||
1866 | 118 | |||
1867 | 119 | EXPECT_NE(nullptr, mir_mock_last_trust_func); | ||
1868 | 120 | mir_mock_last_trust_func(mir_mock_valid_trust_session, mir_prompt_session_state_stopped, mir_mock_last_trust_data); | ||
1869 | 121 | |||
1870 | 122 | pause(100); | ||
1871 | 123 | |||
1872 | 124 | EXPECT_STREQ("url-overlay", ubuntu_app_launch_mock_last_stop_helper); | ||
1873 | 125 | EXPECT_STREQ("app-id", ubuntu_app_launch_mock_last_stop_appid); | ||
1874 | 126 | EXPECT_STREQ("instance", ubuntu_app_launch_mock_last_stop_instance); | ||
1875 | 127 | } | ||
1876 | 0 | 128 | ||
1877 | === modified file 'tests/service-test.cc' | |||
1878 | --- tests/service-test.cc 2014-10-28 12:46:32 +0000 | |||
1879 | +++ tests/service-test.cc 2015-06-12 15:51:31 +0000 | |||
1880 | @@ -39,6 +39,7 @@ | |||
1881 | 39 | g_setenv("UBUNTU_APP_LAUNCH_USE_SESSION", "1", TRUE); | 39 | g_setenv("UBUNTU_APP_LAUNCH_USE_SESSION", "1", TRUE); |
1882 | 40 | g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE); | 40 | g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE); |
1883 | 41 | g_setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, TRUE); | 41 | g_setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, TRUE); |
1884 | 42 | g_setenv("LD_PRELOAD", MIR_MOCK_PATH, TRUE); | ||
1885 | 42 | 43 | ||
1886 | 43 | SetUpDb(); | 44 | SetUpDb(); |
1887 | 44 | 45 | ||
1888 | @@ -94,10 +95,6 @@ | |||
1889 | 94 | } | 95 | } |
1890 | 95 | 96 | ||
1891 | 96 | virtual void TearDown() { | 97 | virtual void TearDown() { |
1892 | 97 | /* dbustest should probably do this, not sure */ | ||
1893 | 98 | kill(dbus_test_process_get_pid(dispatcher), SIGTERM); | ||
1894 | 99 | g_usleep(50000); | ||
1895 | 100 | |||
1896 | 101 | g_clear_object(&dispatcher); | 98 | g_clear_object(&dispatcher); |
1897 | 102 | g_clear_object(&mock); | 99 | g_clear_object(&mock); |
1898 | 103 | g_clear_object(&dashmock); | 100 | g_clear_object(&dashmock); |
1899 | @@ -107,9 +104,7 @@ | |||
1900 | 107 | 104 | ||
1901 | 108 | unsigned int cleartry = 0; | 105 | unsigned int cleartry = 0; |
1902 | 109 | while (bus != nullptr && cleartry < 100) { | 106 | while (bus != nullptr && cleartry < 100) { |
1906 | 110 | g_usleep(100000); | 107 | pause(100); |
1904 | 111 | while (g_main_pending()) | ||
1905 | 112 | g_main_iteration(TRUE); | ||
1907 | 113 | cleartry++; | 108 | cleartry++; |
1908 | 114 | } | 109 | } |
1909 | 115 | 110 | ||
1910 | @@ -249,7 +244,7 @@ | |||
1911 | 249 | } | 244 | } |
1912 | 250 | 245 | ||
1913 | 251 | void | 246 | void |
1915 | 252 | focus_signal_cb (GDBusConnection */*connection*/, const gchar */*sender_name*/, const gchar */*object_path*/, const gchar */*interface_name*/, const gchar */*signal_name*/, GVariant */*parameters*/, gpointer user_data) | 247 | focus_signal_cb (GDBusConnection * /*connection*/, const gchar * /*sender_name*/, const gchar * /*object_path*/, const gchar * /*interface_name*/, const gchar * /*signal_name*/, GVariant * /*parameters*/, gpointer user_data) |
1916 | 253 | { | 248 | { |
1917 | 254 | guint * focus_count = (guint *)user_data; | 249 | guint * focus_count = (guint *)user_data; |
1918 | 255 | *focus_count = *focus_count + 1; | 250 | *focus_count = *focus_count + 1; |
1919 | 256 | 251 | ||
1920 | === modified file 'tests/test-config.h.in' | |||
1921 | --- tests/test-config.h.in 2015-01-09 16:11:45 +0000 | |||
1922 | +++ tests/test-config.h.in 2015-06-12 15:51:31 +0000 | |||
1923 | @@ -10,3 +10,7 @@ | |||
1924 | 10 | #define UPDATE_DIRECTORY_URLS "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-simple" | 10 | #define UPDATE_DIRECTORY_URLS "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-simple" |
1925 | 11 | #define UPDATE_DIRECTORY_VARIED "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-varied" | 11 | #define UPDATE_DIRECTORY_VARIED "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-varied" |
1926 | 12 | #define UPDATE_DIRECTORY_INTENT "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-intent" | 12 | #define UPDATE_DIRECTORY_INTENT "@CMAKE_CURRENT_SOURCE_DIR@/test-urls-intent" |
1927 | 13 | #define OVERLAY_TEST_DIR "@CMAKE_CURRENT_SOURCE_DIR@/overlay-dir" | ||
1928 | 14 | #define EXEC_TOOL "@CMAKE_BINARY_DIR@/service/exec-tool" | ||
1929 | 15 | #define MIR_MOCK_PATH "@CMAKE_CURRENT_BINARY_DIR@/libmir-mock.so" | ||
1930 | 16 | #define CLICK_DATA_DIR "@CMAKE_CURRENT_SOURCE_DIR@/click-data" | ||
1931 | 13 | 17 | ||
1932 | === modified file 'tests/ubuntu-app-launch-mock.c' | |||
1933 | --- tests/ubuntu-app-launch-mock.c 2014-05-26 12:56:47 +0000 | |||
1934 | +++ tests/ubuntu-app-launch-mock.c 2015-06-12 15:51:31 +0000 | |||
1935 | @@ -29,7 +29,7 @@ | |||
1936 | 29 | } | 29 | } |
1937 | 30 | 30 | ||
1938 | 31 | void | 31 | void |
1940 | 32 | ubuntu_app_launch_mock_clear_last_app_id (void) | 32 | ubuntu_app_launch_mock_clear_last_app_id () |
1941 | 33 | { | 33 | { |
1942 | 34 | g_free(last_appid); | 34 | g_free(last_appid); |
1943 | 35 | last_appid = NULL; | 35 | last_appid = NULL; |
1944 | @@ -37,7 +37,72 @@ | |||
1945 | 37 | } | 37 | } |
1946 | 38 | 38 | ||
1947 | 39 | gchar * | 39 | gchar * |
1949 | 40 | ubuntu_app_launch_mock_get_last_app_id (void) | 40 | ubuntu_app_launch_mock_get_last_app_id () |
1950 | 41 | { | 41 | { |
1951 | 42 | return last_appid; | 42 | return last_appid; |
1952 | 43 | } | 43 | } |
1953 | 44 | |||
1954 | 45 | UbuntuAppLaunchHelperObserver ubuntu_app_launch_mock_observer_helper_stop_func = NULL; | ||
1955 | 46 | gchar * ubuntu_app_launch_mock_observer_helper_stop_type = NULL; | ||
1956 | 47 | void * ubuntu_app_launch_mock_observer_helper_stop_user_data = NULL; | ||
1957 | 48 | |||
1958 | 49 | gboolean | ||
1959 | 50 | ubuntu_app_launch_observer_add_helper_stop (UbuntuAppLaunchHelperObserver func, const gchar * type, gpointer user_data) | ||
1960 | 51 | { | ||
1961 | 52 | ubuntu_app_launch_mock_observer_helper_stop_func = func; | ||
1962 | 53 | ubuntu_app_launch_mock_observer_helper_stop_type = g_strdup(type); | ||
1963 | 54 | ubuntu_app_launch_mock_observer_helper_stop_user_data = user_data; | ||
1964 | 55 | |||
1965 | 56 | return TRUE; | ||
1966 | 57 | } | ||
1967 | 58 | |||
1968 | 59 | gboolean | ||
1969 | 60 | ubuntu_app_launch_observer_delete_helper_stop (UbuntuAppLaunchHelperObserver func, const gchar * type, gpointer user_data) | ||
1970 | 61 | { | ||
1971 | 62 | gboolean same = ubuntu_app_launch_mock_observer_helper_stop_func == func && | ||
1972 | 63 | g_strcmp0(ubuntu_app_launch_mock_observer_helper_stop_type, type) == 0 && | ||
1973 | 64 | ubuntu_app_launch_mock_observer_helper_stop_user_data == user_data; | ||
1974 | 65 | |||
1975 | 66 | ubuntu_app_launch_mock_observer_helper_stop_func = NULL; | ||
1976 | 67 | g_clear_pointer(&ubuntu_app_launch_mock_observer_helper_stop_type, g_free); | ||
1977 | 68 | ubuntu_app_launch_mock_observer_helper_stop_user_data = NULL; | ||
1978 | 69 | |||
1979 | 70 | return same; | ||
1980 | 71 | } | ||
1981 | 72 | |||
1982 | 73 | gchar * ubuntu_app_launch_mock_last_start_session_helper = NULL; | ||
1983 | 74 | MirPromptSession * ubuntu_app_launch_mock_last_start_session_session = NULL; | ||
1984 | 75 | gchar * ubuntu_app_launch_mock_last_start_session_appid = NULL; | ||
1985 | 76 | gchar ** ubuntu_app_launch_mock_last_start_session_uris = NULL; | ||
1986 | 77 | |||
1987 | 78 | gchar * | ||
1988 | 79 | ubuntu_app_launch_start_session_helper (const gchar * type, MirPromptSession * session, const gchar * appid, const gchar * const * uris) | ||
1989 | 80 | { | ||
1990 | 81 | g_clear_pointer(&ubuntu_app_launch_mock_last_start_session_helper, g_free); | ||
1991 | 82 | g_clear_pointer(&ubuntu_app_launch_mock_last_start_session_appid, g_free); | ||
1992 | 83 | g_clear_pointer(&ubuntu_app_launch_mock_last_start_session_uris, g_strfreev); | ||
1993 | 84 | |||
1994 | 85 | ubuntu_app_launch_mock_last_start_session_helper = g_strdup(type); | ||
1995 | 86 | ubuntu_app_launch_mock_last_start_session_session = session; | ||
1996 | 87 | ubuntu_app_launch_mock_last_start_session_appid = g_strdup(appid); | ||
1997 | 88 | ubuntu_app_launch_mock_last_start_session_uris = g_strdupv((gchar **)uris); | ||
1998 | 89 | |||
1999 | 90 | return g_strdup("instance"); | ||
2000 | 91 | } | ||
2001 | 92 | |||
2002 | 93 | gchar * ubuntu_app_launch_mock_last_stop_helper = NULL; | ||
2003 | 94 | gchar * ubuntu_app_launch_mock_last_stop_appid = NULL; | ||
2004 | 95 | gchar * ubuntu_app_launch_mock_last_stop_instance = NULL; | ||
2005 | 96 | |||
2006 | 97 | gboolean | ||
2007 | 98 | ubuntu_app_launch_stop_multiple_helper (const gchar * helper_type, const gchar * appid, const gchar * instance) { | ||
2008 | 99 | g_clear_pointer(&ubuntu_app_launch_mock_last_stop_helper, g_free); | ||
2009 | 100 | g_clear_pointer(&ubuntu_app_launch_mock_last_stop_appid, g_free); | ||
2010 | 101 | g_clear_pointer(&ubuntu_app_launch_mock_last_stop_instance, g_free); | ||
2011 | 102 | |||
2012 | 103 | ubuntu_app_launch_mock_last_stop_helper = g_strdup(helper_type); | ||
2013 | 104 | ubuntu_app_launch_mock_last_stop_appid = g_strdup(appid); | ||
2014 | 105 | ubuntu_app_launch_mock_last_stop_instance = g_strdup(instance); | ||
2015 | 106 | |||
2016 | 107 | return TRUE; | ||
2017 | 108 | } | ||
2018 | 44 | 109 | ||
2019 | === modified file 'tests/ubuntu-app-launch-mock.h' | |||
2020 | --- tests/ubuntu-app-launch-mock.h 2014-10-24 18:55:11 +0000 | |||
2021 | +++ tests/ubuntu-app-launch-mock.h 2015-06-12 15:51:31 +0000 | |||
2022 | @@ -19,11 +19,23 @@ | |||
2023 | 19 | #define UPSTART_APP_LAUNCH_MOCK 1 | 19 | #define UPSTART_APP_LAUNCH_MOCK 1 |
2024 | 20 | 20 | ||
2025 | 21 | #include <glib.h> | 21 | #include <glib.h> |
2026 | 22 | #include <ubuntu-app-launch.h> | ||
2027 | 22 | 23 | ||
2028 | 23 | G_BEGIN_DECLS | 24 | G_BEGIN_DECLS |
2029 | 24 | 25 | ||
2032 | 25 | void ubuntu_app_launch_mock_clear_last_app_id (void); | 26 | void ubuntu_app_launch_mock_clear_last_app_id (); |
2033 | 26 | gchar * ubuntu_app_launch_mock_get_last_app_id (void); | 27 | gchar * ubuntu_app_launch_mock_get_last_app_id (); |
2034 | 28 | |||
2035 | 29 | extern UbuntuAppLaunchHelperObserver ubuntu_app_launch_mock_observer_helper_stop_func; | ||
2036 | 30 | extern gchar * ubuntu_app_launch_mock_observer_helper_stop_type; | ||
2037 | 31 | extern void * ubuntu_app_launch_mock_observer_helper_stop_user_data; | ||
2038 | 32 | extern gchar * ubuntu_app_launch_mock_last_start_session_helper; | ||
2039 | 33 | extern MirPromptSession * ubuntu_app_launch_mock_last_start_session_session; | ||
2040 | 34 | extern gchar * ubuntu_app_launch_mock_last_start_session_appid; | ||
2041 | 35 | extern gchar ** ubuntu_app_launch_mock_last_start_session_uris; | ||
2042 | 36 | extern gchar * ubuntu_app_launch_mock_last_stop_helper; | ||
2043 | 37 | extern gchar * ubuntu_app_launch_mock_last_stop_appid; | ||
2044 | 38 | extern gchar * ubuntu_app_launch_mock_last_stop_instance; | ||
2045 | 27 | 39 | ||
2046 | 28 | G_END_DECLS | 40 | G_END_DECLS |
2047 | 29 | 41 |
FAILED: Continuous integration, rev:126 jenkins. qa.ubuntu. com/job/ url-dispatcher- ci/166/ jenkins. qa.ubuntu. com/job/ url-dispatcher- wily-amd64- ci/2/console jenkins. qa.ubuntu. com/job/ url-dispatcher- wily-armhf- ci/2/console jenkins. qa.ubuntu. com/job/ url-dispatcher- wily-i386- ci/2/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/url- dispatcher- ci/166/ rebuild
http://