1 @@ -0,0 +1,697 @@
2 + From a0c130ca5afe06b42fcb887585d4b04d51224c5b Mon Sep 17 00:00:00 2001
3 + From: Simon Fels <morphis@gravedo.de>
4 + Date: Tue, 29 Aug 2017 01:35:04 +0200
5 + Subject: [PATCH 1002/1002] cmd/snap: add userd command to replace
6 + snapd-xdg-open (#3260)
7 +
8 + Based on discussion from
9 + https://forum.snapcraft.io/t/integrate-snapd-xdg-open-into-snapd/100
10 + ---
11 + .gitignore | 5 ++
12 + cmd/snap/cmd_userd.go | 74 ++++++++++++++++++++
13 + cmd/snap/cmd_userd_test.go | 70 ++++++++++++++++++
14 + data/Makefile | 3 +
15 + data/dbus/Makefile | 31 ++++++++
16 + data/dbus/io.snapcraft.Launcher.service.in | 3 +
17 + interfaces/builtin/unity7.go | 16 +++++
18 + testutil/dbustest.go | 69 ++++++++++++++++++
19 + userd/launcher.go | 88 +++++++++++++++++++++++
20 + userd/launcher_test.go | 81 +++++++++++++++++++++
21 + userd/userd.go | 109 +++++++++++++++++++++++++++++
22 + vendor/vendor.json | 12 +++-
23 + 12 files changed, 558 insertions(+), 3 deletions(-)
24 + create mode 100644 cmd/snap/cmd_userd.go
25 + create mode 100644 cmd/snap/cmd_userd_test.go
26 + create mode 100644 data/Makefile
27 + create mode 100644 data/dbus/Makefile
28 + create mode 100644 data/dbus/io.snapcraft.Launcher.service.in
29 + create mode 100644 testutil/dbustest.go
30 + create mode 100644 userd/launcher.go
31 + create mode 100644 userd/launcher_test.go
32 + create mode 100644 userd/userd.go
33 +
34 + diff --git a/.gitignore b/.gitignore
35 + index b9f8c3fdb..d48609e2b 100644
36 + --- a/.gitignore
37 + +++ b/.gitignore
38 + @@ -35,6 +35,11 @@ cmd/*/*.[1-9]
39 + data/systemd/*.service
40 + data/info
41 +
42 + +# auto-generated dbus services
43 + +data/dbus/*.service
44 + +
45 + +data/info
46 + +
47 + # test-driver
48 + *.log
49 + *.trs
50 + diff --git a/cmd/snap/cmd_userd.go b/cmd/snap/cmd_userd.go
51 + new file mode 100644
52 + index 000000000..17b75c5ab
53 + --- /dev/null
54 + +++ b/cmd/snap/cmd_userd.go
55 + @@ -0,0 +1,74 @@
56 + +// -*- Mode: Go; indent-tabs-mode: t -*-
57 + +
58 + +/*
59 + + * Copyright (C) 2017 Canonical Ltd
60 + + *
61 + + * This program is free software: you can redistribute it and/or modify
62 + + * it under the terms of the GNU General Public License version 3 as
63 + + * published by the Free Software Foundation.
64 + + *
65 + + * This program is distributed in the hope that it will be useful,
66 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
67 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68 + + * GNU General Public License for more details.
69 + + *
70 + + * You should have received a copy of the GNU General Public License
71 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
72 + + *
73 + + */
74 + +
75 + +package main
76 + +
77 + +import (
78 + +» "fmt"
79 + +» "os"
80 + +» "os/signal"
81 + +» "syscall"
82 + +
83 + +» "github.com/jessevdk/go-flags"
84 + +
85 + +» "github.com/snapcore/snapd/i18n"
86 + +» "github.com/snapcore/snapd/userd"
87 + +)
88 + +
89 + +type cmdUserd struct {
90 + +» userd userd.Userd
91 + +}
92 + +
93 + +var shortUserdHelp = i18n.G("Start the userd service")
94 + +var longUserdHelp = i18n.G("The userd command starts the snap user session service.")
95 + +
96 + +func init() {
97 + +» cmd := addCommand("userd",
98 + +» » shortAbortHelp,
99 + +» » longAbortHelp,
100 + +» » func() flags.Commander {
101 + +» » » return &cmdUserd{}
102 + +» » },
103 + +» » nil,
104 + +» » []argDesc{},
105 + +» )
106 + +» cmd.hidden = true
107 + +}
108 + +
109 + +func (x *cmdUserd) Execute(args []string) error {
110 + +» if len(args) > 0 {
111 + +» » return ErrExtraArgs
112 + +» }
113 + +
114 + +» if err := x.userd.Init(); err != nil {
115 + +» » return err
116 + +» }
117 + +» x.userd.Start()
118 + +
119 + +» ch := make(chan os.Signal)
120 + +» signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1)
121 + +» select {
122 + +» case sig := <-ch:
123 + +» » fmt.Fprintf(Stdout, "Exiting on %s.\n", sig)
124 + +» case <-x.userd.Dying():
125 + +» » // something called Stop()
126 + +» }
127 + +
128 + +» return x.userd.Stop()
129 + +}
130 + diff --git a/cmd/snap/cmd_userd_test.go b/cmd/snap/cmd_userd_test.go
131 + new file mode 100644
132 + index 000000000..ec134a205
133 + --- /dev/null
134 + +++ b/cmd/snap/cmd_userd_test.go
135 + @@ -0,0 +1,70 @@
136 + +// -*- Mode: Go; indent-tabs-mode: t -*-
137 + +
138 + +/*
139 + + * Copyright (C) 2016 Canonical Ltd
140 + + *
141 + + * This program is free software: you can redistribute it and/or modify
142 + + * it under the terms of the GNU General Public License version 3 as
143 + + * published by the Free Software Foundation.
144 + + *
145 + + * This program is distributed in the hope that it will be useful,
146 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
147 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
148 + + * GNU General Public License for more details.
149 + + *
150 + + * You should have received a copy of the GNU General Public License
151 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
152 + + *
153 + + */
154 + +
155 + +package main_test
156 + +
157 + +import (
158 + +» "os"
159 + +» "syscall"
160 + +» "time"
161 + +
162 + +» . "gopkg.in/check.v1"
163 + +
164 + +» snap "github.com/snapcore/snapd/cmd/snap"
165 + +» "github.com/snapcore/snapd/testutil"
166 + +)
167 + +
168 + +type userdSuite struct {
169 + +» BaseSnapSuite
170 + +» testutil.DBusTest
171 + +}
172 + +
173 + +var _ = Suite(&userdSuite{})
174 + +
175 + +func (s *userdSuite) TestUserdBadCommandline(c *C) {
176 + +» _, err := snap.Parser().ParseArgs([]string{"userd", "extra-arg"})
177 + +» c.Assert(err, ErrorMatches, "too many arguments for command")
178 + +}
179 + +
180 + +func (s *userdSuite) TestUserd(c *C) {
181 + +» go func() {
182 + +» » defer func() {
183 + +» » » me, err := os.FindProcess(os.Getpid())
184 + +» » » c.Assert(err, IsNil)
185 + +» » » me.Signal(syscall.SIGUSR1)
186 + +» » }()
187 + +
188 + +» » needle := "io.snapcraft.Launcher"
189 + +» » for i := 0; i < 10; i++ {
190 + +» » » for _, objName := range s.SessionBus.Names() {
191 + +» » » » if objName == needle {
192 + +» » » » » return
193 + +» » » » }
194 + +» » » » time.Sleep(1 * time.Second)
195 + +» » » }
196 + +
197 + +» » }
198 + +» » c.Fatalf("%s does not appeared on the bus", needle)
199 + +» }()
200 + +
201 + +» rest, err := snap.Parser().ParseArgs([]string{"userd"})
202 + +» c.Assert(err, IsNil)
203 + +» c.Check(rest, DeepEquals, []string{})
204 + +» c.Check(s.Stdout(), Equals, "Exiting on user defined signal 1.\n")
205 + +}
206 + diff --git a/data/Makefile b/data/Makefile
207 + new file mode 100644
208 + index 000000000..caece8c0c
209 + --- /dev/null
210 + +++ b/data/Makefile
211 + @@ -0,0 +1,3 @@
212 + +all install clean:
213 + +» $(MAKE) -C systemd $@
214 + +» $(MAKE) -C dbus $@
215 + diff --git a/data/dbus/Makefile b/data/dbus/Makefile
216 + new file mode 100644
217 + index 000000000..66cc14e86
218 + --- /dev/null
219 + +++ b/data/dbus/Makefile
220 + @@ -0,0 +1,31 @@
221 + +#
222 + +# Copyright (C) 2017 Canonical Ltd
223 + +#
224 + +# This program is free software: you can redistribute it and/or modify
225 + +# it under the terms of the GNU General Public License version 3 as
226 + +# published by the Free Software Foundation.
227 + +#
228 + +# This program is distributed in the hope that it will be useful,
229 + +# but WITHOUT ANY WARRANTY; without even the implied warranty of
230 + +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231 + +# GNU General Public License for more details.
232 + +#
233 + +# You should have received a copy of the GNU General Public License
234 + +# along with this program. If not, see <http://www.gnu.org/licenses/>.
235 + +
236 + +BINDIR := /usr/bin
237 + +DBUSSERVICESDIR := /usr/share/dbus-1/services
238 + +
239 + +SERVICES_GENERATED := $(patsubst %.service.in,%.service,$(wildcard *.service.in))
240 + +SERVICES := ${SERVICES_GENERATED}
241 + +
242 + +%.service: %.service.in
243 + +» cat $< | sed 's:@bindir@:${BINDIR}:g' | cat > $@
244 + +
245 + +all: ${SERVICES}
246 + +
247 + +install: ${SERVICES}
248 + +» install -D -m 0644 -t ${DESTDIR}/${DBUSSERVICESDIR} $^
249 + +
250 + +clean:
251 + +» rm -f ${SERVICES_GENERATED}
252 + diff --git a/data/dbus/io.snapcraft.Launcher.service.in b/data/dbus/io.snapcraft.Launcher.service.in
253 + new file mode 100644
254 + index 000000000..cd65b0aa0
255 + --- /dev/null
256 + +++ b/data/dbus/io.snapcraft.Launcher.service.in
257 + @@ -0,0 +1,3 @@
258 + +[D-BUS Service]
259 + +Name=io.snapcraft.Launcher
260 + +Exec=@bindir@/snap userd
261 + diff --git a/interfaces/builtin/unity7.go b/interfaces/builtin/unity7.go
262 + index c33075942..135c578cc 100644
263 + --- a/interfaces/builtin/unity7.go
264 + +++ b/interfaces/builtin/unity7.go
265 + @@ -88,12 +88,23 @@ const unity7ConnectedPlugAppArmor = `
266 + /usr/bin/xdg-open ixr,
267 + /usr/share/applications/{,*} r,
268 + /usr/bin/dbus-send ixr,
269 + +
270 + +# This allow access to the first version of the snapd-xdg-open
271 + +# version which was shipped outside of snapd
272 + dbus (send)
273 + bus=session
274 + path=/
275 + interface=com.canonical.SafeLauncher
276 + member=OpenURL
277 + peer=(label=unconfined),
278 + +# ... and this allows access to the new xdg-open service which
279 + +# is now part of snapd itself.
280 + +dbus (send)
281 + + bus=session
282 + + path=/io/snapcraft/Launcher
283 + + interface=io.snapcraft.Launcher
284 + + member=OpenURL
285 + + peer=(label=unconfined),
286 +
287 + # input methods (ibus)
288 + # subset of ibus abstraction
289 + @@ -305,6 +316,11 @@ dbus (send)
290 + bus=session
291 + interface=com.canonical.SafeLauncher.OpenURL
292 + peer=(label=unconfined),
293 + +# new url helper (part of snap userd)
294 + +dbus (send)
295 + + bus=session
296 + + interface=io.snapcraft.Launcher.OpenURL
297 + + peer=(label=unconfined),
298 +
299 + # dbusmenu
300 + dbus (send)
301 + diff --git a/testutil/dbustest.go b/testutil/dbustest.go
302 + new file mode 100644
303 + index 000000000..4f7b5f580
304 + --- /dev/null
305 + +++ b/testutil/dbustest.go
306 + @@ -0,0 +1,69 @@
307 + +// -*- Mode: Go; indent-tabs-mode: t -*-
308 + +
309 + +/*
310 + + * Copyright (C) 2015 Canonical Ltd
311 + + *
312 + + * This program is free software: you can redistribute it and/or modify
313 + + * it under the terms of the GNU General Public License version 3 as
314 + + * published by the Free Software Foundation.
315 + + *
316 + + * This program is distributed in the hope that it will be useful,
317 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
318 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
319 + + * GNU General Public License for more details.
320 + + *
321 + + * You should have received a copy of the GNU General Public License
322 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
323 + + *
324 + + */
325 + +
326 + +package testutil
327 + +
328 + +import (
329 + +» "fmt"
330 + +» "os"
331 + +» "os/exec"
332 + +
333 + +» "github.com/godbus/dbus"
334 + +
335 + +» . "gopkg.in/check.v1"
336 + +)
337 + +
338 + +// DBusTest provides a separate dbus session bus for running tests
339 + +type DBusTest struct {
340 + +» tmpdir string
341 + +» dbusDaemon *exec.Cmd
342 + +» oldSessionBusEnv string
343 + +
344 + +» // the dbus.Conn to the session bus that tests can use
345 + +» SessionBus *dbus.Conn
346 + +}
347 + +
348 + +func (s *DBusTest) SetUpSuite(c *C) {
349 + +» if _, err := exec.LookPath("dbus-daemon"); err != nil {
350 + +» » c.Skip(fmt.Sprintf("cannot run test without dbus-daemon: %s", err))
351 + +» » return
352 + +» }
353 + +» if _, err := exec.LookPath("dbus-launch"); err != nil {
354 + +» » c.Skip(fmt.Sprintf("cannot run test without dbus-launch: %s", err))
355 + +» » return
356 + +» }
357 + +
358 + +» s.tmpdir = c.MkDir()
359 + +» s.dbusDaemon = exec.Command("dbus-daemon", "--session", fmt.Sprintf("--address=unix:%s/user_bus_socket", s.tmpdir))
360 + +» err := s.dbusDaemon.Start()
361 + +» c.Assert(err, IsNil)
362 + +» s.oldSessionBusEnv = os.Getenv("DBUS_SESSION_BUS_ADDRESS")
363 + +
364 + +» s.SessionBus, err = dbus.SessionBus()
365 + +» c.Assert(err, IsNil)
366 + +}
367 + +
368 + +func (s *DBusTest) TearDownSuite(c *C) {
369 + +» os.Setenv("DBUS_SESSION_BUS_ADDRESS", s.oldSessionBusEnv)
370 + +» if s.dbusDaemon != nil && s.dbusDaemon.Process != nil {
371 + +» » err := s.dbusDaemon.Process.Kill()
372 + +» » c.Assert(err, IsNil)
373 + +» }
374 + +
375 + +}
376 + diff --git a/userd/launcher.go b/userd/launcher.go
377 + new file mode 100644
378 + index 000000000..fc427e87b
379 + --- /dev/null
380 + +++ b/userd/launcher.go
381 + @@ -0,0 +1,88 @@
382 + +// -*- Mode: Go; indent-tabs-mode: t -*-
383 + +
384 + +/*
385 + + * Copyright (C) 2017 Canonical Ltd
386 + + *
387 + + * This program is free software: you can redistribute it and/or modify
388 + + * it under the terms of the GNU General Public License version 3 as
389 + + * published by the Free Software Foundation.
390 + + *
391 + + * This program is distributed in the hope that it will be useful,
392 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
393 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
394 + + * GNU General Public License for more details.
395 + + *
396 + + * You should have received a copy of the GNU General Public License
397 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
398 + + *
399 + + */
400 + +
401 + +package userd
402 + +
403 + +import (
404 + +» "fmt"
405 + +» "net/url"
406 + +» "os/exec"
407 + +
408 + +» "github.com/godbus/dbus"
409 + +» "github.com/snapcore/snapd/strutil"
410 + +)
411 + +
412 + +const launcherIntrospectionXML = `
413 + +<interface name="org.freedesktop.DBus.Peer">
414 + +» <method name='Ping'>
415 + +» </method>
416 + +» <method name='GetMachineId'>
417 + + <arg type='s' name='machine_uuid' direction='out'/>
418 + +» </method>
419 + +</interface>
420 + +<interface name='io.snapcraft.Launcher'>
421 + +» <method name='OpenURL'>
422 + +» » <arg type='s' name='url' direction='in'/>
423 + +» </method>
424 + +</interface>`
425 + +
426 + +var (
427 + +» allowedURLSchemes = []string{"http", "https", "mailto"}
428 + +)
429 + +
430 + +// Launcher implements the 'io.snapcraft.Launcher' DBus interface.
431 + +type Launcher struct{}
432 + +
433 + +// Name returns the name of the interface this object implements
434 + +func (s *Launcher) Name() string {
435 + +» return "io.snapcraft.Launcher"
436 + +}
437 + +
438 + +// IntrospectionData gives the XML formatted introspection description
439 + +// of the DBus service.
440 + +func (s *Launcher) IntrospectionData() string {
441 + +» return launcherIntrospectionXML
442 + +}
443 + +
444 + +func makeAccessDeniedError(err error) *dbus.Error {
445 + +» return &dbus.Error{
446 + +» » Name: "org.freedesktop.DBus.Error.AccessDenied",
447 + +» » Body: []interface{}{err.Error()},
448 + +» }
449 + +}
450 + +
451 + +// OpenURL implements the 'OpenURL' method of the 'com.canonical.Launcher'
452 + +// DBus interface. Before the provided url is passed to xdg-open the scheme is
453 + +// validated against a list of allowed schemes. All other schemes are denied.
454 + +func (s *Launcher) OpenURL(addr string) *dbus.Error {
455 + +» u, err := url.Parse(addr)
456 + +» if err != nil {
457 + +» » return &dbus.ErrMsgInvalidArg
458 + +» }
459 + +
460 + +» if !strutil.ListContains(allowedURLSchemes, u.Scheme) {
461 + +» » return makeAccessDeniedError(fmt.Errorf("Supplied URL scheme %q is not allowed", u.Scheme))
462 + +» }
463 + +
464 + +» if err = exec.Command("xdg-open", addr).Run(); err != nil {
465 + +» » return dbus.MakeFailedError(fmt.Errorf("cannot open supplied URL"))
466 + +» }
467 + +
468 + +» return nil
469 + +}
470 + diff --git a/userd/launcher_test.go b/userd/launcher_test.go
471 + new file mode 100644
472 + index 000000000..acc174243
473 + --- /dev/null
474 + +++ b/userd/launcher_test.go
475 + @@ -0,0 +1,81 @@
476 + +// -*- Mode: Go; indent-tabs-mode: t -*-
477 + +
478 + +/*
479 + + * Copyright (C) 2017 Canonical Ltd
480 + + *
481 + + * This program is free software: you can redistribute it and/or modify
482 + + * it under the terms of the GNU General Public License version 3 as
483 + + * published by the Free Software Foundation.
484 + + *
485 + + * This program is distributed in the hope that it will be useful,
486 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
487 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
488 + + * GNU General Public License for more details.
489 + + *
490 + + * You should have received a copy of the GNU General Public License
491 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
492 + + *
493 + + */
494 + +
495 + +package userd_test
496 + +
497 + +import (
498 + +» "github.com/godbus/dbus"
499 + +
500 + +» . "gopkg.in/check.v1"
501 + +
502 + +» "github.com/snapcore/snapd/testutil"
503 + +» "github.com/snapcore/snapd/userd"
504 + +)
505 + +
506 + +type launcherSuite struct {
507 + +» launcher *userd.Launcher
508 + +
509 + +» mockXdgOpen *testutil.MockCmd
510 + +}
511 + +
512 + +var _ = Suite(&launcherSuite{})
513 + +
514 + +func (s *launcherSuite) SetUpTest(c *C) {
515 + +» s.launcher = &userd.Launcher{}
516 + +» s.mockXdgOpen = testutil.MockCommand(c, "xdg-open", "")
517 + +}
518 + +
519 + +func (s *launcherSuite) TearDownTest(c *C) {
520 + +» s.mockXdgOpen.Restore()
521 + +}
522 + +
523 + +func (s *launcherSuite) TestOpenURLWithNotAllowedScheme(c *C) {
524 + +» for _, t := range []struct {
525 + +» » url string
526 + +» » errMatcher string
527 + +» }{
528 + +» » {"tel://049112233445566", "Supplied URL scheme \"tel\" is not allowed"},
529 + +» » {"aabbccdd0011", "Supplied URL scheme \"\" is not allowed"},
530 + +» » {"invälid:%url", dbus.ErrMsgInvalidArg.Error()},
531 + +» } {
532 + +» » err := s.launcher.OpenURL(t.url)
533 + +» » c.Assert(err, ErrorMatches, t.errMatcher)
534 + +» » c.Assert(s.mockXdgOpen.Calls(), IsNil)
535 + +» }
536 + +}
537 + +
538 + +func (s *launcherSuite) TestOpenURLWithAllowedSchemeHappy(c *C) {
539 + +» for _, schema := range []string{"http", "https", "mailto"} {
540 + +» » err := s.launcher.OpenURL(schema + "://snapcraft.io")
541 + +» » c.Assert(err, IsNil)
542 + +» » c.Assert(s.mockXdgOpen.Calls(), DeepEquals, [][]string{
543 + +» » » {"xdg-open", schema + "://snapcraft.io"},
544 + +» » })
545 + +» » s.mockXdgOpen.ForgetCalls()
546 + +» }
547 + +}
548 + +
549 + +func (s *launcherSuite) TestOpenURLWithFailingXdgOpen(c *C) {
550 + +» cmd := testutil.MockCommand(c, "xdg-open", "false")
551 + +» defer cmd.Restore()
552 + +
553 + +» err := s.launcher.OpenURL("https://snapcraft.io")
554 + +» c.Assert(err, NotNil)
555 + +» c.Assert(err, ErrorMatches, "cannot open supplied URL")
556 + +}
557 + diff --git a/userd/userd.go b/userd/userd.go
558 + new file mode 100644
559 + index 000000000..d17018e62
560 + --- /dev/null
561 + +++ b/userd/userd.go
562 + @@ -0,0 +1,109 @@
563 + +// -*- Mode: Go; indent-tabs-mode: t -*-
564 + +
565 + +/*
566 + + * Copyright (C) 2017 Canonical Ltd
567 + + *
568 + + * This program is free software: you can redistribute it and/or modify
569 + + * it under the terms of the GNU General Public License version 3 as
570 + + * published by the Free Software Foundation.
571 + + *
572 + + * This program is distributed in the hope that it will be useful,
573 + + * but WITHOUT ANY WARRANTY; without even the implied warranty of
574 + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
575 + + * GNU General Public License for more details.
576 + + *
577 + + * You should have received a copy of the GNU General Public License
578 + + * along with this program. If not, see <http://www.gnu.org/licenses/>.
579 + + *
580 + + */
581 + +
582 + +package userd
583 + +
584 + +import (
585 + +» "bytes"
586 + +» "fmt"
587 + +
588 + +» "github.com/godbus/dbus"
589 + +» "github.com/godbus/dbus/introspect"
590 + +» "gopkg.in/tomb.v2"
591 + +)
592 + +
593 + +const (
594 + +» busName = "io.snapcraft.Launcher"
595 + +» basePath = "/io/snapcraft/Launcher"
596 + +)
597 + +
598 + +type dbusInterface interface {
599 + +» Name() string
600 + +» IntrospectionData() string
601 + +}
602 + +
603 + +type Userd struct {
604 + +» tomb tomb.Tomb
605 + +» conn *dbus.Conn
606 + +» dbusIfaces []dbusInterface
607 + +}
608 + +
609 + +func (ud *Userd) createAndExportInterfaces() {
610 + +» ud.dbusIfaces = []dbusInterface{&Launcher{}}
611 + +
612 + +» var buffer bytes.Buffer
613 + +» buffer.WriteString("<node>")
614 + +
615 + +» for _, iface := range ud.dbusIfaces {
616 + +» » ud.conn.Export(iface, basePath, iface.Name())
617 + +» » buffer.WriteString(iface.IntrospectionData())
618 + +» }
619 + +
620 + +» buffer.WriteString(introspect.IntrospectDataString)
621 + +» buffer.WriteString("</node>")
622 + +
623 + +» ud.conn.Export(introspect.Introspectable(buffer.String()), basePath, "org.freedesktop.DBus.Introspectable")
624 + +}
625 + +
626 + +func (ud *Userd) Init() error {
627 + +» var err error
628 + +
629 + +» ud.conn, err = dbus.SessionBus()
630 + +» if err != nil {
631 + +» » return err
632 + +» }
633 + +
634 + +» reply, err := ud.conn.RequestName(busName, dbus.NameFlagDoNotQueue)
635 + +» if err != nil {
636 + +» » return err
637 + +» }
638 + +
639 + +» if reply != dbus.RequestNameReplyPrimaryOwner {
640 + +» » err = fmt.Errorf("cannot obtain bus name '%s'", busName)
641 + +» » return err
642 + +» }
643 + +
644 + +» ud.createAndExportInterfaces()
645 + +» return nil
646 + +}
647 + +
648 + +func (ud *Userd) Start() {
649 + +» ud.tomb.Go(func() error {
650 + +» » // Listen to keep our thread up and running. All DBus bits
651 + +» » // are running in the background
652 + +» » select {
653 + +» » case <-ud.tomb.Dying():
654 + +» » » ud.conn.Close()
655 + +» » }
656 + +» » err := ud.tomb.Err()
657 + +» » if err != nil && err != tomb.ErrStillAlive {
658 + +» » » return err
659 + +» » }
660 + +» » return nil
661 + +» })
662 + +}
663 + +
664 + +func (ud *Userd) Stop() error {
665 + +» ud.tomb.Kill(nil)
666 + +» return ud.tomb.Wait()
667 + +}
668 + +
669 + +func (ud *Userd) Dying() <-chan struct{} {
670 + +» return ud.tomb.Dying()
671 + +}
672 + diff --git a/vendor/vendor.json b/vendor/vendor.json
673 + index 8715a0db5..c8e3aa756 100644
674 + --- a/vendor/vendor.json
675 + +++ b/vendor/vendor.json
676 + @@ -19,10 +19,16 @@
677 + » » » "revisionTime": "2014-05-03T19:37:39Z"
678 + » » },
679 + » » {
680 + -» » » "checksumSHA1": "LIpi0bDVAl3e0Xza8gohpKkH0+I=",
681 + +» » » "checksumSHA1": "h77tT8kVh8x/J5ikkZReONPUjU0=",
682 + » » » "path": "github.com/godbus/dbus",
683 + -» » » "revision": "bd29ed602e2cf4207ebcabcd530259169e4289ba",
684 + -» » » "revisionTime": "2017-07-07T17:46:28Z"
685 + +» » » "revision": "97646858c46433e4afb3432ad28c12e968efa298",
686 + +» » » "revisionTime": "2017-08-22T15:24:03Z"
687 + +» » },
688 + +» » {
689 + +» » » "checksumSHA1": "NrP46FPoALgKz3FY6puL3syMAAI=",
690 + +» » » "path": "github.com/godbus/dbus/introspect",
691 + +» » » "revision": "97646858c46433e4afb3432ad28c12e968efa298",
692 + +» » » "revisionTime": "2017-08-22T15:24:03Z"
693 + » » },
694 + » » {
695 + » » » "checksumSHA1": "iIUYZyoanCQQTUaWsu8b+iOSPt4=",
696 + --
697 + 2.13.5
698 +