Merge lp:~mhr3/unity-scopes-api/always-join-threads into lp:unity-scopes-api
- always-join-threads
- Merge into trunk
Proposed by
Michal Hruby
Status: | Superseded |
---|---|
Proposed branch: | lp:~mhr3/unity-scopes-api/always-join-threads |
Merge into: | lp:unity-scopes-api |
Diff against target: |
1673 lines (+615/-325) 31 files modified
CMakeLists.txt (+4/-2) debian/control (+3/-0) debian/libunity-scopes1.scope.click-hook (+3/-0) debian/libunity-scopes1.symbols (+5/-0) debian/rules (+4/-1) demo/CMakeLists.txt (+1/-0) demo/click/CMakeLists.txt (+1/-0) demo/click/scope-click/CMakeLists.txt (+34/-0) demo/click/scope-click/click-build.sh (+47/-0) demo/click/scope-click/click/CMakeLists.txt (+8/-0) demo/click/scope-click/click/manifest.json.in (+19/-0) demo/click/scope-click/scope-click.cpp (+95/-0) demo/click/scope-click/scope-click.ini.in (+9/-0) demo/click/scope-click/scope-click.map (+9/-0) include/unity/scopes/ScopeMetadata.h (+14/-0) include/unity/scopes/internal/RegistryConfig.h (+2/-0) include/unity/scopes/internal/ScopeConfig.h (+3/-0) include/unity/scopes/internal/ScopeMetadataImpl.h (+3/-0) include/unity/scopes/internal/smartscopes/SmartScope.h (+25/-5) scoperegistry/FindFiles.cpp (+10/-34) scoperegistry/scoperegistry.cpp (+125/-70) scoperunner/scoperunner.cpp (+86/-143) src/scopes/ScopeMetadata.cpp (+5/-0) src/scopes/internal/RegistryConfig.cpp (+10/-0) src/scopes/internal/ScopeConfig.cpp (+32/-0) src/scopes/internal/ScopeMetadataImpl.cpp (+17/-1) test/gtest/scopes/Registry/Registry_test.cpp (+22/-0) test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp (+5/-1) test/whitespace/CMakeLists.txt (+5/-1) test/whitespace/check_whitespace.py (+9/-5) test/whitespace/check_whitespace.sh (+0/-62) |
To merge this branch: | bzr merge lp:~mhr3/unity-scopes-api/always-join-threads |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Team | Pending | ||
Review via email:
|
This proposal has been superseded by a proposal from 2014-04-08.
Commit message
Always join worker threads.
Description of the change
Always join worker threads. Otherwise if something throws an exception, the thread is destructed without being joined, and that's not a good thing to do.
To post a comment you must log in.
- 302. By Michal Hruby
-
Wrap the trap thread also in smartscopesproxy
- 303. By Marcus Tomlinson
-
Init state receiver first
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-04-04 14:53:32 +0000 |
3 | +++ CMakeLists.txt 2014-04-08 16:22:25 +0000 |
4 | @@ -54,11 +54,12 @@ |
5 | endif() |
6 | |
7 | include(FindPkgConfig) |
8 | -find_package(Boost COMPONENTS regex serialization REQUIRED) |
9 | +find_package(Boost COMPONENTS system filesystem regex serialization REQUIRED) |
10 | pkg_check_modules(UNITY_API libunity-api>=0.1.1 REQUIRED) |
11 | pkg_check_modules(PROCESS_CPP process-cpp>=1.0.0 REQUIRED) |
12 | pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) |
13 | pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) |
14 | +pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED) |
15 | find_program(LTTNG_EXECUTABLE lttng) |
16 | if (NOT LTTNG_EXECUTABLE) |
17 | message(SEND_ERROR "Cannot find LTTng executable: ensure that lttng-tools is installed") |
18 | @@ -100,7 +101,7 @@ |
19 | endif() |
20 | set(CAPNPC_FLAGS "" CACHE STRING "Extra flags for capnpc.") |
21 | |
22 | -set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS}) |
23 | +set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS}) |
24 | set(OTHER_LIBS ${UNITY_API_LDFLAGS} ${OTHER_LIBS}) |
25 | |
26 | # Standard install paths |
27 | @@ -218,6 +219,7 @@ |
28 | ${Boost_LIBRARIES} |
29 | ${JSONCPP_LDFLAGS} |
30 | ${PROCESS_CPP_LDFLAGS} |
31 | + ${APPARMOR_LDFLAGS} |
32 | ${ZMQPPLIB} |
33 | ${ZMQLIB} |
34 | ${CAPNPLIB} |
35 | |
36 | === modified file 'debian/control' |
37 | --- debian/control 2014-04-04 14:53:32 +0000 |
38 | +++ debian/control 2014-04-08 16:22:25 +0000 |
39 | @@ -2,6 +2,7 @@ |
40 | Priority: optional |
41 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
42 | Build-Depends: debhelper (>= 9), |
43 | + click-dev (>= 0.2.2), |
44 | cmake, |
45 | doxygen, |
46 | google-mock, |
47 | @@ -9,8 +10,10 @@ |
48 | pkg-config, |
49 | python3, |
50 | capnproto, |
51 | + libapparmor-dev, |
52 | libprocess-cpp-dev (>= 1.0.0), |
53 | libunity-api-dev (>= 7.80.5~), |
54 | + libboost-filesystem-dev, |
55 | libboost-regex-dev, |
56 | libboost-serialization-dev, |
57 | libcapnp-dev (>= 0.4.0), |
58 | |
59 | === added file 'debian/libunity-scopes1.scope.click-hook' |
60 | --- debian/libunity-scopes1.scope.click-hook 1970-01-01 00:00:00 +0000 |
61 | +++ debian/libunity-scopes1.scope.click-hook 2014-04-08 16:22:25 +0000 |
62 | @@ -0,0 +1,3 @@ |
63 | +Pattern: ${home}/.local/share/unity-scopes/${id} |
64 | +User-Level: yes |
65 | +Hook-Name: scope |
66 | |
67 | === modified file 'debian/libunity-scopes1.symbols' |
68 | --- debian/libunity-scopes1.symbols 2014-04-04 17:36:38 +0000 |
69 | +++ debian/libunity-scopes1.symbols 2014-04-08 16:22:25 +0000 |
70 | @@ -430,6 +430,8 @@ |
71 | (c++)"unity::scopes::internal::MiddlewareFactory::to_kind(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
72 | (c++)"unity::scopes::internal::MiddlewareFactory::MiddlewareFactory(unity::scopes::internal::RuntimeImpl*)@Base" 0.4.0+14.04.20140312.1 |
73 | (c++)"unity::scopes::internal::MiddlewareFactory::~MiddlewareFactory()@Base" 0.4.0+14.04.20140312.1 |
74 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::set_confinement_type(unity::scopes::ConfinementType)@Base" 0replaceme |
75 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::confinement_type() const@Base" 0replaceme |
76 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_author(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
77 | (c++)"unity::scopes::internal::ScopeMetadataImpl::deserialize(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1 |
78 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_hot_key(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
79 | @@ -511,6 +513,7 @@ |
80 | (c++)"unity::scopes::PreviewWidget::id() const@Base" 0.4.0+14.04.20140312.1 |
81 | (c++)"unity::scopes::PreviewWidget::data() const@Base" 0.4.0+14.04.20140312.1 |
82 | (c++)"unity::scopes::PreviewWidget::serialize() const@Base" 0.4.0+14.04.20140312.1 |
83 | + (c++)"unity::scopes::ScopeMetadata::confinement_type() const@Base" 0replaceme |
84 | (c++)"unity::scopes::ScopeMetadata::description() const@Base" 0.4.0+14.04.20140312.1 |
85 | (c++)"unity::scopes::ScopeMetadata::search_hint() const@Base" 0.4.0+14.04.20140312.1 |
86 | (c++)"unity::scopes::ScopeMetadata::display_name() const@Base" 0.4.0+14.04.20140312.1 |
87 | @@ -610,6 +613,7 @@ |
88 | (c++)"unity::scopes::internal::RuntimeImpl::factory() const@Base" 0.4.0+14.04.20140312.1 |
89 | (c++)"unity::scopes::internal::RuntimeImpl::registry() const@Base" 0.4.0+14.04.20140312.1 |
90 | (c++)"unity::scopes::internal::RuntimeImpl::scope_id() const@Base" 0.4.0+14.04.20140312.1 |
91 | + (c++)"unity::scopes::internal::ScopeConfig::confinement_type() const@Base" 0replaceme |
92 | (c++)"unity::scopes::internal::ScopeConfig::description() const@Base" 0.4.0+14.04.20140312.1 |
93 | (c++)"unity::scopes::internal::ScopeConfig::search_hint() const@Base" 0.4.0+14.04.20140312.1 |
94 | (c++)"unity::scopes::internal::ScopeConfig::display_name() const@Base" 0.4.0+14.04.20140312.1 |
95 | @@ -634,6 +638,7 @@ |
96 | (c++)"unity::scopes::internal::RuntimeConfig::registry_configfile() const@Base" 0.4.2+14.04.20140404.2 |
97 | (c++)"unity::scopes::internal::RuntimeConfig::default_middleware_configfile() const@Base" 0.4.2+14.04.20140404.2 |
98 | (c++)"unity::scopes::internal::MiddlewareBase::runtime() const@Base" 0.4.0+14.04.20140312.1 |
99 | + (c++)"unity::scopes::internal::RegistryConfig::click_installdir() const@Base" 0replaceme |
100 | (c++)"unity::scopes::internal::RegistryConfig::endpointdir() const@Base" 0.4.0+14.04.20140312.1 |
101 | (c++)"unity::scopes::internal::RegistryConfig::mw_configfile() const@Base" 0.4.0+14.04.20140312.1 |
102 | (c++)"unity::scopes::internal::RegistryConfig::oem_installdir() const@Base" 0.4.0+14.04.20140312.1 |
103 | |
104 | === modified file 'debian/rules' |
105 | --- debian/rules 2013-12-19 02:35:14 +0000 |
106 | +++ debian/rules 2014-04-08 16:22:25 +0000 |
107 | @@ -6,7 +6,7 @@ |
108 | export DPKG_GENSYMBOLS_CHECK_LEVEL=4 |
109 | |
110 | %: |
111 | - dh $@ --parallel --fail-missing |
112 | + dh $@ --parallel --fail-missing --with click |
113 | |
114 | override_dh_auto_configure: |
115 | dh_auto_configure -- -DLIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH) |
116 | @@ -14,3 +14,6 @@ |
117 | # Tests are not written to be run in parallel. |
118 | override_dh_auto_test: |
119 | dh_auto_test --max-parallel=1 -- ARGS="--verbose" |
120 | + |
121 | +override_dh_click: |
122 | + dh_click --name scope |
123 | |
124 | === modified file 'demo/CMakeLists.txt' |
125 | --- demo/CMakeLists.txt 2014-02-03 09:04:04 +0000 |
126 | +++ demo/CMakeLists.txt 2014-04-08 16:22:25 +0000 |
127 | @@ -1,3 +1,4 @@ |
128 | +add_subdirectory(click) |
129 | add_subdirectory(scopes) |
130 | add_subdirectory(stand-alone) |
131 | |
132 | |
133 | === added directory 'demo/click' |
134 | === added file 'demo/click/CMakeLists.txt' |
135 | --- demo/click/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
136 | +++ demo/click/CMakeLists.txt 2014-04-08 16:22:25 +0000 |
137 | @@ -0,0 +1,1 @@ |
138 | +add_subdirectory(scope-click) |
139 | |
140 | === added directory 'demo/click/scope-click' |
141 | === added file 'demo/click/scope-click/CMakeLists.txt' |
142 | --- demo/click/scope-click/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
143 | +++ demo/click/scope-click/CMakeLists.txt 2014-04-08 16:22:25 +0000 |
144 | @@ -0,0 +1,34 @@ |
145 | + |
146 | +if(CLICK_MODE) |
147 | + project(unity-scope-click C CXX) |
148 | + cmake_minimum_required(VERSION 2.8.10) |
149 | + |
150 | + include(GNUInstallDirs) |
151 | + include(FindPkgConfig) |
152 | + |
153 | + pkg_check_modules(UNITY_SCOPES REQUIRED libunity-scopes>=0.4.0) |
154 | + add_definitions(${UNITY_SCOPES_CFLAGS} ${UNITY_SCOPES_CFLAGS_OTHER}) |
155 | + |
156 | + add_definitions(-std=c++11) |
157 | +endif(CLICK_MODE) |
158 | + |
159 | +add_subdirectory(click) |
160 | + |
161 | +set(symbol_map "${CMAKE_CURRENT_SOURCE_DIR}/scope-click.map") |
162 | + |
163 | +add_library(scope-click MODULE scope-click.cpp) |
164 | +# Add_dependencies should be used sparingly. In this case we need the global |
165 | +# header to be generated before we start building the client binary. |
166 | +add_dependencies(scope-click globalheader) |
167 | +set_target_properties(scope-click PROPERTIES |
168 | + LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") |
169 | +set_target_properties(scope-click PROPERTIES LINK_DEPENDS ${symbol_map}) |
170 | + |
171 | +configure_file(scope-click.ini.in scope-click.ini) |
172 | + |
173 | +if(CLICK_MODE) |
174 | + install(TARGETS scope-click |
175 | + DESTINATION "${CMAKE_INSTALL_PREFIX}/scope-click/") |
176 | + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/scope-click.ini" |
177 | + DESTINATION "${CMAKE_INSTALL_PREFIX}/scope-click/") |
178 | +endif(CLICK_MODE) |
179 | |
180 | === added directory 'demo/click/scope-click/click' |
181 | === added file 'demo/click/scope-click/click-build.sh' |
182 | --- demo/click/scope-click/click-build.sh 1970-01-01 00:00:00 +0000 |
183 | +++ demo/click/scope-click/click-build.sh 2014-04-08 16:22:25 +0000 |
184 | @@ -0,0 +1,47 @@ |
185 | +#!/bin/sh |
186 | + |
187 | +# Copyright (C) 2014 Canonical Ltd |
188 | +# |
189 | +# This program is free software: you can redistribute it and/or modify |
190 | +# it under the terms of the GNU Lesser General Public License version 3 as |
191 | +# published by the Free Software Foundation. |
192 | +# |
193 | +# This program is distributed in the hope that it will be useful, |
194 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
195 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
196 | +# GNU Lesser General Public License for more details. |
197 | +# |
198 | +# You should have received a copy of the GNU Lesser General Public License |
199 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
200 | +# |
201 | +# Authored by: Pete Woods <pete.woods@canonical.com> |
202 | + |
203 | +# Simple script to build a click packaged scope. |
204 | + |
205 | + |
206 | +export LC_ALL=C |
207 | + |
208 | +if [ "$#" -ne 1 ]; then |
209 | + echo "Usage: click-build.sh amd64|armhf|..." |
210 | + exit 1 |
211 | +fi |
212 | + |
213 | +BZR_SOURCE=${1:-lp:scope-click} |
214 | + |
215 | +CLICK_ARCH="$1" |
216 | +rm -rf "$CLICK_ARCH-build" |
217 | +rm -rf "package" |
218 | +mkdir "$CLICK_ARCH-build" |
219 | +( |
220 | + cd "$CLICK_ARCH-build" |
221 | + cmake .. \ |
222 | + -DCMAKE_INSTALL_PREFIX:PATH=../package \ |
223 | + -DCLICK_MODE=on \ |
224 | + -DCLICK_ARCH="$CLICK_ARCH" \ |
225 | + -DBZR_REVNO=$(cd ..; bzr revno) \ |
226 | + -DBZR_SOURCE="$BZR_SOURCE" |
227 | + make install |
228 | +) |
229 | +click build package |
230 | +rm -rf "$CLICK_ARCH-build" |
231 | +rm -rf "package" |
232 | |
233 | === added file 'demo/click/scope-click/click/CMakeLists.txt' |
234 | --- demo/click/scope-click/click/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
235 | +++ demo/click/scope-click/click/CMakeLists.txt 2014-04-08 16:22:25 +0000 |
236 | @@ -0,0 +1,8 @@ |
237 | +if(CLICK_MODE) |
238 | + if(NOT BZR_REVNO) |
239 | + set(BZR_REVNO "latest") |
240 | + endif(NOT BZR_REVNO) |
241 | + configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json) |
242 | + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json |
243 | + DESTINATION ${CMAKE_INSTALL_PREFIX}) |
244 | +endif(CLICK_MODE) |
245 | |
246 | === added file 'demo/click/scope-click/click/manifest.json.in' |
247 | --- demo/click/scope-click/click/manifest.json.in 1970-01-01 00:00:00 +0000 |
248 | +++ demo/click/scope-click/click/manifest.json.in 2014-04-08 16:22:25 +0000 |
249 | @@ -0,0 +1,19 @@ |
250 | +{ |
251 | + "description": "A pretend click scope", |
252 | + "framework": "ubuntu-sdk-14.04-dev1", |
253 | + "architecture": "@CLICK_ARCH@", |
254 | + "hooks": { |
255 | + "scope-click": { |
256 | + "scope": "scope-click" |
257 | + } |
258 | + }, |
259 | + "icon": "@CLICK_SCOPE_ICON@", |
260 | + "maintainer": "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>", |
261 | + "name": "com.ubuntu.scope-click", |
262 | + "title": "Click Scope", |
263 | + "version": "1.0.0.@BZR_REVNO@", |
264 | + "x-source": { |
265 | + "vcs-bzr": "@BZR_SOURCE@", |
266 | + "vcs-bzr-revno": "@BZR_REVNO@" |
267 | + } |
268 | +} |
269 | |
270 | === added file 'demo/click/scope-click/scope-click.cpp' |
271 | --- demo/click/scope-click/scope-click.cpp 1970-01-01 00:00:00 +0000 |
272 | +++ demo/click/scope-click/scope-click.cpp 2014-04-08 16:22:25 +0000 |
273 | @@ -0,0 +1,95 @@ |
274 | +/* |
275 | + * Copyright (C) 2014 Canonical Ltd |
276 | + * |
277 | + * This program is free software: you can redistribute it and/or modify |
278 | + * it under the terms of the GNU Lesser General Public License version 3 as |
279 | + * published by the Free Software Foundation. |
280 | + * |
281 | + * This program is distributed in the hope that it will be useful, |
282 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
283 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
284 | + * GNU Lesser General Public License for more details. |
285 | + * |
286 | + * You should have received a copy of the GNU Lesser General Public License |
287 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
288 | + * |
289 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
290 | + */ |
291 | + |
292 | +#include <unity/scopes/ScopeBase.h> |
293 | + |
294 | +#include <iostream> |
295 | +#include <thread> |
296 | + |
297 | +#define EXPORT __attribute__ ((visibility ("default"))) |
298 | + |
299 | +using namespace std; |
300 | +using namespace unity::scopes; |
301 | + |
302 | +// Demonstration of building a click scope. This file has the bare minimum scope implementation. |
303 | + |
304 | +class MyQuery : public SearchQueryBase |
305 | +{ |
306 | +public: |
307 | + MyQuery() |
308 | + { |
309 | + } |
310 | + |
311 | + ~MyQuery() |
312 | + { |
313 | + } |
314 | + |
315 | + virtual void cancelled() override |
316 | + { |
317 | + cerr << "scope-click: received cancel request" << endl; |
318 | + } |
319 | + |
320 | + virtual void run(SearchReplyProxy const&) override |
321 | + { |
322 | + cerr << "scope-click: received query" << endl; |
323 | + this_thread::sleep_for(chrono::seconds(3)); |
324 | + cerr << "scope-click: query complete" << endl; |
325 | + } |
326 | +}; |
327 | + |
328 | +class MyScope : public ScopeBase |
329 | +{ |
330 | +public: |
331 | + virtual int start(string const&, RegistryProxy const&) override |
332 | + { |
333 | + return VERSION; |
334 | + } |
335 | + |
336 | + virtual void stop() override {} |
337 | + |
338 | + virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override |
339 | + { |
340 | + return SearchQueryBase::UPtr(new MyQuery); |
341 | + } |
342 | + |
343 | + virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override |
344 | + { |
345 | + return nullptr; |
346 | + } |
347 | +}; |
348 | + |
349 | +extern "C" |
350 | +{ |
351 | + |
352 | + EXPORT |
353 | + unity::scopes::ScopeBase* |
354 | + // cppcheck-suppress unusedFunction |
355 | + UNITY_SCOPE_CREATE_FUNCTION() |
356 | + { |
357 | + return new MyScope; |
358 | + } |
359 | + |
360 | + EXPORT |
361 | + void |
362 | + // cppcheck-suppress unusedFunction |
363 | + UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) |
364 | + { |
365 | + delete scope_base; |
366 | + } |
367 | + |
368 | +} |
369 | |
370 | === added file 'demo/click/scope-click/scope-click.ini.in' |
371 | --- demo/click/scope-click/scope-click.ini.in 1970-01-01 00:00:00 +0000 |
372 | +++ demo/click/scope-click/scope-click.ini.in 2014-04-08 16:22:25 +0000 |
373 | @@ -0,0 +1,9 @@ |
374 | +[ScopeConfig] |
375 | +DisplayName = scope-click.DisplayName |
376 | +Description = scope-click.Description |
377 | +Art = scope-click.Art |
378 | +Author = Canonical Ltd. |
379 | +Icon = scope-click.Icon |
380 | +SearchHint = scope-click.SearchHint |
381 | +HotKey = scope-click.HotKey |
382 | +ConfinementType = UntrustedLocal |
383 | |
384 | === added file 'demo/click/scope-click/scope-click.map' |
385 | --- demo/click/scope-click/scope-click.map 1970-01-01 00:00:00 +0000 |
386 | +++ demo/click/scope-click/scope-click.map 2014-04-08 16:22:25 +0000 |
387 | @@ -0,0 +1,9 @@ |
388 | +{ |
389 | +global: |
390 | + "unity_scope_create"; |
391 | + "unity_scope_destroy"; |
392 | +local: |
393 | + extern "C++" { |
394 | + *; |
395 | + }; |
396 | +}; |
397 | |
398 | === modified file 'include/unity/scopes/ScopeMetadata.h' |
399 | --- include/unity/scopes/ScopeMetadata.h 2014-04-03 16:46:00 +0000 |
400 | +++ include/unity/scopes/ScopeMetadata.h 2014-04-08 16:22:25 +0000 |
401 | @@ -27,8 +27,16 @@ |
402 | namespace scopes |
403 | { |
404 | |
405 | +enum class ConfinementType |
406 | +{ |
407 | + Trusted, |
408 | + UntrustedLocal, |
409 | + UntrustedInternet |
410 | +}; |
411 | + |
412 | namespace internal |
413 | { |
414 | + |
415 | class ScopeMetadataImpl; |
416 | } // namespace internal |
417 | |
418 | @@ -71,6 +79,12 @@ |
419 | std::string scope_id() const; |
420 | |
421 | /** |
422 | + \brief Get the scope type. |
423 | + \return The type of the scope. |
424 | + */ |
425 | + ConfinementType confinement_type() const; |
426 | + |
427 | + /** |
428 | \brief Get the proxy object for this scope. |
429 | \return The scope proxy. |
430 | */ |
431 | |
432 | === modified file 'include/unity/scopes/internal/RegistryConfig.h' |
433 | --- include/unity/scopes/internal/RegistryConfig.h 2014-01-28 03:12:35 +0000 |
434 | +++ include/unity/scopes/internal/RegistryConfig.h 2014-04-08 16:22:25 +0000 |
435 | @@ -45,6 +45,7 @@ |
436 | std::string mw_configfile() const; |
437 | std::string scope_installdir() const; // Directory for Canonical scopes |
438 | std::string oem_installdir() const; // Directory for OEM scope config files |
439 | + std::string click_installdir() const; // Directory for Click scope config files |
440 | std::string scoperunner_path() const; // Path to scoperunner binary |
441 | std::string ss_registry_identity() const; // Identity of smart scopes registry |
442 | std::string ss_registry_endpoint() const; // Endpoint of smart scopes registry |
443 | @@ -57,6 +58,7 @@ |
444 | std::string mw_configfile_; |
445 | std::string scope_installdir_; |
446 | std::string oem_installdir_; |
447 | + std::string click_installdir_; |
448 | std::string scoperunner_path_; |
449 | std::string ss_registry_identity_; |
450 | std::string ss_registry_endpoint_; |
451 | |
452 | === modified file 'include/unity/scopes/internal/ScopeConfig.h' |
453 | --- include/unity/scopes/internal/ScopeConfig.h 2014-03-18 10:25:32 +0000 |
454 | +++ include/unity/scopes/internal/ScopeConfig.h 2014-04-08 16:22:25 +0000 |
455 | @@ -21,6 +21,7 @@ |
456 | |
457 | #include <unity/scopes/internal/ConfigBase.h> |
458 | #include <unity/scopes/Variant.h> |
459 | +#include <unity/scopes/ScopeMetadata.h> |
460 | |
461 | namespace unity |
462 | { |
463 | @@ -41,6 +42,7 @@ |
464 | ~ScopeConfig(); |
465 | |
466 | bool overrideable() const; // Optional, returns false if not present |
467 | + ConfinementType confinement_type() const; // Optional, returns Trusted if not present |
468 | std::string display_name() const; |
469 | std::string description() const; |
470 | std::string author() const; |
471 | @@ -54,6 +56,7 @@ |
472 | |
473 | private: |
474 | bool overrideable_; |
475 | + ConfinementType confinement_type_; |
476 | std::string display_name_; |
477 | std::string description_; |
478 | std::string author_; |
479 | |
480 | === modified file 'include/unity/scopes/internal/ScopeMetadataImpl.h' |
481 | --- include/unity/scopes/internal/ScopeMetadataImpl.h 2014-04-02 16:54:53 +0000 |
482 | +++ include/unity/scopes/internal/ScopeMetadataImpl.h 2014-04-08 16:22:25 +0000 |
483 | @@ -44,6 +44,7 @@ |
484 | ScopeMetadataImpl& operator=(ScopeMetadataImpl&&) = default; |
485 | |
486 | std::string scope_id() const; |
487 | + ConfinementType confinement_type() const; |
488 | ScopeProxy proxy() const; |
489 | std::string display_name() const; // localized |
490 | std::string description() const; // localized |
491 | @@ -57,6 +58,7 @@ |
492 | std::string scope_directory() const; |
493 | |
494 | void set_scope_id(std::string const& scope_id); |
495 | + void set_confinement_type(ConfinementType scope_type); |
496 | void set_proxy(ScopeProxy const& proxy); |
497 | void set_display_name(std::string const& display_name); |
498 | void set_description(std::string const& description); |
499 | @@ -78,6 +80,7 @@ |
500 | |
501 | MiddlewareBase* mw_; |
502 | std::string scope_id_; |
503 | + ConfinementType confinement_type_; |
504 | ScopeProxy proxy_; |
505 | std::string display_name_; |
506 | std::string description_; |
507 | |
508 | === modified file 'include/unity/scopes/internal/smartscopes/SmartScope.h' |
509 | --- include/unity/scopes/internal/smartscopes/SmartScope.h 2014-03-26 10:01:03 +0000 |
510 | +++ include/unity/scopes/internal/smartscopes/SmartScope.h 2014-04-08 16:22:25 +0000 |
511 | @@ -48,11 +48,22 @@ |
512 | : scope_id_(scope_id) |
513 | , query_(query) |
514 | { |
515 | + static const std::string no_net_hint("no-internet"); |
516 | + if (hints.contains_hint(no_net_hint)) |
517 | + { |
518 | + auto var = hints[no_net_hint]; |
519 | + if (var.which() == Variant::Type::Bool && var.get_bool()) |
520 | + { |
521 | + std::cout << "SmartQuery(): networking disabled for remote scope " << scope_id << ", skipping" << std::endl; |
522 | + return; |
523 | + } |
524 | + } |
525 | + |
526 | SmartScopesClient::SPtr ss_client = reg->get_ssclient(); |
527 | std::string base_url = reg->get_base_url(scope_id_); |
528 | |
529 | - ///! TODO: session_id, query_id, locale, country |
530 | - search_handle_ = ss_client->search(base_url, query_.query_string(), query.department_id(), "session_id", 0, hints.form_factor(), "", "", hints.cardinality()); |
531 | + ///! TODO: session_id, query_id, country |
532 | + search_handle_ = ss_client->search(base_url, query_.query_string(), query.department_id(), "session_id", 0, hints.form_factor(), hints.locale(), "", hints.cardinality()); |
533 | } |
534 | |
535 | ~SmartQuery() noexcept |
536 | @@ -61,11 +72,20 @@ |
537 | |
538 | virtual void cancelled() override |
539 | { |
540 | - search_handle_->cancel_search(); |
541 | + if (search_handle_ != nullptr) |
542 | + { |
543 | + search_handle_->cancel_search(); |
544 | + } |
545 | } |
546 | |
547 | virtual void run(SearchReplyProxy const& reply) override |
548 | { |
549 | + if (search_handle_ == nullptr) |
550 | + { |
551 | + // this can happen if networking is disabled |
552 | + return; |
553 | + } |
554 | + |
555 | std::vector<SearchResult> results = search_handle_->get_search_results(); |
556 | std::map<std::string, Category::SCPtr> categories; |
557 | |
558 | @@ -124,8 +144,8 @@ |
559 | SmartScopesClient::SPtr ss_client = reg->get_ssclient(); |
560 | std::string base_url = reg->get_base_url(scope_id_); |
561 | |
562 | - ///! TODO: session_id, widgets_api_version, locale, country |
563 | - preview_handle_ = ss_client->preview(base_url, result_["result_json"].get_string(), "session_id", hints.form_factor(), 0, "", ""); |
564 | + ///! TODO: session_id, widgets_api_version, country |
565 | + preview_handle_ = ss_client->preview(base_url, result_["result_json"].get_string(), "session_id", hints.form_factor(), 0, hints.locale(), ""); |
566 | } |
567 | |
568 | ~SmartPreview() |
569 | |
570 | === modified file 'scoperegistry/FindFiles.cpp' |
571 | --- scoperegistry/FindFiles.cpp 2014-04-03 12:57:25 +0000 |
572 | +++ scoperegistry/FindFiles.cpp 2014-04-08 16:22:25 +0000 |
573 | @@ -25,8 +25,11 @@ |
574 | #include <string.h> |
575 | #include <sys/stat.h> |
576 | |
577 | +#include <boost/filesystem/path.hpp> |
578 | + |
579 | using namespace std; |
580 | using namespace unity; |
581 | +using namespace boost; |
582 | |
583 | namespace scoperegistry |
584 | { |
585 | @@ -34,17 +37,6 @@ |
586 | namespace |
587 | { |
588 | |
589 | -bool has_suffix(string const& s, string const& suffix) |
590 | -{ |
591 | - auto s_len = s.length(); |
592 | - auto suffix_len = suffix.length(); |
593 | - if (s_len >= suffix_len) |
594 | - { |
595 | - return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; |
596 | - } |
597 | - return false; |
598 | -} |
599 | - |
600 | // Return all paths underneath the given dir that are of the given type |
601 | // or are a symbolic link. |
602 | |
603 | @@ -91,7 +83,7 @@ |
604 | |
605 | } // namespace |
606 | |
607 | -// Return all files of the form dir/<somescope>/<scomescope>.ini that are regular files or |
608 | +// Return all files of the form dir/*/<scomescope>.ini that are regular files or |
609 | // symbolic links and have the specified suffix. |
610 | // The empty suffix is legal and causes all regular files and symlinks to be returned. |
611 | |
612 | @@ -102,32 +94,16 @@ |
613 | auto subdirs = find_entries(install_dir, Directory); |
614 | for (auto subdir : subdirs) |
615 | { |
616 | - string scope_id = basename(const_cast<char*>(subdir.c_str())); // basename() modifies its argument |
617 | auto candidates = find_entries(subdir, File); |
618 | for (auto c : candidates) |
619 | { |
620 | - string config_name = basename(const_cast<char*>(c.c_str())); // basename() modifies its argument |
621 | - if (config_name == scope_id + suffix) |
622 | - { |
623 | - files.emplace_back(c); |
624 | + // TODO Check for multiple ini files |
625 | + |
626 | + filesystem::path path(c); |
627 | + if (path.extension() != suffix) { |
628 | + continue; |
629 | } |
630 | - } |
631 | - } |
632 | - |
633 | - return files; |
634 | -} |
635 | - |
636 | -// Return all files with the given suffix in dir. |
637 | - |
638 | -vector<string> find_files(string const& dir, string const& suffix) |
639 | -{ |
640 | - vector<string> files; |
641 | - |
642 | - auto candidates = find_entries(dir, File); |
643 | - for (auto c : candidates) |
644 | - { |
645 | - if (has_suffix(c, suffix)) |
646 | - { |
647 | + |
648 | files.emplace_back(c); |
649 | } |
650 | } |
651 | |
652 | === modified file 'scoperegistry/scoperegistry.cpp' |
653 | --- scoperegistry/scoperegistry.cpp 2014-04-03 16:46:00 +0000 |
654 | +++ scoperegistry/scoperegistry.cpp 2014-04-08 16:22:25 +0000 |
655 | @@ -39,12 +39,15 @@ |
656 | #include <libgen.h> |
657 | #include <unistd.h> |
658 | |
659 | +#include <boost/filesystem/path.hpp> |
660 | + |
661 | using namespace scoperegistry; |
662 | using namespace std; |
663 | using namespace unity; |
664 | using namespace unity::scopes; |
665 | using namespace unity::scopes::internal; |
666 | using namespace unity::util; |
667 | +using namespace boost; |
668 | |
669 | char const* prog_name; |
670 | |
671 | @@ -57,30 +60,68 @@ |
672 | cerr << prog_name << ": " << msg << endl; |
673 | } |
674 | |
675 | -string strip_suffix(string const& s, string const& suffix) |
676 | -{ |
677 | - auto s_len = s.length(); |
678 | - auto suffix_len = suffix.length(); |
679 | - if (s_len >= suffix_len) |
680 | - { |
681 | - if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) |
682 | - { |
683 | - return string(s, 0, s_len - suffix_len); |
684 | - } |
685 | - } |
686 | - return s; |
687 | -} |
688 | - |
689 | // if path is an absolute path, just return it. otherwise, append it to scopedir. |
690 | -string relative_scope_path_to_abs_path(string const& path, string const& scopedir) |
691 | +filesystem::path relative_scope_path_to_abs_path(filesystem::path const& path, filesystem::path const& scopedir) |
692 | { |
693 | - if (path.size() > 0 && path[0] != '/') |
694 | + if (path.is_relative()) |
695 | { |
696 | - return scopedir + "/" + path; |
697 | + return scopedir / path; |
698 | } |
699 | return path; |
700 | } |
701 | |
702 | +// throwing an exception without joining with a thread is a bad, bad thing to do, so let's RAII to avoid doing it |
703 | +struct SignalThreadWrapper |
704 | +{ |
705 | + std::shared_ptr<core::posix::SignalTrap> termination_trap; |
706 | + std::shared_ptr<core::posix::SignalTrap> child_trap; |
707 | + std::unique_ptr<core::posix::ChildProcess::DeathObserver> death_observer; |
708 | + std::thread termination_trap_worker; |
709 | + std::thread child_trap_worker; |
710 | + |
711 | + SignalThreadWrapper() : |
712 | + // We shutdown the runtime whenever these signals happen. |
713 | + termination_trap(core::posix::trap_signals_for_all_subsequent_threads( |
714 | + { |
715 | + core::posix::Signal::sig_int, |
716 | + core::posix::Signal::sig_hup, |
717 | + core::posix::Signal::sig_term |
718 | + })), |
719 | + // And we maintain our list of processes with the help of sig_chld. |
720 | + child_trap(core::posix::trap_signals_for_all_subsequent_threads( |
721 | + { |
722 | + core::posix::Signal::sig_chld |
723 | + })), |
724 | + // The death observer is required to make sure that we reap all child processes |
725 | + // whenever multiple sigchld's are compressed together. |
726 | + death_observer(core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(child_trap)), |
727 | + // Starting up both traps. |
728 | + termination_trap_worker([&]() { termination_trap->run(); }), |
729 | + child_trap_worker([&]() { child_trap->run(); }) |
730 | + { |
731 | + } |
732 | + |
733 | + core::Signal<core::posix::Signal>& signal_raised() |
734 | + { |
735 | + return termination_trap->signal_raised(); |
736 | + } |
737 | + |
738 | + ~SignalThreadWrapper() |
739 | + { |
740 | + // Stop termination_trap |
741 | + termination_trap->stop(); |
742 | + if (termination_trap_worker.joinable()) |
743 | + termination_trap_worker.join(); |
744 | + |
745 | + // Please note that the child_trap must only be stopped once the |
746 | + // termination_trap thread has been joined. We otherwise will encounter |
747 | + // a race between the middleware shutting down and not receiving sigchld anymore. |
748 | + child_trap->stop(); |
749 | + if (child_trap_worker.joinable()) |
750 | + child_trap_worker.join(); |
751 | + } |
752 | +}; |
753 | + |
754 | // Return a map of <scope, config_file> pairs for all scopes (Canonical and OEM scopes). |
755 | // If a Canonical scope is overrideable and the OEM has configured a scope with the |
756 | // same id, the OEM scope overrides the Canonical one. |
757 | @@ -98,8 +139,8 @@ |
758 | auto config_files = find_scope_config_files(scope_installdir, ".ini"); |
759 | for (auto&& path : config_files) |
760 | { |
761 | - string file_name = basename(const_cast<char*>(string(path).c_str())); // basename() modifies its argument |
762 | - string scope_id = strip_suffix(file_name, ".ini"); |
763 | + filesystem::path p(path); |
764 | + string scope_id = p.stem().native(); |
765 | try |
766 | { |
767 | ScopeConfig config(path); |
768 | @@ -125,8 +166,9 @@ |
769 | auto oem_paths = find_scope_config_files(oem_installdir, ".ini"); |
770 | for (auto&& path : oem_paths) |
771 | { |
772 | - string file_name = basename(const_cast<char*>(string(path).c_str())); // basename() modifies its argument |
773 | - string scope_id = strip_suffix(file_name, ".ini"); |
774 | + filesystem::path p(path); |
775 | + string file_name = p.filename().native(); |
776 | + string scope_id = p.stem().native(); |
777 | if (fixed_scopes.find(scope_id) == fixed_scopes.end()) |
778 | { |
779 | overrideable_scopes[scope_id] = path; // Replaces scope if it was present already |
780 | @@ -149,6 +191,40 @@ |
781 | return fixed_scopes; |
782 | } |
783 | |
784 | +map<string, string> find_click_scopes(map<string, string> const& local_scopes, string const& click_installdir) |
785 | +{ |
786 | + map<string, string> click_scopes; |
787 | + |
788 | + if (!click_installdir.empty()) |
789 | + { |
790 | + try |
791 | + { |
792 | + auto click_paths = find_scope_config_files(click_installdir, ".ini"); |
793 | + for (auto&& path : click_paths) |
794 | + { |
795 | + filesystem::path p(path); |
796 | + string file_name = p.filename().native(); |
797 | + string scope_id = p.stem().native(); |
798 | + if (local_scopes.find(scope_id) == local_scopes.end()) |
799 | + { |
800 | + click_scopes[scope_id] = path; |
801 | + } |
802 | + else |
803 | + { |
804 | + error("ignoring non-overrideable scope config \"" + file_name + "\" in click directory " + click_installdir); |
805 | + } |
806 | + } |
807 | + } |
808 | + catch (ResourceException const& e) |
809 | + { |
810 | + error(e.what()); |
811 | + error("could not open Click installation directory, ignoring Click scopes"); |
812 | + } |
813 | + } |
814 | + |
815 | + return click_scopes; |
816 | +} |
817 | + |
818 | // For each scope, open the config file for the scope, create the metadata info from the config, |
819 | // and add an entry to the RegistryObject. |
820 | |
821 | @@ -156,18 +232,19 @@ |
822 | map<string, string> const& all_scopes, |
823 | MiddlewareBase::SPtr const& mw, |
824 | string const& scoperunner_path, |
825 | - string const& config_file) |
826 | + string const& config_file, |
827 | + bool click) |
828 | { |
829 | for (auto&& pair : all_scopes) |
830 | { |
831 | try |
832 | { |
833 | unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(mw.get())); |
834 | - ScopeConfig sc(pair.second); |
835 | + string scope_config(pair.second); |
836 | + ScopeConfig sc(scope_config); |
837 | |
838 | - // dirname modifies its argument, so we need a copy of scope ini path. |
839 | - std::vector<char> scope_ini(pair.second.c_str(), pair.second.c_str() + pair.second.size() + 1); |
840 | - const std::string scope_dir(dirname(&scope_ini[0])); |
841 | + filesystem::path scope_path(scope_config); |
842 | + filesystem::path scope_dir(scope_path.parent_path()); |
843 | |
844 | mi->set_scope_id(pair.first); |
845 | mi->set_display_name(sc.display_name()); |
846 | @@ -175,17 +252,24 @@ |
847 | mi->set_author(sc.author()); |
848 | mi->set_invisible(sc.invisible()); |
849 | mi->set_appearance_attributes(sc.appearance_attributes()); |
850 | - mi->set_scope_directory(scope_dir); |
851 | + mi->set_scope_directory(scope_dir.native()); |
852 | + |
853 | + if (click && (sc.confinement_type() == ConfinementType::Trusted)) |
854 | + { |
855 | + throw unity::InvalidArgumentException("Invalid type, Trusted for click scope: " + pair.first); |
856 | + } |
857 | + mi->set_confinement_type(sc.confinement_type()); |
858 | + |
859 | try |
860 | { |
861 | - mi->set_art(relative_scope_path_to_abs_path(sc.art(), scope_dir)); |
862 | + mi->set_art(relative_scope_path_to_abs_path(sc.art(), scope_dir).native()); |
863 | } |
864 | catch (NotFoundException const&) |
865 | { |
866 | } |
867 | try |
868 | { |
869 | - mi->set_icon(relative_scope_path_to_abs_path(sc.icon(), scope_dir)); |
870 | + mi->set_icon(relative_scope_path_to_abs_path(sc.icon(), scope_dir).native()); |
871 | } |
872 | catch (NotFoundException const&) |
873 | { |
874 | @@ -220,7 +304,7 @@ |
875 | { |
876 | throw unity::InvalidArgumentException("Invalid scope runner executable for scope: " + pair.first); |
877 | } |
878 | - exec_data.scoperunner_path = relative_scope_path_to_abs_path(custom_exec, scope_dir); |
879 | + exec_data.scoperunner_path = relative_scope_path_to_abs_path(custom_exec, scope_dir).native(); |
880 | } |
881 | catch (NotFoundException const&) |
882 | { |
883 | @@ -278,29 +362,7 @@ |
884 | |
885 | try |
886 | { |
887 | - // We shutdown the runtime whenever these signals happen. |
888 | - auto termination_trap = core::posix::trap_signals_for_all_subsequent_threads( |
889 | - { |
890 | - core::posix::Signal::sig_int, |
891 | - core::posix::Signal::sig_hup, |
892 | - core::posix::Signal::sig_term |
893 | - }); |
894 | - |
895 | - // And we maintain our list of processes with the help of sig_chld. |
896 | - auto child_trap = core::posix::trap_signals_for_all_subsequent_threads( |
897 | - { |
898 | - core::posix::Signal::sig_chld |
899 | - }); |
900 | - |
901 | - // The death observer is required to make sure that we reap all child processes |
902 | - // whenever multiple sigchld's are compressed together. |
903 | - auto death_observer = |
904 | - core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap( |
905 | - child_trap); |
906 | - |
907 | - // Starting up both traps. |
908 | - std::thread termination_trap_worker([termination_trap]() { termination_trap->run(); }); |
909 | - std::thread child_trap_worker([child_trap]() { child_trap->run(); }); |
910 | + SignalThreadWrapper signal_handler_wrapper; |
911 | |
912 | // And finally creating our runtime. |
913 | RuntimeConfig rt_config(config_file); |
914 | @@ -315,6 +377,7 @@ |
915 | string mw_configfile; |
916 | string scope_installdir; |
917 | string oem_installdir; |
918 | + string click_installdir; |
919 | string scoperunner_path; |
920 | string ss_reg_id; |
921 | string ss_reg_endpoint; |
922 | @@ -325,6 +388,7 @@ |
923 | mw_configfile = c.mw_configfile(); |
924 | scope_installdir = c.scope_installdir(); |
925 | oem_installdir = c.oem_installdir(); |
926 | + click_installdir = c.click_installdir(); |
927 | scoperunner_path = c.scoperunner_path(); |
928 | ss_reg_id = c.ss_registry_identity(); |
929 | ss_reg_endpoint = c.ss_registry_endpoint(); |
930 | @@ -334,7 +398,7 @@ |
931 | |
932 | // Inform the signal thread that it should shutdown the middleware |
933 | // if we get a termination signal. |
934 | - termination_trap->signal_raised().connect([middleware](core::posix::Signal signal) |
935 | + signal_handler_wrapper.signal_raised().connect([middleware](core::posix::Signal signal) |
936 | { |
937 | switch(signal) |
938 | { |
939 | @@ -349,25 +413,28 @@ |
940 | }); |
941 | |
942 | // The registry object stores the local and remote scopes |
943 | - RegistryObject::SPtr registry(new RegistryObject(*death_observer)); |
944 | + RegistryObject::SPtr registry(new RegistryObject(*signal_handler_wrapper.death_observer)); |
945 | |
946 | // Add the metadata for each scope to the lookup table. |
947 | // We do this before starting any of the scopes, so aggregating scopes don't get a lookup failure if |
948 | // they look for another scope in the registry. |
949 | |
950 | auto local_scopes = find_local_scopes(scope_installdir, oem_installdir); |
951 | + auto click_scopes = find_click_scopes(local_scopes, click_installdir); |
952 | |
953 | // Before we add the local scopes, we check whether any scopes were explicitly specified |
954 | // on the command line. If so, scopes on the command line override scopes in |
955 | // configuration files. |
956 | for (auto i = 2; i < argc; ++i) |
957 | { |
958 | - string file_name = basename(const_cast<char*>(string(argv[i]).c_str())); // basename() modifies its argument |
959 | - string scope_id = strip_suffix(file_name, ".ini"); |
960 | + filesystem::path path(argv[i]); |
961 | + string scope_id = path.stem().native(); |
962 | local_scopes[scope_id] = argv[i]; // operator[] overwrites pre-existing entries |
963 | } |
964 | |
965 | - add_local_scopes(registry, local_scopes, middleware, scoperunner_path, runtime->configfile()); |
966 | + add_local_scopes(registry, local_scopes, middleware, scoperunner_path, runtime->configfile(), false); |
967 | + add_local_scopes(registry, click_scopes, middleware, scoperunner_path, runtime->configfile(), true); |
968 | + local_scopes.insert(click_scopes.begin(), click_scopes.end()); |
969 | if (ss_reg_id.empty() || ss_reg_endpoint.empty()) |
970 | { |
971 | error("no remote registry configured, only local scopes will be available"); |
972 | @@ -415,18 +482,6 @@ |
973 | // Wait until we are done, which happens if we receive a termination signal. |
974 | middleware->wait_for_shutdown(); |
975 | |
976 | - // Stop termination_trap |
977 | - termination_trap->stop(); |
978 | - if (termination_trap_worker.joinable()) |
979 | - termination_trap_worker.join(); |
980 | - |
981 | - // Please note that the child_trap must only be stopped once the |
982 | - // termination_trap thread has been joined. We otherwise will encounter |
983 | - // a race between the middleware shutting down and not receiving sigchld anymore. |
984 | - child_trap->stop(); |
985 | - if (child_trap_worker.joinable()) |
986 | - child_trap_worker.join(); |
987 | - |
988 | exit_status = 0; |
989 | } |
990 | catch (std::exception const& e) |
991 | |
992 | === modified file 'scoperunner/scoperunner.cpp' |
993 | --- scoperunner/scoperunner.cpp 2014-04-03 14:49:30 +0000 |
994 | +++ scoperunner/scoperunner.cpp 2014-04-08 16:22:25 +0000 |
995 | @@ -21,6 +21,7 @@ |
996 | #include <unity/scopes/internal/RegistryConfig.h> |
997 | #include <unity/scopes/internal/RuntimeConfig.h> |
998 | #include <unity/scopes/internal/RuntimeImpl.h> |
999 | +#include <unity/scopes/internal/ScopeConfig.h> |
1000 | #include <unity/scopes/internal/ScopeLoader.h> |
1001 | #include <unity/scopes/internal/ScopeObject.h> |
1002 | #include <unity/scopes/internal/ThreadSafeQueue.h> |
1003 | @@ -32,15 +33,21 @@ |
1004 | #include <cassert> |
1005 | #include <future> |
1006 | #include <iostream> |
1007 | +#include <sstream> |
1008 | #include <string> |
1009 | #include <unordered_map> |
1010 | #include <vector> |
1011 | |
1012 | #include <libgen.h> |
1013 | |
1014 | +#include <boost/filesystem/path.hpp> |
1015 | + |
1016 | +#include <sys/apparmor.h> |
1017 | + |
1018 | using namespace std; |
1019 | using namespace unity::scopes; |
1020 | using namespace unity::scopes::internal; |
1021 | +using namespace boost; |
1022 | |
1023 | namespace |
1024 | { |
1025 | @@ -53,66 +60,66 @@ |
1026 | cerr << prog_name << ": " << msg << endl; |
1027 | } |
1028 | |
1029 | -bool has_suffix(string const& s, string const& suffix) |
1030 | -{ |
1031 | - auto s_len = s.length(); |
1032 | - auto suffix_len = suffix.length(); |
1033 | - if (s_len >= suffix_len) |
1034 | - { |
1035 | - return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; |
1036 | - } |
1037 | - return false; |
1038 | -} |
1039 | - |
1040 | -string strip_suffix(string const& s, string const& suffix) |
1041 | -{ |
1042 | - auto s_len = s.length(); |
1043 | - auto suffix_len = suffix.length(); |
1044 | - if (s_len >= suffix_len) |
1045 | - { |
1046 | - if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) |
1047 | - { |
1048 | - return string(s, 0, s_len - suffix_len); |
1049 | - } |
1050 | - } |
1051 | - return s; |
1052 | -} |
1053 | - |
1054 | -// One thread for each scope, plus a future that the thread sets when it finishes. |
1055 | - |
1056 | -struct ThreadFuture |
1057 | -{ |
1058 | - thread t; |
1059 | - std::future<void> f; |
1060 | -}; |
1061 | - |
1062 | -// Each thread provides its own ID on a queue when it finishes. That allows us to |
1063 | -// then locate the thread in the map. The promise is set by the thread so we can |
1064 | -// find out what happened to it and join with it. Unfortunately, we have to jump |
1065 | -// through these hoops because there is no way to wait on multiple futures in C++ 11. |
1066 | - |
1067 | -unordered_map<thread::id, ThreadFuture> threads; |
1068 | - |
1069 | -ThreadSafeQueue<thread::id> finished_threads; |
1070 | - |
1071 | -// Scope thread start function. |
1072 | - |
1073 | -void scope_thread(std::shared_ptr<core::posix::SignalTrap> trap, |
1074 | - MWStateReceiverProxy reg_state_receiver, |
1075 | - string const& mw_kind, |
1076 | - string const& mw_config, |
1077 | - string const& runtime_config, |
1078 | - string const& scope_id, |
1079 | - string const& lib_dir, |
1080 | - promise<void> finished_promise) |
1081 | -{ |
1082 | +// Run the scope specified by the config_file in a separate thread and wait for the thread to finish. |
1083 | +// Return exit status for main to use. |
1084 | + |
1085 | +int run_scope(filesystem::path const& runtime_config, filesystem::path const& scope_config) |
1086 | +{ |
1087 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
1088 | + { |
1089 | + core::posix::Signal::sig_hup, |
1090 | + core::posix::Signal::sig_term |
1091 | + }); |
1092 | + |
1093 | + std::thread trap_worker([trap]() { trap->run(); }); |
1094 | + |
1095 | + // Retrieve the registry middleware and create a proxy to its state receiver |
1096 | + RuntimeConfig rt_config(runtime_config.native()); |
1097 | + RegistryConfig reg_conf(rt_config.registry_identity(), rt_config.registry_configfile()); |
1098 | + auto reg_runtime = RuntimeImpl::create(rt_config.registry_identity(), runtime_config.native()); |
1099 | + auto reg_mw = reg_runtime->factory()->find(reg_runtime->registry_identity(), reg_conf.mw_kind()); |
1100 | + auto reg_state_receiver = reg_mw->create_state_receiver_proxy("StateReceiver"); |
1101 | + |
1102 | + string lib_dir = scope_config.parent_path().native(); |
1103 | + string scope_id = scope_config.stem().native(); |
1104 | + |
1105 | + int exit_status = 1; |
1106 | try |
1107 | { |
1108 | // Instantiate the run time, create the middleware, load the scope from its |
1109 | // shared library, and call the scope's start() method. |
1110 | - auto rt = RuntimeImpl::create(scope_id, runtime_config); |
1111 | - auto mw = rt->factory()->create(scope_id, mw_kind, mw_config); |
1112 | - ScopeLoader::SPtr loader = ScopeLoader::load(scope_id, lib_dir + "lib" + scope_id + ".so", rt->registry()); |
1113 | + auto rt = RuntimeImpl::create(scope_id, runtime_config.native()); |
1114 | + auto mw = rt->factory()->create(scope_id, reg_conf.mw_kind(), reg_conf.mw_configfile()); |
1115 | + |
1116 | + ScopeConfig sc(scope_config.c_str()); |
1117 | + |
1118 | + // Drop our privileges |
1119 | + string profile; |
1120 | + switch (sc.confinement_type()) |
1121 | + { |
1122 | + case ConfinementType::Trusted: |
1123 | + break; |
1124 | + case ConfinementType::UntrustedLocal: |
1125 | + profile = "unity-scope-local"; |
1126 | + break; |
1127 | + case ConfinementType::UntrustedInternet: |
1128 | + profile = "unity-scope-internet"; |
1129 | + break; |
1130 | + } |
1131 | + |
1132 | + if (!profile.empty()) |
1133 | + { |
1134 | + int profile_change_code = aa_change_profile(profile.c_str()); |
1135 | + if (profile_change_code != 0) |
1136 | + { |
1137 | + ostringstream message; |
1138 | + message << "Couldn't change to AppArmor profile [" << profile |
1139 | + << "] error = [" << profile_change_code << "]"; |
1140 | + throw ConfigException(message.str()); |
1141 | + } |
1142 | + } |
1143 | + |
1144 | + ScopeLoader::SPtr loader = ScopeLoader::load(scope_id, lib_dir + "/lib" + scope_id + ".so", rt->registry()); |
1145 | loader->start(); |
1146 | |
1147 | // Give a thread to the scope to do with as it likes. If the scope doesn't want to use it and |
1148 | @@ -141,82 +148,15 @@ |
1149 | // destructor will still call stop() on the scope. |
1150 | run_future.get(); |
1151 | |
1152 | - finished_promise.set_value(); |
1153 | + exit_status = 0; |
1154 | + } |
1155 | + catch (std::exception const& e) |
1156 | + { |
1157 | + error(e.what()); |
1158 | } |
1159 | catch (...) |
1160 | { |
1161 | - finished_promise.set_exception(current_exception()); |
1162 | - } |
1163 | - |
1164 | - finished_threads.push(this_thread::get_id()); |
1165 | -} |
1166 | - |
1167 | -// Run each of the scopes in config_files in a separate thread and wait for each thread to finish. |
1168 | -// Return the number of threads that did not terminate normally. |
1169 | - |
1170 | -int run_scopes(string const& runtime_config, vector<string> config_files) |
1171 | -{ |
1172 | - auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
1173 | - { |
1174 | - core::posix::Signal::sig_hup, |
1175 | - core::posix::Signal::sig_term |
1176 | - }); |
1177 | - |
1178 | - std::thread trap_worker([trap]() { trap->run(); }); |
1179 | - |
1180 | - // Retrieve the registry middleware and create a proxy to its state receiver |
1181 | - RuntimeConfig rt_config(runtime_config); |
1182 | - RegistryConfig reg_conf(rt_config.registry_identity(), rt_config.registry_configfile()); |
1183 | - auto reg_runtime = RuntimeImpl::create(rt_config.registry_identity(), runtime_config); |
1184 | - auto reg_mw = reg_runtime->factory()->find(reg_runtime->registry_identity(), reg_conf.mw_kind()); |
1185 | - auto reg_state_receiver = reg_mw->create_state_receiver_proxy("StateReceiver"); |
1186 | - |
1187 | - for (auto file : config_files) |
1188 | - { |
1189 | - string file_name = basename(const_cast<char*>(string(file).c_str())); // basename() modifies its argument |
1190 | - auto dir_len = file.size() - file_name.size(); |
1191 | - string dir = file.substr(0, dir_len); |
1192 | - if (*dir.rbegin() != '/') |
1193 | - { |
1194 | - dir += "/"; |
1195 | - } |
1196 | - string scope_id = strip_suffix(file_name, ".ini"); |
1197 | - |
1198 | - // For each scope, create a thread that loads the scope and initializes it. |
1199 | - // Each thread gets a promise to indicate when it is finished. When a thread |
1200 | - // completes, it fulfils the promise, and pushes its ID onto the finished queue. |
1201 | - // We collect exit status from the thread via the future from each promise. |
1202 | - promise<void> p; |
1203 | - auto f = p.get_future(); |
1204 | - thread t(scope_thread, trap, reg_state_receiver, reg_conf.mw_kind(), reg_conf.mw_configfile(), |
1205 | - runtime_config, scope_id, dir, move(p)); |
1206 | - |
1207 | - auto id = t.get_id(); |
1208 | - threads[id] = ThreadFuture { move(t), move(f) }; |
1209 | - } |
1210 | - |
1211 | - // Now wait for the threads to finish (in any order). |
1212 | - int num_errors = 0; |
1213 | - for (int i = threads.size(); i > 0; --i) |
1214 | - { |
1215 | - try |
1216 | - { |
1217 | - auto id = finished_threads.wait_and_pop(); |
1218 | - auto it = threads.find(id); |
1219 | - assert(it != threads.end()); |
1220 | - it->second.t.join(); |
1221 | - it->second.f.get(); // This will throw if the thread terminated due to an exception |
1222 | - } |
1223 | - catch (std::exception const& e) |
1224 | - { |
1225 | - error(e.what()); |
1226 | - ++num_errors; |
1227 | - } |
1228 | - catch (...) |
1229 | - { |
1230 | - error("unknown exception"); |
1231 | - ++num_errors; |
1232 | - } |
1233 | + error("unknown exception"); |
1234 | } |
1235 | |
1236 | trap->stop(); |
1237 | @@ -224,7 +164,7 @@ |
1238 | if (trap_worker.joinable()) |
1239 | trap_worker.join(); |
1240 | |
1241 | - return num_errors; |
1242 | + return exit_status; |
1243 | } |
1244 | |
1245 | } // namespace |
1246 | @@ -240,27 +180,30 @@ |
1247 | ::pthread_sigmask(SIG_SETMASK, &set, nullptr); |
1248 | |
1249 | prog_name = basename(argv[0]); |
1250 | - if (argc < 3) |
1251 | + if (argc != 3) |
1252 | { |
1253 | - cerr << "usage: " << prog_name << " runtime.ini configfile.ini [configfile.ini ...]" << endl; |
1254 | + cerr << "usage: " << prog_name << " runtime.ini configfile.ini" << endl; |
1255 | return 2; |
1256 | } |
1257 | char const* const runtime_config = argv[1]; |
1258 | + char const* const scope_config = argv[2]; |
1259 | |
1260 | int exit_status = 1; |
1261 | try |
1262 | { |
1263 | - vector<string> config_files; |
1264 | - for (int i = 2; i < argc; ++i) |
1265 | - { |
1266 | - if (!has_suffix(argv[i], ".ini")) |
1267 | - { |
1268 | - throw ConfigException(string("invalid config file name: \"") + argv[i] + "\": missing .ini extension"); |
1269 | - } |
1270 | - config_files.push_back(argv[i]); |
1271 | - } |
1272 | - |
1273 | - exit_status = run_scopes(runtime_config, config_files); |
1274 | + filesystem::path runtime_path(runtime_config); |
1275 | + if (runtime_path.extension() != ".ini") |
1276 | + { |
1277 | + throw ConfigException(string("invalid runtime config file name: \"") + runtime_config + "\": missing .ini extension"); |
1278 | + } |
1279 | + |
1280 | + filesystem::path scope_path(scope_config); |
1281 | + if (scope_path.extension() != ".ini") |
1282 | + { |
1283 | + throw ConfigException(string("invalid scope config file name: \"") + scope_config + "\": missing .ini extension"); |
1284 | + } |
1285 | + |
1286 | + exit_status = run_scope(runtime_path, scope_path); |
1287 | } |
1288 | catch (std::exception const& e) |
1289 | { |
1290 | |
1291 | === modified file 'src/scopes/ScopeMetadata.cpp' |
1292 | --- src/scopes/ScopeMetadata.cpp 2014-04-02 16:54:53 +0000 |
1293 | +++ src/scopes/ScopeMetadata.cpp 2014-04-08 16:22:25 +0000 |
1294 | @@ -72,6 +72,11 @@ |
1295 | return p->scope_id(); |
1296 | } |
1297 | |
1298 | +ConfinementType ScopeMetadata::confinement_type() const |
1299 | +{ |
1300 | + return p->confinement_type(); |
1301 | +} |
1302 | + |
1303 | ScopeProxy ScopeMetadata::proxy() const |
1304 | { |
1305 | return p->proxy(); |
1306 | |
1307 | === modified file 'src/scopes/internal/RegistryConfig.cpp' |
1308 | --- src/scopes/internal/RegistryConfig.cpp 2014-01-28 03:12:35 +0000 |
1309 | +++ src/scopes/internal/RegistryConfig.cpp 2014-04-08 16:22:25 +0000 |
1310 | @@ -48,6 +48,11 @@ |
1311 | mw_configfile_ = get_string(REGISTRY_CONFIG_GROUP, mw_kind_ + ".ConfigFile"); |
1312 | scope_installdir_ = get_string(REGISTRY_CONFIG_GROUP, "Scope.InstallDir"); |
1313 | oem_installdir_ = get_optional_string(REGISTRY_CONFIG_GROUP, "OEM.InstallDir"); |
1314 | + click_installdir_ = get_optional_string(REGISTRY_CONFIG_GROUP, "Click.InstallDir"); |
1315 | + if (click_installdir_.empty()) |
1316 | + { |
1317 | + click_installdir_ = string(getenv("HOME")) + "/.local/share/unity-scopes/"; |
1318 | + } |
1319 | scoperunner_path_ = get_string(REGISTRY_CONFIG_GROUP, "Scoperunner.Path"); |
1320 | if (scoperunner_path_[0] != '/') |
1321 | { |
1322 | @@ -96,6 +101,11 @@ |
1323 | return oem_installdir_; |
1324 | } |
1325 | |
1326 | +string RegistryConfig::click_installdir() const |
1327 | +{ |
1328 | + return click_installdir_; |
1329 | +} |
1330 | + |
1331 | string RegistryConfig::scoperunner_path() const |
1332 | { |
1333 | return scoperunner_path_; |
1334 | |
1335 | === modified file 'src/scopes/internal/ScopeConfig.cpp' |
1336 | --- src/scopes/internal/ScopeConfig.cpp 2014-03-31 16:05:42 +0000 |
1337 | +++ src/scopes/internal/ScopeConfig.cpp 2014-04-08 16:22:25 +0000 |
1338 | @@ -39,6 +39,7 @@ |
1339 | { |
1340 | const string overrideable_str = "Override"; |
1341 | const string scope_id_str = "DisplayName"; |
1342 | + const string scope_confinement_type_str = "ConfinementType"; |
1343 | const string description_str = "Description"; |
1344 | const string author_str = "Author"; |
1345 | const string art_str = "Art"; |
1346 | @@ -47,6 +48,10 @@ |
1347 | const string hot_key_str = "HotKey"; |
1348 | const string invisible_str = "Invisible"; |
1349 | const string scope_runner_exec = "ScopeRunner"; |
1350 | + |
1351 | + const string scope_confinement_type_trusted_str = "Trusted"; |
1352 | + const string scope_confinement_type_untrusted_local_str = "UntrustedLocal"; |
1353 | + const string scope_confinement_type_untrusted_internet_str = "UntrustedInternet"; |
1354 | } |
1355 | |
1356 | ScopeConfig::ScopeConfig(string const& configfile) : |
1357 | @@ -60,6 +65,28 @@ |
1358 | { |
1359 | overrideable_ = false; |
1360 | } |
1361 | + |
1362 | + confinement_type_ = ConfinementType::Trusted; |
1363 | + try |
1364 | + { |
1365 | + string confinement_type = parser()->get_string(SCOPE_CONFIG_GROUP, scope_confinement_type_str); |
1366 | + if (confinement_type == scope_confinement_type_trusted_str) |
1367 | + { |
1368 | + confinement_type_ = ConfinementType::Trusted; |
1369 | + } |
1370 | + else if (confinement_type == scope_confinement_type_untrusted_local_str) |
1371 | + { |
1372 | + confinement_type_ = ConfinementType::UntrustedLocal; |
1373 | + } |
1374 | + else if (confinement_type == scope_confinement_type_untrusted_internet_str) |
1375 | + { |
1376 | + confinement_type_ = ConfinementType::UntrustedInternet; |
1377 | + } |
1378 | + } |
1379 | + catch (LogicException const& e) |
1380 | + { |
1381 | + } |
1382 | + |
1383 | display_name_ = parser()->get_string(SCOPE_CONFIG_GROUP, scope_id_str); |
1384 | description_ = parser()->get_string(SCOPE_CONFIG_GROUP, description_str); |
1385 | author_ = parser()->get_string(SCOPE_CONFIG_GROUP, author_str); |
1386 | @@ -141,6 +168,11 @@ |
1387 | return overrideable_; |
1388 | } |
1389 | |
1390 | +ConfinementType ScopeConfig::confinement_type() const |
1391 | +{ |
1392 | + return confinement_type_; |
1393 | +} |
1394 | + |
1395 | string ScopeConfig::display_name() const |
1396 | { |
1397 | return display_name_; |
1398 | |
1399 | === modified file 'src/scopes/internal/ScopeMetadataImpl.cpp' |
1400 | --- src/scopes/internal/ScopeMetadataImpl.cpp 2014-04-02 17:05:14 +0000 |
1401 | +++ src/scopes/internal/ScopeMetadataImpl.cpp 2014-04-08 16:22:25 +0000 |
1402 | @@ -36,7 +36,7 @@ |
1403 | { |
1404 | |
1405 | ScopeMetadataImpl::ScopeMetadataImpl(MiddlewareBase* mw) : |
1406 | - mw_(mw) |
1407 | + mw_(mw), confinement_type_(ConfinementType::Trusted) |
1408 | { |
1409 | } |
1410 | |
1411 | @@ -49,6 +49,7 @@ |
1412 | ScopeMetadataImpl::ScopeMetadataImpl(ScopeMetadataImpl const& other) : |
1413 | mw_(other.mw_), |
1414 | scope_id_(other.scope_id_), |
1415 | + confinement_type_(other.confinement_type_), |
1416 | proxy_(other.proxy_), |
1417 | display_name_(other.display_name_), |
1418 | description_(other.description_), |
1419 | @@ -87,6 +88,7 @@ |
1420 | { |
1421 | mw_ = rhs.mw_; |
1422 | scope_id_ = rhs.scope_id_; |
1423 | + confinement_type_ = rhs.confinement_type_; |
1424 | proxy_ = rhs.proxy_; |
1425 | display_name_ = rhs.display_name_; |
1426 | description_ = rhs.description_; |
1427 | @@ -107,6 +109,11 @@ |
1428 | return scope_id_; |
1429 | } |
1430 | |
1431 | +ConfinementType ScopeMetadataImpl::confinement_type() const |
1432 | +{ |
1433 | + return confinement_type_; |
1434 | +} |
1435 | + |
1436 | ScopeProxy ScopeMetadataImpl::proxy() const |
1437 | { |
1438 | return proxy_; |
1439 | @@ -191,6 +198,11 @@ |
1440 | scope_id_ = scope_id; |
1441 | } |
1442 | |
1443 | +void ScopeMetadataImpl::set_confinement_type(ConfinementType confinement_type) |
1444 | +{ |
1445 | + confinement_type_ = confinement_type; |
1446 | +} |
1447 | + |
1448 | void ScopeMetadataImpl::set_proxy(ScopeProxy const& proxy) |
1449 | { |
1450 | proxy_ = proxy; |
1451 | @@ -272,6 +284,7 @@ |
1452 | |
1453 | VariantMap var; |
1454 | var["scope_id"] = scope_id_; |
1455 | + var["confinement_type"] = (int) confinement_type_; |
1456 | VariantMap proxy; |
1457 | proxy["identity"] = proxy_->identity(); |
1458 | proxy["endpoint"] = proxy_->endpoint(); |
1459 | @@ -364,6 +377,9 @@ |
1460 | |
1461 | // Optional fields |
1462 | |
1463 | + it = var.find("confinement_type"); |
1464 | + confinement_type_ = (ConfinementType) it->second.get_int(); |
1465 | + |
1466 | it = var.find("art"); |
1467 | if (it != var.end()) |
1468 | { |
1469 | |
1470 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
1471 | --- test/gtest/scopes/Registry/Registry_test.cpp 2014-04-02 16:54:53 +0000 |
1472 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2014-04-08 16:22:25 +0000 |
1473 | @@ -21,6 +21,9 @@ |
1474 | #include <unity/scopes/SearchMetadata.h> |
1475 | #include <unity/scopes/SearchListenerBase.h> |
1476 | #include <unity/scopes/CategorisedResult.h> |
1477 | +#include <boost/filesystem.hpp> |
1478 | +#include <boost/system/error_code.hpp> |
1479 | +#include <boost/filesystem/operations.hpp> |
1480 | #include <functional> |
1481 | #include <gtest/gtest.h> |
1482 | #include <signal.h> |
1483 | @@ -86,6 +89,23 @@ |
1484 | } |
1485 | } |
1486 | |
1487 | +bool wait_for_registry() |
1488 | +{ |
1489 | + const int num_retries = 10; |
1490 | + const boost::filesystem::path path("/tmp/RegistryTest"); |
1491 | + for (int i = 0; i<num_retries; i++) |
1492 | + { |
1493 | + if (boost::filesystem::exists(path)) |
1494 | + { |
1495 | + boost::system::error_code error; |
1496 | + auto st = boost::filesystem::status(path, error).type(); |
1497 | + return st == boost::filesystem::file_type::socket_file; |
1498 | + } |
1499 | + sleep(1); |
1500 | + } |
1501 | + return false; |
1502 | +} |
1503 | + |
1504 | int main(int argc, char **argv) |
1505 | { |
1506 | ::testing::InitGoogleTest(&argc, argv); |
1507 | @@ -102,6 +122,8 @@ |
1508 | } |
1509 | else if (rpid > 0) |
1510 | { |
1511 | + // FIXME: remove this once we have async queries and can set arbitrary timeout when calling registry |
1512 | + EXPECT_TRUE(wait_for_registry()); |
1513 | auto rc = RUN_ALL_TESTS(); |
1514 | kill(rpid, SIGTERM); |
1515 | return rc; |
1516 | |
1517 | === modified file 'test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp' |
1518 | --- test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 2014-04-03 16:46:00 +0000 |
1519 | +++ test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 2014-04-08 16:22:25 +0000 |
1520 | @@ -234,6 +234,7 @@ |
1521 | |
1522 | unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(&mw)); |
1523 | mi->set_scope_id("scope_id"); |
1524 | + mi->set_confinement_type(ConfinementType::UntrustedLocal); |
1525 | auto mw_proxy = mw.create_scope_proxy("identity", "endpoint"); |
1526 | mi->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime(), "scope_id")); |
1527 | mi->set_display_name("display_name"); |
1528 | @@ -249,8 +250,9 @@ |
1529 | // Check that serialize() sets the map values correctly |
1530 | auto m = ScopeMetadataImpl::create(move(mi)); |
1531 | auto var = m.serialize(); |
1532 | - EXPECT_EQ(11u, var.size()); |
1533 | + EXPECT_EQ(12u, var.size()); |
1534 | EXPECT_EQ("scope_id", var["scope_id"].get_string()); |
1535 | + EXPECT_EQ(ConfinementType::UntrustedLocal, (ConfinementType) var["confinement_type"].get_int()); |
1536 | EXPECT_EQ("display_name", var["display_name"].get_string()); |
1537 | EXPECT_EQ("description", var["description"].get_string()); |
1538 | EXPECT_EQ("author", var["author"].get_string()); |
1539 | @@ -264,6 +266,7 @@ |
1540 | // Make another instance from the VariantMap and check its fields |
1541 | ScopeMetadataImpl c(var, &mw); |
1542 | EXPECT_EQ("scope_id", c.scope_id()); |
1543 | + EXPECT_EQ(ConfinementType::UntrustedLocal, c.confinement_type()); |
1544 | EXPECT_EQ("identity", c.proxy()->identity()); |
1545 | EXPECT_EQ("endpoint", c.proxy()->endpoint()); |
1546 | EXPECT_EQ("display_name", c.display_name()); |
1547 | @@ -448,6 +451,7 @@ |
1548 | m["author"] = "author"; |
1549 | |
1550 | // Optional attributes |
1551 | + m["confinement_type"] = (int) ConfinementType::UntrustedLocal; |
1552 | m["art"] = "art"; |
1553 | m["icon"] = "icon"; |
1554 | m["search_hint"] = "search_hint"; |
1555 | |
1556 | === modified file 'test/whitespace/CMakeLists.txt' |
1557 | --- test/whitespace/CMakeLists.txt 2013-05-29 04:57:50 +0000 |
1558 | +++ test/whitespace/CMakeLists.txt 2014-04-08 16:22:25 +0000 |
1559 | @@ -2,4 +2,8 @@ |
1560 | # Test that all source files, cmakefiles, etc. do not contain trailing whitespace. |
1561 | # |
1562 | |
1563 | -add_test(whitespace ${CMAKE_CURRENT_SOURCE_DIR}/check_whitespace.py ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) |
1564 | +add_test(whitespace |
1565 | + ${CMAKE_CURRENT_SOURCE_DIR}/check_whitespace.py |
1566 | + ${CMAKE_SOURCE_DIR} |
1567 | + ${CMAKE_BINARY_DIR} |
1568 | +) |
1569 | |
1570 | === modified file 'test/whitespace/check_whitespace.py' |
1571 | --- test/whitespace/check_whitespace.py 2013-06-27 08:38:02 +0000 |
1572 | +++ test/whitespace/check_whitespace.py 2014-04-08 16:22:25 +0000 |
1573 | @@ -80,7 +80,7 @@ |
1574 | |
1575 | parser = argparse.ArgumentParser(description = 'Test that source files do not contain trailing whitespace.') |
1576 | parser.add_argument('dir', nargs = 1, help = 'The directory to (recursively) search for source files') |
1577 | -parser.add_argument('ignore_prefix', nargs = '?', default=None, |
1578 | +parser.add_argument('ignore_prefix', nargs = '+', default=None, |
1579 | help = 'Ignore source files with a path that starts with the given prefix.') |
1580 | args = parser.parse_args() |
1581 | |
1582 | @@ -93,16 +93,20 @@ |
1583 | # directory and check them for trailing whitespace. |
1584 | |
1585 | directory = os.path.abspath(args.dir[0]) |
1586 | -ignore = args.ignore_prefix and os.path.abspath(args.ignore_prefix) or None |
1587 | +ignores = args.ignore_prefix and args.ignore_prefix or [] |
1588 | |
1589 | found_whitespace = False |
1590 | try: |
1591 | for root, dirs, files in os.walk(directory, onerror = raise_error): |
1592 | for file in files: |
1593 | path = os.path.join(root, file) |
1594 | - if not (ignore and path.startswith(ignore)) and pat.match(file): |
1595 | - if scan_for_bad_whitespace(path): |
1596 | - found_whitespace = True |
1597 | + ignored = False |
1598 | + for ignore in ignores: |
1599 | + if ignore and path.startswith(os.path.abspath(ignore)): |
1600 | + ignored = True |
1601 | + break |
1602 | + if not ignored and pat.match(file) and scan_for_bad_whitespace(path): |
1603 | + found_whitespace = True |
1604 | |
1605 | except OSError as e: |
1606 | error("cannot create file list for \"" + dir + "\": " + e.strerror) |
1607 | |
1608 | === removed file 'test/whitespace/check_whitespace.sh' |
1609 | --- test/whitespace/check_whitespace.sh 2013-06-27 08:38:02 +0000 |
1610 | +++ test/whitespace/check_whitespace.sh 1970-01-01 00:00:00 +0000 |
1611 | @@ -1,62 +0,0 @@ |
1612 | -#!/bin/sh |
1613 | - |
1614 | -# |
1615 | -# Copyright (C) 2013 Canonical Ltd |
1616 | -# |
1617 | -# This program is free software: you can redistribute it and/or modify |
1618 | -# it under the terms of the GNU Lesser General Public License version 3 as |
1619 | -# published by the Free Software Foundation. |
1620 | -# |
1621 | -# This program is distributed in the hope that it will be useful, |
1622 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1623 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1624 | -# GNU Lesser General Public License for more details. |
1625 | -# |
1626 | -# You should have received a copy of the GNU Lesser General Public License |
1627 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1628 | -# |
1629 | -# Authored by: Michi Henning <michi.henning@canonical.com> |
1630 | -# |
1631 | - |
1632 | -# |
1633 | -# Check that files below the specified directory don't have lines with trailing whitespace. |
1634 | -# Print out a messsage for each file with trailing whitespace and exit with non-zero status |
1635 | -# if any such file is found. |
1636 | -# |
1637 | - |
1638 | -usage() |
1639 | -{ |
1640 | - echo "usage: check_whitespace.sh dir [ignore_dir]" >&2 |
1641 | - exit 2 |
1642 | -} |
1643 | - |
1644 | -[ $# -lt 1 ] && usage |
1645 | -[ $# -gt 2 ] && usage |
1646 | - |
1647 | -ignore="grep -v CMakeFile" |
1648 | - |
1649 | -[ $# -eq 2 ] && { |
1650 | - ignore="$ignore | grep -v \"$2\"" |
1651 | -} |
1652 | - |
1653 | -err=no |
1654 | -for file in `find "$1" \ |
1655 | - -name '*.cpp' -o \ |
1656 | - -name '*.h' -o \ |
1657 | - -name '*.py' -o \ |
1658 | - -name '*.sh' -o \ |
1659 | - -name 'CMakeLists.txt' -o \ |
1660 | - -name '*.cmake' \ |
1661 | - | grep -v CMakeFiles \ |
1662 | - | eval $ignore` |
1663 | -do |
1664 | - grep -q '[ ]$' "$file" |
1665 | - [ $? -eq 0 ] && { |
1666 | - echo "$file: trailing whitespace" |
1667 | - err=yes |
1668 | - } |
1669 | -done |
1670 | - |
1671 | -[ $err = yes ] && exit 1 |
1672 | - |
1673 | -exit 0 |