Mir

Merge lp:~nick-dedekind/mir/trusted_sessions into lp:mir

Proposed by Nick Dedekind
Status: Merged
Merged at revision: 1701
Proposed branch: lp:~nick-dedekind/mir/trusted_sessions
Merge into: lp:mir
Prerequisite: lp:~alan-griffiths/mir/spike-passing-out-client-fds
Diff against target: 4606 lines (+3344/-40)
79 files modified
examples/CMakeLists.txt (+6/-2)
examples/demo-inprocess-surface-client/inprocess_egl_client.cpp (+1/-1)
examples/trust_session.c (+249/-0)
include/client/mir_toolkit/mir_trust_session.h (+119/-0)
include/server/mir/default_server_configuration.h (+3/-0)
include/server/mir/frontend/event_sink.h (+2/-0)
include/server/mir/frontend/session.h (+1/-0)
include/server/mir/frontend/session_mediator_report.h (+6/-0)
include/server/mir/frontend/shell.h (+9/-0)
include/server/mir/frontend/trust_session.h (+53/-0)
include/server/mir/scene/null_trust_session_listener.h (+50/-0)
include/server/mir/scene/session.h (+3/-1)
include/server/mir/scene/trust_session.h (+43/-0)
include/server/mir/scene/trust_session_creation_parameters.h (+46/-0)
include/server/mir/scene/trust_session_listener.h (+52/-0)
include/shared/mir_toolkit/client_types.h (+26/-0)
include/shared/mir_toolkit/common.h (+17/-0)
include/shared/mir_toolkit/event.h (+10/-1)
include/test/mir_test/test_protobuf_client.h (+18/-0)
include/test/mir_test_doubles/mock_scene_session.h (+3/-0)
include/test/mir_test_doubles/mock_shell.h (+9/-0)
include/test/mir_test_doubles/mock_trust_session_listener.h (+48/-0)
include/test/mir_test_doubles/null_trust_session.h (+69/-0)
include/test/mir_test_doubles/stub_scene_session.h (+8/-0)
include/test/mir_test_doubles/stub_session.h (+4/-0)
include/test/mir_test_doubles/stub_shell.h (+15/-0)
src/client/CMakeLists.txt (+4/-1)
src/client/connection_configuration.h (+2/-0)
src/client/default_connection_configuration.cpp (+11/-1)
src/client/default_connection_configuration.h (+2/-0)
src/client/event_distributor.cpp (+57/-0)
src/client/event_distributor.h (+52/-0)
src/client/mir_connection.cpp (+9/-2)
src/client/mir_connection.h (+5/-0)
src/client/mir_trust_session.cpp (+182/-0)
src/client/mir_trust_session.h (+88/-0)
src/client/mir_trust_session_api.cpp (+133/-0)
src/client/rpc/make_rpc_channel.h (+3/-1)
src/client/rpc/make_socket_rpc_channel.cpp (+4/-3)
src/client/rpc/mir_socket_rpc_channel.cpp (+26/-7)
src/client/rpc/mir_socket_rpc_channel.h (+6/-2)
src/server/default_server_configuration.cpp (+11/-0)
src/server/frontend/protobuf_message_processor.cpp (+12/-0)
src/server/frontend/session_mediator.cpp (+95/-2)
src/server/frontend/session_mediator.h (+17/-0)
src/server/report/logging/session_mediator_report.cpp (+15/-0)
src/server/report/logging/session_mediator_report.h (+6/-0)
src/server/report/lttng/session_mediator_report.cpp (+11/-0)
src/server/report/lttng/session_mediator_report.h (+3/-0)
src/server/report/lttng/session_mediator_report_tp.h (+21/-0)
src/server/report/null/session_mediator_report.cpp (+12/-0)
src/server/report/null/session_mediator_report.h (+6/-0)
src/server/scene/CMakeLists.txt (+3/-0)
src/server/scene/application_session.cpp (+21/-0)
src/server/scene/application_session.h (+3/-0)
src/server/scene/default_configuration.cpp (+3/-2)
src/server/scene/session_manager.cpp (+125/-3)
src/server/scene/session_manager.h (+20/-1)
src/server/scene/trust_session_container.cpp (+95/-0)
src/server/scene/trust_session_container.h (+103/-0)
src/server/scene/trust_session_creation_parameters.cpp (+51/-0)
src/server/scene/trust_session_impl.cpp (+175/-0)
src/server/scene/trust_session_impl.h (+74/-0)
src/shared/protobuf/mir_protobuf.proto (+23/-2)
tests/acceptance-tests/CMakeLists.txt (+1/-0)
tests/acceptance-tests/test_client_trust_session_api.cpp (+106/-0)
tests/acceptance-tests/test_nested_mir.cpp (+3/-0)
tests/integration-tests/frontend/test_application_mediator_report.cpp (+181/-0)
tests/integration-tests/test_session_manager.cpp (+3/-1)
tests/mir_test_doubles/test_protobuf_client.cpp (+27/-1)
tests/unit-tests/client/CMakeLists.txt (+1/-0)
tests/unit-tests/client/test_mir_trust_session.cpp (+244/-0)
tests/unit-tests/frontend/stress_protobuf_communicator.cpp (+3/-1)
tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved (+65/-0)
tests/unit-tests/scene/CMakeLists.txt (+2/-0)
tests/unit-tests/scene/test_application_session.cpp (+45/-0)
tests/unit-tests/scene/test_session_manager.cpp (+55/-5)
tests/unit-tests/scene/test_trust_session.cpp (+82/-0)
tests/unit-tests/scene/test_trust_session_container.cpp (+167/-0)
To merge this branch: bzr merge lp:~nick-dedekind/mir/trusted_sessions
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Alexandros Frantzis Pending
Andreas Pokorny Pending
Mir development team Pending
Review via email: mp+218975@code.launchpad.net

This proposal supersedes a proposal from 2014-03-04.

Description of the change

This adds/implements the API required for client & server to manage "trust sessions".

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

There's a lot of this to digest - and I don't know what feature(s) it is supposed to support.

Accordingly, I get bogged down in details like:

@SessionId - why is this useful (compared to, say, std::[shared|weak]_ptr<Session>)

@TrustedSessionCreationParameters - this has one public mutable member (which initializes itself). Why does it need a constructor? (And does it really belong in the shell namespace?)

61 + * Copyright © 2012 Canonical Ltd.

Wrong year.

@examples/trusted_session_trusted_session.c

This is written using the original (async) APIs it would probably be clearer using the (slightly) more recent sync ones. (I suspect cut & paste from an example that should have been updated last year.)

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Wow, so much code. This will take a while...

(1) One quick note:
1196 +MirTrustedSession* mir_trusted_session_create(MirConnection* connection)
The pattern we use is "NAMESPACE_OBJECT_ACTION", so that should be:
    MirTrustedSession* mir_connection_create_trusted_session(MirConnection* connection)
Although since "session" was never an object in the client API before, the word "trusted" is superfluous and could be removed. Even if only from the public client API.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(2) Quick requirements/analysis sanity check: Can you explain why this feature needs to be in Mir itself?

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> Wow, so much code. This will take a while...
>
> (1) One quick note:
> 1196 +MirTrustedSession* mir_trusted_session_create(MirConnection*
> connection)
> The pattern we use is "NAMESPACE_OBJECT_ACTION", so that should be:
> MirTrustedSession* mir_connection_create_trusted_session(MirConnection*
> connection)
> Although since "session" was never an object in the client API before, the
> word "trusted" is superfluous and could be removed. Even if only from the
> public client API.

It doesn't mean the same thing without "trusted". The TrustedSession is "the object" we are creating. A "trusted session" describes the trust relationship between mir [server] sessions. https://wiki.ubuntu.com/Security/TrustStoreAndSessions

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> (2) Quick requirements/analysis sanity check: Can you explain why this feature
> needs to be in Mir itself?

The trust session needs to be created by a mir client, and interpreted by the shell (in our case, the mirserver api shell layer - unity-mir).
Since it describes the relationship between sessions, it seems like the logical place. Without mir we would need to create a new framework for the client to communicate this with the shell.

tvoss may have a more speicific answer for you.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> > Wow, so much code. This will take a while...
> >
> > (1) One quick note:
> > 1196 +MirTrustedSession* mir_trusted_session_create(MirConnection*
> > connection)
> > The pattern we use is "NAMESPACE_OBJECT_ACTION", so that should be:
> > MirTrustedSession* mir_connection_create_trusted_session(MirConnection*
> > connection)
> > Although since "session" was never an object in the client API before, the
> > word "trusted" is superfluous and could be removed. Even if only from the
> > public client API.
>
> It doesn't mean the same thing without "trusted". The TrustedSession is "the
> object" we are creating. A "trusted session" describes the trust relationship
> between mir [server] sessions.
> https://wiki.ubuntu.com/Security/TrustStoreAndSessions

In retrospect, it's actually a "trust session". I'll change that.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:1400
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~nick-dedekind/mir/trusted_sessions/+merge/209224/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-ci/1002/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-trusty-i386-build/1150
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-trusty-amd64-build/1148
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-trusty-touch/732
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-amd64-ci/734
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-amd64-ci/734/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-armhf-ci/739
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-armhf-ci/739/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-trusty-armhf/733
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-trusty-armhf/733/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/694
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4531

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-team-mir-development-branch-ci/1002/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> There's a lot of this to digest - and I don't know what feature(s) it is
> supposed to support.

Thanks for the review.
This adds/implements the API required for client & server to manage "trust sessions" (as the name suggests).
The easiest way to get an overview of what this code "does" is by looking at the diagram:
https://docs.google.com/a/canonical.com/drawings/d/1Sx3Q6IugYY0DjrQfN3em6PBhyeNotXtYAa4UioVdT8c/edit

>
> Accordingly, I get bogged down in details like:
>
> @SessionId - why is this useful (compared to, say,
> std::[shared|weak]_ptr<Session>)

:/ This was a bit of a mixed implementation. The client side supports multiple trust sessions per connection, while the server does not. So [at least for now] I've removed support for multiple trust sessions (start refused). So removed the SessionId in favour of std::shared_ptr<TrustSession>

>
> @TrustedSessionCreationParameters - this has one public mutable member (which
> initializes itself). Why does it need a constructor? (And does it really
> belong in the shell namespace?)
>
> 61 + * Copyright © 2012 Canonical Ltd.
>
> Wrong year.
>
> @examples/trusted_session_trusted_session.c
>
> This is written using the original (async) APIs it would probably be clearer
> using the (slightly) more recent sync ones. (I suspect cut & paste from an
> example that should have been updated last year.)

Refactored example & added sync methods to trust session API.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal

First run on the public client side API

+ 399 wrong comment
+ 408 Really Lifecycle, not just "state"?
+ 443 wrong comment

In general - do we need to the start and stop states? Isnt create/destroy enough?

+ 399ff this means all sessions of the same process pid are trusted? Couldnt that be: mir_trust_session_trust_process(session, pid);

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

This isn't a full review, but some minor fixes to do in the mean time...

(1) Please follow the existing convention, which would mean:
396 +MirTrustSession* mir_trust_session_create(MirConnection* connection);
becomes:
MirTrustSession* mir_connection_create_trust_session(MirConnection* connection);

(2) Please put the details/justification you mentioned in the commit message or proposal description. A four word description for a 3713 line proposal is a bit brief...

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> First run on the public client side API
>
> + 399 wrong comment
> + 408 Really Lifecycle, not just "state"?
> + 443 wrong comment

Fixed.

>
> In general - do we need to the start and stop states? Isnt create/destroy
> enough?
>
> + 399ff this means all sessions of the same process pid are trusted? Couldnt
> that be: mir_trust_session_trust_process(session, pid);

The trust sessions doesn't exist on the server until we call start. The trust session is set up (add pids), after which we call mir_trust_session_start (which creates the server side impl). And the server can manually stop the trust session as well, so that's why we need the state callback.

renamed to mir_trust_session_add_trusted_pid

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Overall, very nice. The size of the proposal however means the little issues are adding up to quite a list...

(1) 397 +MirTrustSession* mir_connection_trust_session_create(MirConnection* connection);
should be renamed to follow the existing convention:
MirTrustSession* mir_connection_create_trust_session(MirConnection* connection);

(2) Please expand on the commit message/description further. It's still too brief for a large enhancement.

(3) Please remove "handle_trust_session_event()". EventSink is only meant to have one method "handle_event" which handles any and all event types. The other methods of EventSink are mistakes we need to revert already. Sorry it's misleading.

(4) ABI bumps: The server ABI seems to have changed, but the client ABI is not broken by this proposal. Please revent the MIR_CLIENT_ABI bump.

(5) trust_session.c: The program prints messages referring to itself as "demo_client_trusted_helper" and "demo_client_app2". However the binary name is "mir_demo_client_trust_session". Maybe it should be printing that or just argv[0] to avoid confusion.

(6) trust_session.c: Forks into two processes, which is unusual for a client. Is that the expected/normal use case?

(7) read(STDIN_FILENO, &buff, 1) - Why not getchar()? It's simpler more portable too.

(8) Long lines - I prefer code wrapped before column 80 and so do plenty of people. Not just because that's what a terminal defaults to, but it's easier for the brain to follow line continuation when you avoid them getting too long.

(9) frontend/trust_session.h: Is std::vector necessary to maintain an ordered list? If not then the more appropriate container is std::unordered_set

(10) frontend/trust_session.h: a stop() method but no start() method? Is that a good idea? Is the start implicit in construction?

(11) MirTrustSessionAddTrustResult: The enum values are arguably too long. IMHO.

(12) Identical descriptions for different function types?
784 + * Callback member of MirTrustSession for handling of trust sessions.
791 + * Callback member of MirTrustSession for handling of trust sessions.

(13) We should avoid landing new code with known race conditions:
1618 + /* todo: race condition. protobuf does not guarantee that callbacks will be synchronized. potential
1619 + race in session, last_buffer_id */

(14) Superficially it's confusing as to why these with equivalent names should be separate classes:
1592 +struct MirTrustSession : public mir::client::TrustSession
But now I notice how simple mir::client::TrustSession is, they're clearly quite different things. So the class names should clarify the differences between them.

(15) What's a "Control"?
1885 +class TrustSessionControl
I'm not familiar with that abstraction. Even though there seems to be another "Control" class there already :S

(16) test_protobuf_client.cpp: A busy wait loop seems like a lazy approach to this (albeit a lazy approach we've already used in other tests). It would be cleaner to use a std::condition_variable with a std::mutex and bool. That would also avoid the expected Helgrind complaints about std::atomic being racy.

(17) test_trust_session.cpp: Wrong copyright year range.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

A first pass...

Since mir_client_library.cpp has started to become unwieldly I propose we follow the convention mir_screencast is using, i.e.:

1. Public header file goes in mir_toolkit/mir_trust_session.h
2. C API implementation goes in src/client/mir_trust_session_api.cpp
3. Internal classes as usual, src/client/mir_trust_session.{cpp,h}

148 +///\page trust_session.c trust_session.c: A mir client which starts a trust session and trusted client app.
149 +/// mir_demo_client_trust_session shows the use of mir trust session API.
150 +/// This program opens a mir connection and creates a trust session.
...

519 + virtual std::shared_ptr<TrustSession> start_trust_session_for(std::string& error,
520 + std::shared_ptr<Session> const& session,

Since this is a C file, the C(/Javadoc) format is preferred, like in the public files.

519 + virtual std::shared_ptr<TrustSession> start_trust_session_for(std::string& error,
520 + std::shared_ptr<Session> const& session,
...

Either use a 4-space indentation or align with char after '('.

567 + virtual ~TrustSession() {}
1129 + TrustSession() {}
1130 + virtual ~TrustSession() {}

Use '= default' instead;

744 +#include <string>

Not needed.

1239 +/**************************
1240 + * Trust session specific functions *
1241 + **************************/

This can be made prettier :)

1249 + pid_t pid)

1255 + mir_trust_session_callback callback,
1256 + void* context)

1272 + reinterpret_cast<mir_trust_session_callback>
1273 + (assign_result),
1274 + NULL));

1279 + mir_trust_session_callback callback,
1280 + void* context)

1296 + reinterpret_cast<mir_trust_session_callback>
1297 + (assign_result),
1298 + NULL));

1308 + mir_trust_session_event_callback callback,
1309 + void* context)

Either use a 4-space indentation or align with char after '(' on previous line.

1427 + [this]
1428 + (MirTrustSessionState new_state)

1501 + [this, callback, context]
1502 + (MirTrustSessionState state)

2771 + [this]
2772 + (std::shared_ptr<msh::Session> const& child_session)

We tend to prefer to keep the parameter list on the same line as the capture list:
[this] (MirTrustSessionState new_state), but that's not a hard and fast rule AFAIK.

1430 + std::lock_guard<std::recursive_mutex> lock(mutex);

Why do we need a recursive mutex?

1595 + MirTrustSession(mir::protobuf::DisplayServer::Stub & server,
1600 + MirTrustSession(MirTrustSession const &) = delete;
1601 + MirTrustSession& operator=(MirTrustSession const &) = delete;
... and others in the class

* and & go with the type (or 'const' if there is one).

1820 + std::unique_lock<std::mutex> lk(guard);

Since the lock is not used with condition variables or moved, we could use the simpler std::lock_guard<>.

1814 +mcl::TrustSessionControl::~TrustSessionControl()
1815 +{
1816 +}

Is this needed?

2737 + TrustSession* impl = new TrustSession(trusted_helper, parameters, sink);
2738 + std::shared_ptr<msh::TrustSession> ptr(impl);

auto const trust_session = std::make_shared<TrustSession>(trusted_helper, parameters, sink);

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal
Download full text (4.8 KiB)

> Overall, very nice. The size of the proposal however means the little issues
> are adding up to quite a list...
>
> (1) 397 +MirTrustSession* mir_connection_trust_session_create(MirConnection*
> connection);
> should be renamed to follow the existing convention:
> MirTrustSession* mir_connection_create_trust_session(MirConnection*
> connection);

My bad again. Done

>
> (2) Please expand on the commit message/description further. It's still too
> brief for a large enhancement.

Done

>
> (3) Please remove "handle_trust_session_event()". EventSink is only meant to
> have one method "handle_event" which handles any and all event types. The
> other methods of EventSink are mistakes we need to revert already. Sorry it's
> misleading.

Hmm. bit of an interesting one about this one. The only consumer for MirEvents are the surfaces.
Which means we'll need another consumer to push the events to clients without a surface.
I've removed the TrustSessionControl class, and added a mcl::EventDistributor class to the client library which does this.

>
> (4) ABI bumps: The server ABI seems to have changed, but the client ABI is not
> broken by this proposal. Please revent the MIR_CLIENT_ABI bump.

Done

>
> (5) trust_session.c: The program prints messages referring to itself as
> "demo_client_trusted_helper" and "demo_client_app2". However the binary name
> is "mir_demo_client_trust_session". Maybe it should be printing that or just
> argv[0] to avoid confusion.

Made references/stdout of each process more explicit.

>
> (6) trust_session.c: Forks into two processes, which is unusual for a client.
> Is that the expected/normal use case?

We need 2 processes for a trust session, the "trusted helper", and the "trusted app".
It would probably be more normal for the trusted helper to start an external process, but I it
better to enclose all behaviour in the single example.

>
> (7) read(STDIN_FILENO, &buff, 1) - Why not getchar()? It's simpler more
> portable too.

Done

>
> (8) Long lines - I prefer code wrapped before column 80 and so do plenty of
> people. Not just because that's what a terminal defaults to, but it's easier
> for the brain to follow line continuation when you avoid them getting too
> long.
>
> (9) frontend/trust_session.h: Is std::vector necessary to maintain an ordered
> list? If not then the more appropriate container is std::unordered_set

Needs to be ordered for the shell. (last session is on top)

>
> (10) frontend/trust_session.h: a stop() method but no start() method? Is that
> a good idea? Is the start implicit in construction?

It's not ideal, but there is a static start_for function on the src/server/scene/trust_session.cpp
Which essentially is implicit start on creation. Can't do what we need from a member start.

>
> (11) MirTrustSessionAddTrustResult: The enum values are arguably too long.
> IMHO.

Now shorter (kind of). Though there are some pretty long ones about still.

>
> (12) Identical descriptions for different function types?
> 784 + * Callback member of MirTrustSession for handling of trust sessions.
> 791 + * Callback member of MirTrustSession for handling of trust sessions.
>

Fixed.

> (13) We ...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal
Download full text (3.6 KiB)

> A first pass...
>
> Since mir_client_library.cpp has started to become unwieldly I propose we
> follow the convention mir_screencast is using, i.e.:
>
> 1. Public header file goes in mir_toolkit/mir_trust_session.h
> 2. C API implementation goes in src/client/mir_trust_session_api.cpp
> 3. Internal classes as usual, src/client/mir_trust_session.{cpp,h}

Done

>
> 148 +///\page trust_session.c trust_session.c: A mir client which starts a
> trust session and trusted client app.
> 149 +/// mir_demo_client_trust_session shows the use of mir trust session
> API.
> 150 +/// This program opens a mir connection and creates a trust session.
> ...
>
> 519 + virtual std::shared_ptr<TrustSession>
> start_trust_session_for(std::string& error,
> 520 + std::shared_ptr<Session> const& session,
>
> Since this is a C file, the C(/Javadoc) format is preferred, like in the
> public files.
>

This is using the same format as the other examples.

>
> 519 + virtual std::shared_ptr<TrustSession>
> start_trust_session_for(std::string& error,
> 520 + std::shared_ptr<Session> const& session,
> ...
>
> Either use a 4-space indentation or align with char after '('.

Done

>
> 567 + virtual ~TrustSession() {}
> 1129 + TrustSession() {}
> 1130 + virtual ~TrustSession() {}
>
> Use '= default' instead;

Done

>
> 744 +#include <string>
>
> Not needed.

Done

>
> 1239 +/**************************
> 1240 + * Trust session specific functions *
> 1241 + **************************/
>
> This can be made prettier :)

Removed with separation of client api source files

>
> 1249 + pid_t pid)
>
> 1255 + mir_trust_session_callback callback,
> 1256 + void* context)
>
> 1272 + reinterpret_cast<mir_trust_session_callback>
> 1273 + (assign_result),
> 1274 + NULL));
>
> 1279 + mir_trust_session_callback callback,
> 1280 + void* context)
>
> 1296 + reinterpret_cast<mir_trust_session_callback>
> 1297 + (assign_result),
> 1298 + NULL));
>
> 1308 + mir_trust_session_event_callback callback,
> 1309 + void* context)
>
> Either use a 4-space indentation or align with char after '(' on previous
> line.
>
> 1427 + [this]
> 1428 + (MirTrustSessionState new_state)
>
> 1501 + [this, callback, context]
> 1502 + (MirTrustSessionState state)
>
> 2771 + [this]
> 2772 + (std::shared_ptr<msh::Session> const& child_session)
>
> We tend to prefer to keep the parameter list on the same line as the capture
> list:
> [this] (MirTrustSessionState new_state), but that's not a hard and fast rule
> AFAIK.

Must have picked it up on some other project. Switched to single line

>
> 1430 + std::lock_guard<std::recursive_mutex> lock(mutex);
>
> Why do we need a recursive mutex?

Changed already

>
> 1595 + MirTrustSession(mir::protobuf::DisplayServer::Stub & server,
> 1600 + MirTrustSession(MirTrustSession const &) = delete;
> 1601 + MirTrustSession& operator=(MirTrustSession const &) = delete;
> ... and others in the class
>
> * and & go with the type (or 'const' if there is one).

Done

>
> 1820 + std::unique_lock<std::mutex> lk(guard);
>
> Since the lock is not used with condition...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

2919 + * Copyright © 2013 Canonical Ltd.

Surely 2014 deserves a mention?

~~~~

534 === renamed file 'src/server/scene/session_container.h' => 'include/server/mir/scene/session_container.h'

Why is this interface being made public? It is internal to the Mir scene implementation and should be access via SessionManager (which has public interfaces frontend::Shell and shell::FocusController)

Oh, I see: it has an entirely new use with shell::Session::get_children(). That opens a whole new debate about procedural vs OO design:

In this instance, for example, in TrustSession::stop() we should be telling the trusted_helper that the session has stopped, not asking for this collection and manipulating it.

This isn't the only part of the design that makes use of manipulating state directly instead of tell what is going on. A quick search for [sg]et_ turns up more.

~~~~

There's a misuse of smart pointers - shared_ptr is about "ownership" and this needs to be a directed *acyclic* graph to correctly manage memory. Having the parent and child both "own" each other is wrong. At least one of these smart pointers should be a raw pointer.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> There's a misuse of smart pointers - shared_ptr is about "ownership" and this
> needs to be a directed *acyclic* graph to correctly manage memory. Having the
> parent and child both "own" each other is wrong. At least one of these smart
> pointers should be a raw pointer.

I've not checked the required semantics, but another solution that might be evaluated is to use weak_ptr.

Revision history for this message
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal

I had a quick look at the proposed API; please consider adding an API to add an application by app-id, so that we can add applications which have not been started yet.
More about that here:

https://lists.launchpad.net/ubuntu-phone/msg06680.html

(I myself would have preferred a different approach, where an app could add itself to an existing session)

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> > There's a misuse of smart pointers - shared_ptr is about "ownership" and
> this
> > needs to be a directed *acyclic* graph to correctly manage memory. Having
> the
> > parent and child both "own" each other is wrong. At least one of these smart
> > pointers should be a raw pointer.
>
> I've not checked the required semantics, but another solution that might be
> evaluated is to use weak_ptr.

Would have liked to use weak_ptr, but it wouldn't work for setting child parents from within Session::begin_trust_session.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> I had a quick look at the proposed API; please consider adding an API to add
> an application by app-id, so that we can add applications which have not been
> started yet.
> More about that here:
>
> https://lists.launchpad.net/ubuntu-phone/msg06680.html
>
> (I myself would have preferred a different approach, where an app could add
> itself to an existing session)

From when I've seen, a mir session has no concept of an app id, so we wouldn't be able to determine if we needed to add a newly started session to the existing trust session. There is a "Session::name", but that doesn't seem to equate to anything.
I'm not sure how we're supposed to deal with this.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I'm wondering why we have single "trust session" object managed by the client that can contain zero or more pids - wouldn't a more useful design be to have a collection of zero or more trusted pids that can be managed by the client?

Vis:

start_trust_session(pid1, pid2)
...
stop_trust_session(pid1)
...
start_trust_session(pid3)
...
stop_trust_session(pid2, pid3)

review: Needs Information
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

532 === renamed file 'src/server/scene/session_container.h' => 'include/server/mir/scene/session_container.h'

[Already discussed] above this interface should not be published. It is internal to the Mir scene implementation.

~~~~

424 +
425 + // TODO - remove these in favour of using handle_event

What has this to do with trust sessions?

~~~~

437 + virtual void session_start_trust_session_called(std::string const& app_name) = 0;

Is the name of the current session enough information to be useful? Would some information about what is trusted be appropriate?

~~~~

1902 + // only surface events have e.surface.id . Other events will throw exception.
1903 + try
1904 + {
1905 + surface_map->with_surface_do(e.surface.id,
1906 + [&e](MirSurface* surface)
1907 + {
1908 + surface->handle_event(e);
1909 + });
1910 + }
1911 + catch (std::exception const& x)
1912 + {
1913 + rpc_report->event_parsing_failed(event);
1914 + // Eat this exception as it doesn't affect other events
1915 + }

This looks suspiciously like using exceptions in the normal control path. We're not even logging information from x.

~~~~

2016 + BOOST_THROW_EXCEPTION(std::logic_error("Cannot start another trust session"));

If I read the surrounding code correctly, the client has requested a trust session while the server already has one associated with the client? That doesn't sound like a logic_error (in the Mir code), more like a runtime_error as the client code hasn't acted in the expected manner.

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

Moved the relationship information to the trust session, rather than being a property of the session itself.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

The conflicts are not as numerous as Launchpad reports, but still numerous:
Text conflict in CMakeLists.txt
Text conflict in debian/changelog
Text conflict in include/server/mir/shell/session.h
Text conflict in src/client/CMakeLists.txt
Text conflict in src/client/default_connection_configuration.cpp
Text conflict in src/client/rpc/mir_socket_rpc_channel.cpp
Text conflict in src/server/frontend/default_configuration.cpp
Text conflict in src/server/frontend/session_mediator.cpp
Text conflict in tests/unit-tests/scene/test_application_session.cpp
Text conflict in tests/unit-tests/scene/test_session_manager.cpp
Text conflict in tests/unit-tests/scene/test_surface_impl.cpp
11 conflicts encountered.

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

Fixed conflicts.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(18) Spurious (old) changes to debian/changelog have now crept in.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(19) Conflict:
Text conflict in tests/unit-tests/scene/test_session_manager.cpp
1 conflicts encountered.

review: Needs Fixing
Revision history for this message
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal

Hi! I was asked to comment on the current approach, so here I am. :-)

I'll first recap what Online Accounts needs on a higher level (see also the description of bug 1230091):

The Online Accounts ("OA" for brevity) D-Bus service responds to client requests, and in response to these requests it's possible that we need to open the Online Accounts UI on top of the client application in a modal way: without blocking its process execution, but preventing it from getting mouse/keyboard input.

While the user is working with the OA window, it may be that we need to start other processes; these are not ordinary applications, but account plugins: there is a single binary which loads different QML UIs depending on the account provider (where provider is "google", "facebook", etc.). Also, the apparmor confinement under which the account plugin process is run depends on the account provider (we want to confine account plugins which come as part of click packages).

Note that different applications can talk to the OA API at the same time, and it's possible that at a certain given moment there are two different client applications involved in two different trust sessions, with two OA windows (each one being modal to one client application) and each one having an account plugin UI opened, which might be the same plugin for both sessions, or a different one.

We currently produce all the OA UIs from a single process (the OA D-Bus service); this bit of implementation can be changed if needed, and we can make so that each OA UI window leaves in a different process. This however would require more IPC and added complexity, and I believe that when Mir/Unity8 will hit the desktop it will anyway have to support the case of a single process creating multiple windows, so I hope that "1 pid = 1 window" won't be a requirement for the trust sessions.

Considering all the above, the API proposed in this branch doesn't seem to provide the functionality we need, since it only accepts PIDs as members of a session.

With no intention of sounding more expert than what I am, I'll quickly describe how my ideal API would look like, while indeed acknowledging that other implementations might exist and be better suited:
- refer to individual windows, not processes or applications
- API to request a window to be placed as modal of another window (possibly created by another process)
- such request might fail if the calling process is confined and has not been authorized
- API to authorize a process (by APP_ID) to set any of its window as modal to a given window
That is, mainly a couple of methods:
  void Window::setTransientFor(WindowHandle obscuredWindow);
  void Window::allowModalWindowsFromApplication(AppId app);
The first one for actually doing the reparenting work, and the latter to decide who can do that (besides unconfined apps).

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Pushing to WIP as Nick's been off and the MP has yet to incorporate the results of various discussions.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal
Download full text (3.5 KiB)

> Hi! I was asked to comment on the current approach, so here I am. :-)
>
> I'll first recap what Online Accounts needs on a higher level (see also the
> description of bug 1230091):
>
> The Online Accounts ("OA" for brevity) D-Bus service responds to client
> requests, and in response to these requests it's possible that we need to open
> the Online Accounts UI on top of the client application in a modal way:
> without blocking its process execution, but preventing it from getting
> mouse/keyboard input.
>
> While the user is working with the OA window, it may be that we need to start
> other processes; these are not ordinary applications, but account plugins:
> there is a single binary which loads different QML UIs depending on the
> account provider (where provider is "google", "facebook", etc.). Also, the
> apparmor confinement under which the account plugin process is run depends on
> the account provider (we want to confine account plugins which come as part of
> click packages).
>
> Note that different applications can talk to the OA API at the same time, and
> it's possible that at a certain given moment there are two different client
> applications involved in two different trust sessions, with two OA windows
> (each one being modal to one client application) and each one having an
> account plugin UI opened, which might be the same plugin for both sessions, or
> a different one.
>
> We currently produce all the OA UIs from a single process (the OA D-Bus
> service); this bit of implementation can be changed if needed, and we can make
> so that each OA UI window leaves in a different process. This however would
> require more IPC and added complexity, and I believe that when Mir/Unity8 will
> hit the desktop it will anyway have to support the case of a single process
> creating multiple windows, so I hope that "1 pid = 1 window" won't be a
> requirement for the trust sessions.
>
> Considering all the above, the API proposed in this branch doesn't seem to
> provide the functionality we need, since it only accepts PIDs as members of a
> session.
>
>
> With no intention of sounding more expert than what I am, I'll quickly
> describe how my ideal API would look like, while indeed acknowledging that
> other implementations might exist and be better suited:
> - refer to individual windows, not processes or applications
> - API to request a window to be placed as modal of another window (possibly
> created by another process)
> - such request might fail if the calling process is confined and has not been
> authorized
> - API to authorize a process (by APP_ID) to set any of its window as modal to
> a given window
> That is, mainly a couple of methods:
> void Window::setTransientFor(WindowHandle obscuredWindow);
> void Window::allowModalWindowsFromApplication(AppId app);
> The first one for actually doing the reparenting work, and the latter to
> decide who can do that (besides unconfined apps).

As far as I'm aware, we're not doing any Qt API for trust sessions. This will be dealt with by dedicated trusted helpers which use the mir API directly.
[At the moment,] a trusted helper starts a trust session between 2 or more sessions. T...

Read more...

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

Maybe quite a few changes.

1) The mir_trust_session_add_trusted_session should now be called after a mir_trust_session_start. Allows trusted helpers to dynamically add sessions to the trust session. This is more for phase 2.

use case:
Gallery -> ContentHub -> Facebook/Flickr/Twitter
   a) user starts gallery
   a.1) user view: gallery app pops up
   b) user selects picture and clicks "share"
   c) content hub creates destination picker
   c.1) user view: destination picker surface pops up
   d) user selects Facebook
   d.1) user view: Facebook pops up.

While it's possible for the trust session to know about the content hub + gallery, it doesn't know the user will select facebook when it starts.

2) I've separated out the trust session notifications from the SessionListener into it's own TrustSessionListener.

3) Added a trust session container, which has bidirectional mapping between process ids and TrustSessions. This allows quick lookup when we need to add/remove sessions from a trust session.
3.1) mir::Session now has no links to trust session/trusted helper.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Looking at the client API:

    MirTrustSession* mir_connection_create_trust_session(MirConnection* connection);

I would expect "create_trust_session" to take parameters (such as the event callback) and create the server-side trust session (which would implicitly make it an async call).

AIUI this just creates a client-side object that still needs to be initialized before the server-side trust session is created using "mir_trust_session_start".

Is there any reason to separate out these create/set_event_callback/start calls?

~~~~

mir_trust_session_add_trusted_session

This is an async call - so presumably it is expected to be invoked after the trust session is started?

Does that imply a round trip for each pid added to the trust session? If so would it be better to accept a list of pids?

Can it be called on a created (but not started) trust session?

~~~~

Is there a missing mir_trust_session_remove_trusted_session() for revoking trust?

~~~~

mir_trust_session_set_event_callback

The only state changes appear to be "start" and "stop" - which are under the control of the client. So does this do any more than duplicate the functionality of the WaitHandles returned by the start/stop functions?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

std::shared_ptr<TrustSession> Shell::start_trust_session_for(std::string& error,
                                                                  std::shared_ptr<Session> const& session,
                                                                  shell::TrustSessionCreationParameters const& params) = 0;

This "error" parameter is not an idiomatic way to handle failure. Simply throwing an exception derived from std::exception that returns the error in what() will result in invoke<>() setting the error.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

bool shell::TrustSession::add_trusted_child(std::shared_ptr<shell::Session> const& session) = 0;

I'm not convinced that TrustSession *owns* Session is the correct model. It means that if a client disconnects while in a trust session the Mir Session remains alive. Which is confusing at best.

I note that in practice scene::TrustSession only keeps weak_ptr<Session> which is a better reflection of the relationship. However, I still think that the relationship between TrustSession and Session better modeled as an association than as attributes.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

In TrustSession::add_trusted_child() there's a call "session->begin_trust_session();" which will send a mir_event_type_trust_session_state_change to the "child" process.

But AIUI the child isn't the "helper" process that created the trust session and can't have registered a mir_trust_session_event_callback (which needs a trust session).

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

+class TrustSession
+{
+public:
+ virtual ~TrustSession() = default;
+
+ virtual void for_each_trusted_client_process(std::function<void(pid_t pid)> f, bool reverse) const = 0;

I don't see what this function is for. It isn't used. Which is just as well because the implementation is useless:

+void ms::TrustSession::for_each_trusted_client_process(std::function<void(pid_t pid)>, bool) const
+{
+}

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

+class TrustSessionListener
+{
+public:
+ virtual void starting(std::shared_ptr<TrustSession> const& trust_session) = 0;
+ virtual void stopping(std::shared_ptr<TrustSession> const& trust_session) = 0;
+
+ virtual void trusted_session_beginning(TrustSession& trust_session, std::shared_ptr<Session> const& session) = 0;
+ virtual void trusted_session_ending(TrustSession& trust_session, std::shared_ptr<Session> const& session) = 0;

The listener shouldn't be given any ownership of the referenced objects. So the prototypes should be:

    virtual void starting(TrustSession const& trust_session) = 0;
    virtual void stopping(TrustSession const& trust_session) = 0;

    virtual void trusted_session_beginning(TrustSession& trust_session, Session const& session) = 0;
    virtual void trusted_session_ending(TrustSession& trust_session, Session const& session) = 0;

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> Looking at the client API:
>
> MirTrustSession* mir_connection_create_trust_session(MirConnection*
> connection);
>
> I would expect "create_trust_session" to take parameters (such as the event
> callback) and create the server-side trust session (which would implicitly
> make it an async call).
>
> AIUI this just creates a client-side object that still needs to be initialized
> before the server-side trust session is created using
> "mir_trust_session_start".
>
> Is there any reason to separate out these create/set_event_callback/start
> calls?

I guess not anymore. Previously it would be possible to start and stop trust sessions multiple times; but I think with the "post-start" adding of participants, it's no longer a possibility.
I've merged all of these into a mir_connection_start_trust_session which async returns a MirTrustSession.
Not sure if the stop/release should be separate now. Left as is for now.

>
> ~~~~
>
> mir_trust_session_add_trusted_session
>
> This is an async call - so presumably it is expected to be invoked after the
> trust session is started?
>
> Does that imply a round trip for each pid added to the trust session? If so
> would it be better to accept a list of pids?
>
> Can it be called on a created (but not started) trust session?
>

It does have a round trip, but as I don't think it's an issue. We call the start_trust_session with the pid of the "source" participant (whatever is "using" the trust helper. eg. gallery application). From there, thinking about the flow, we would be layering the trust as the user makes decisions (eg. content hub "share with google+", then online accounts "log in to google+"). So practically speaking we only do one layer of trust at a time.

> ~~~~
>
> Is there a missing mir_trust_session_remove_trusted_session() for revoking
> trust?

Closing a session will remove it from the server trust session, but I'm not sure about the helper explicitly removing it. For the moment at least, I think we can do without it.

>
> ~~~~
>
> mir_trust_session_set_event_callback
>
> The only state changes appear to be "start" and "stop" - which are under the
> control of the client. So does this do any more than duplicate the
> functionality of the WaitHandles returned by the start/stop functions?

The server can also stop an active trust session (if the application closes, we don't want it hanging around). Also, for first iteration, we want to stop the trust session when switching away from the app.
So we need the helper to get a notification of this.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> std::shared_ptr<TrustSession> Shell::start_trust_session_for(std::string&
> error,
> std::shared_ptr<Session> const& session,
> shell::TrustSessionCreationParameters const& params) = 0;
>
> This "error" parameter is not an idiomatic way to handle failure. Simply
> throwing an exception derived from std::exception that returns the error in
> what() will result in invoke<>() setting the error.

Thanks, didn't know that.
Removed error parameter from interface.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> In TrustSession::add_trusted_child() there's a call
> "session->begin_trust_session();" which will send a
> mir_event_type_trust_session_state_change to the "child" process.
>
> But AIUI the child isn't the "helper" process that created the trust session
> and can't have registered a mir_trust_session_event_callback (which needs a
> trust session).

Right. this was so that the participants could be informed that a trust session has been started with them; if they need to do anything fancy. But at the moment, I don't think there's a client API for applying for general distributor events (only trust session & surface events I think), so I've removed the event send from the participants, but left it on the helper.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> +class TrustSession
> +{
> +public:
> + virtual ~TrustSession() = default;
> +
> + virtual void for_each_trusted_client_process(std::function<void(pid_t
> pid)> f, bool reverse) const = 0;
>
> I don't see what this function is for. It isn't used. Which is just as well
> because the implementation is useless:
>
> +void
> ms::TrustSession::for_each_trusted_client_process(std::function<void(pid_t
> pid)>, bool) const
> +{
> +}

old code from before the process<->trust_session bi-directional map.
removed.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal

> +class TrustSessionListener
> +{
> +public:
> + virtual void starting(std::shared_ptr<TrustSession> const& trust_session)
> = 0;
> + virtual void stopping(std::shared_ptr<TrustSession> const& trust_session)
> = 0;
> +
> + virtual void trusted_session_beginning(TrustSession& trust_session,
> std::shared_ptr<Session> const& session) = 0;
> + virtual void trusted_session_ending(TrustSession& trust_session,
> std::shared_ptr<Session> const& session) = 0;
>
> The listener shouldn't be given any ownership of the referenced objects. So
> the prototypes should be:
>
> virtual void starting(TrustSession const& trust_session) = 0;
> virtual void stopping(TrustSession const& trust_session) = 0;
>
> virtual void trusted_session_beginning(TrustSession& trust_session,
> Session const& session) = 0;
> virtual void trusted_session_ending(TrustSession& trust_session, Session
> const& session) = 0;

changed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Just a quick note - We're dealing with a bunch of regressions in Mir 0.2.0 and already have a large set of changes arriving in that release. I think we should solidify and resolve Mir 0.2.0 before considering landing any more very large changes like this.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

After fixing the (trivial) conflict in src/client/CMakeLists.txt there are test failures:

[ RUN ] SessionMediatorTest.client_socket_fd_calls_connector_client_socket_fd
unknown file: Failure
C++ exception with description "Invalid trust session" thrown in the test body.
/home/alan/display_server/development-branch/tests/unit-tests/frontend/test_session_mediator.cpp:733: Failure
Actual function call count doesn't match EXPECT_CALL(connector, client_socket_fd(_))...
         Expected: to be called once
           Actual: never called - unsatisfied and active
[ FAILED ] SessionMediatorTest.client_socket_fd_calls_connector_client_socket_fd (0 ms)
[ RUN ] SessionMediatorTest.client_socket_fd_allocates_requested_number_of_fds
unknown file: Failure
C++ exception with description "Invalid trust session" thrown in the test body.
/home/alan/display_server/development-branch/tests/unit-tests/frontend/test_session_mediator.cpp:758: Failure
Actual function call count doesn't match EXPECT_CALL(connector, client_socket_fd(_))...
         Expected: to be called 11 times
           Actual: never called - unsatisfied and active
[ FAILED ] SessionMediatorTest.client_socket_fd_allocates_requested_number_of_fds (0 ms)

~~~~

[ RUN ] TrustSessionHelper.gets_fds_for_trusted_clients
/home/alan/display_server/development-branch/tests/acceptance-tests/test_trust_session_helper.cpp:90: Failure
Value of: actual_fd_count
Expected: is equal to 3
  Actual: 0 (of type unsigned long)
[ FAILED ] TrustSessionHelper.gets_fds_for_trusted_clients (12 ms)

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Fixed tests.
Due to IRC discussion about shell being able to track trust sessions through listeners,
I've reverted changes to the listener object ownership passing (using shared_ptrs).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Out of step with latest landings. :(

Text conflict in src/server/frontend/session_mediator.cpp
1 conflicts encountered.

I pretty trivial - I fixed it like this:

std::function<void(std::shared_ptr<mf::Session> const&)> mf::SessionMediator::trusted_connect_handler() const
{
    return [this](std::shared_ptr<frontend::Session> const& session)
        {
            auto trust_session = weak_trust_session.lock();
            if (trust_session.get() == nullptr)
                BOOST_THROW_EXCEPTION(std::logic_error("Invalid trust session"));

            shell->add_trusted_session_for(trust_session, session->process_id());
        };
}

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Out of step with latest landings. :(
>
> Text conflict in src/server/frontend/session_mediator.cpp
> 1 conflicts encountered.
>
> I pretty trivial - I fixed it like this:
>
> std::function<void(std::shared_ptr<mf::Session> const&)>
> mf::SessionMediator::trusted_connect_handler() const
> {
> return [this](std::shared_ptr<frontend::Session> const& session)
> {
> auto trust_session = weak_trust_session.lock();
> if (trust_session.get() == nullptr)
> BOOST_THROW_EXCEPTION(std::logic_error("Invalid trust
> session"));
>
> shell->add_trusted_session_for(trust_session,
> session->process_id());
> };
> }

Thanks. Fixed.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :
Download full text (5.4 KiB)

Just some quick notes:

1088 + * Copyright © 2013 Canonical Ltd.
...
3383 + * Copyright © 2013 Canonical Ltd.

I know this was first proposed months ago - but was it really written last year? And not changed this year?

~~~~

+TEST_F(MirClientTrustSessionAPITest, client_trust_session_api)
+{
+ struct ClientConfig : ClientConfigCommon
+ {
+ void exec()
+ {
+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
+
+ ASSERT_TRUE(connection != NULL);
+ EXPECT_TRUE(mir_connection_is_valid(connection));
+ EXPECT_STREQ("", mir_connection_get_error_message(connection));
+
+ mir_wait_for(mir_connection_start_trust_session(connection, __LINE__, trust_session_start_callback, NULL, this));
+ ASSERT_TRUE(trust_session != NULL);
+ EXPECT_EQ(started, 1);
+
+ mir_wait_for(mir_trust_session_stop(trust_session, trust_session_stop_callback, this));
+ EXPECT_EQ(stopped, 1);
+
+ mir_connection_release(connection);
+ }
+ } client_config;
+
+ launch_client_process(client_config);
+}

This test has an unclear name and asserts things that are unrelated to the purpose of the test. It would also be simpler using InProcessServer as its basis, not DefaultDisplayServerTestFixture (side note: that name has become misleading.) It is also overcomplicated in its use of management of connection. It should look like:

TEST_F(TrustSessionClientAPI, can_start_and_stop_a_trust_session)
{
    mir_wait_for(mir_connection_start_trust_session(connection, arbitrarty_base_session_pid, trust_session_start_callback, null_event_callback, this));
    ASSERT_THAT(trust_session, Ne(NULL));
    EXPECT_THAT(started, Eq(1));

    mir_wait_for(mir_trust_session_stop(trust_session, trust_session_stop_callback, this));
    EXPECT_THAT(stopped, Eq(1));
}

~~~~

+struct TrustSession : public testing::Test
+{
+ TrustSession()
+ {
+ }
+
+ testing::NiceMock<mtd::MockTrustSessionListener> trust_session_listener;
+ testing::NiceMock<mtd::MockSceneSession> trusted_helper;
+ testing::NiceMock<mtd::MockSceneSession> trusted_app1;
+ testing::NiceMock<mtd::MockSceneSession> trusted_app2;

NiceMock is inappropriate as these are the interactions under test.

+};
+}
+
+TEST_F(TrustSession, start_and_stop)

the name doesn't reflect what the test is about. There is no mention of adding and removing apps.

+{
+ using namespace testing;
+
+ auto shared_helper = mt::fake_shared(trusted_helper);
+ std::shared_ptr<ms::Session> shared_app1 = mt::fake_shared(trusted_app1);
+ std::shared_ptr<ms::Session> shared_app2 = mt::fake_shared(trusted_app2);
+
+ ms::TrustSessionImpl trust_session(shared_helper,
+ ms::a_trust_session(),
+ mt::fake_shared(trust_session_listener));

All the above initialization could be in the fixture

+ EXPECT_CALL(trusted_helper, begin_trust_session()).Times(1);
+ EXPECT_CALL(trusted_helper, end_trust_session()).Times(1);
+
+ EXPECT_CALL(trusted_app1, begin_trust_session()).Times(0);
+ EXPECT_CALL(trusted_app...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1456
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~nick-dedekind/mir/trusted_sessions/+merge/218975/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-ci/1634/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-utopic-i386-build/202
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-clang-utopic-amd64-build/203/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-utopic-touch/203
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-amd64-ci/153
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-amd64-ci/153/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-armhf-ci/152
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-armhf-ci/152/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/496
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/496/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/1457
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/7206

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-team-mir-development-branch-ci/1634/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

4082 === added file 'tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved'

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Setting to WIP as shifting focus to lp:~mir-team/mir/trusted_sessions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/CMakeLists.txt'
2--- examples/CMakeLists.txt 2014-05-05 03:36:45 +0000
3+++ examples/CMakeLists.txt 2014-05-15 13:19:23 +0000
4@@ -92,6 +92,9 @@
5
6 )
7
8+add_executable(mir_demo_client_trust_session trust_session.c)
9+target_link_libraries(mir_demo_client_trust_session mirclient)
10+
11 add_library(mirdraw STATIC graphics_utils.cpp)
12 target_link_libraries(mirdraw ${GLESv2_LIBRARIES})
13
14@@ -143,7 +146,7 @@
15 server_configuration.cpp
16 )
17
18-target_link_libraries(mir_demo_standalone_input_filter
19+target_link_libraries(mir_demo_standalone_input_filter
20 mirserver
21 )
22
23@@ -158,8 +161,9 @@
24 mir_demo_client_multiwin
25 mir_demo_client_display_config
26 mir_demo_client_progressbar
27+ mir_demo_client_trust_session
28 mir_demo_standalone_input_filter
29- mir_demo_standalone_render_to_fb
30+ mir_demo_standalone_render_to_fb
31 mir_demo_standalone_render_surfaces
32 )
33
34
35=== modified file 'examples/demo-inprocess-surface-client/inprocess_egl_client.cpp'
36--- examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2014-04-15 05:31:19 +0000
37+++ examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2014-05-15 13:19:23 +0000
38@@ -102,7 +102,7 @@
39
40 auto input_platform = mircv::InputPlatform::create();
41 input_thread = input_platform->create_input_thread(
42- surface->client_input_fd(),
43+ surface->client_input_fd(),
44 std::bind(std::mem_fn(&me::InprocessEGLClient::handle_event), this, std::placeholders::_1));
45 input_thread->start();
46
47
48=== added file 'examples/trust_session.c'
49--- examples/trust_session.c 1970-01-01 00:00:00 +0000
50+++ examples/trust_session.c 2014-05-15 13:19:23 +0000
51@@ -0,0 +1,249 @@
52+/*
53+ * Copyright © 2014 Canonical Ltd.
54+ *
55+ * This program is free software: you can redistribute it and/or modify
56+ * it under the terms of the GNU General Public License version 3 as
57+ * published by the Free Software Foundation.
58+ *
59+ * This program is distributed in the hope that it will be useful,
60+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62+ * GNU General Public License for more details.
63+ *
64+ * You should have received a copy of the GNU General Public License
65+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
66+ *
67+ * Authored by: Nick Dedekind <nick.dedekind <nick.dedekind@canonical.com>
68+ */
69+
70+#define _POSIX_SOURCE
71+
72+#include "mir_toolkit/mir_client_library.h"
73+#include "mir_toolkit/mir_trust_session.h"
74+
75+#include <assert.h>
76+#include <string.h>
77+#include <stdio.h>
78+#include <stdlib.h>
79+#include <getopt.h>
80+#include <unistd.h>
81+#include <errno.h>
82+#include <sys/wait.h>
83+#include <sys/types.h>
84+#include <signal.h>
85+
86+///\page trust_session.c trust_session.c: A mir client which starts a trust session and trusted client app.
87+/// mir_demo_client_trust_session shows the use of mir trust session API.
88+/// This program opens a mir connection and creates a trust session.
89+///\section trusted_helper trusted_helper()
90+/// Opens a mir connection and creates a trust session
91+/// before closing the trust session and connection.
92+///\section trust_session_app trust_session_app()
93+/// Opens a mir connection and creates a surface
94+/// before releasing the surface and closing the connection.
95+///\example trust_session.c A mir client demonstrating trust sessions.
96+///\section MirDemoState MirDemoState
97+/// The handles needs to be accessible both to callbacks and to the control function.
98+///\snippet trust_session.c MirDemoState_tag
99+///\section Callbacks Callbacks
100+///\snippet trust_session.c Callback_tag
101+/// This program creates two processes, both opening a mir connection, one starting
102+/// a trust session with the other process.
103+
104+///\internal [MirDemoState_tag]
105+// Utility structure for the state of a single session.
106+typedef struct MirDemoState
107+{
108+ MirConnection *connection;
109+ MirSurface *surface;
110+ MirTrustSession *trust_session;
111+ pid_t child_pid;
112+} MirDemoState;
113+///\internal [MirDemoState_tag]
114+
115+
116+///\internal [Callback_tag]
117+// Callback to update MirDemoState on trust_session_event
118+static void trust_session_event_callback(MirTrustSession* trust_session,
119+ MirTrustSessionState state,
120+ void* context)
121+{
122+ (void)trust_session;
123+ MirDemoState* demo_state = (MirDemoState*)context;
124+
125+ printf("Trust Session state updated to %d\n", state);
126+ if (state == mir_trust_session_state_stopped)
127+ {
128+ kill(demo_state->child_pid, SIGINT);
129+ }
130+}
131+///\internal [Callback_tag]
132+
133+void start_session(const char* server, const char* name, MirDemoState* mcd)
134+{
135+ // Call mir_connect synchronously
136+ mcd->connection = mir_connect_sync(server, name);
137+
138+ // We expect a connection handle;
139+ // we expect it to be valid; and,
140+ // we don't expect an error description
141+ assert(mcd->connection != NULL);
142+ assert(mir_connection_is_valid(mcd->connection));
143+ assert(strcmp(mir_connection_get_error_message(mcd->connection), "") == 0);
144+ printf("%s: Connected\n", name);
145+
146+ // We can query information about the platform we're running on
147+ {
148+ MirPlatformPackage platform_package;
149+ platform_package.data_items = -1;
150+ platform_package.fd_items = -1;
151+
152+ mir_connection_get_platform(mcd->connection, &platform_package);
153+ assert(0 <= platform_package.data_items);
154+ assert(0 <= platform_package.fd_items);
155+ }
156+}
157+
158+void stop_session(MirDemoState* mcd, const char* name)
159+{
160+ if (mcd->trust_session)
161+ {
162+ mir_trust_session_release(mcd->trust_session);
163+ mcd->trust_session = 0;
164+ printf("%s: Trust session released \n", name);
165+ }
166+
167+ if (mcd->surface)
168+ {
169+ // We should release our surface
170+ mir_surface_release_sync(mcd->surface);
171+ mcd->surface = 0;
172+ printf("%s: Surface released\n", name);
173+ }
174+
175+ // We should release our connection
176+ mir_connection_release(mcd->connection);
177+ printf("%s: Connection released\n", name);
178+}
179+
180+void trusted_helper(const char* server, pid_t child_pid)
181+{
182+ MirDemoState mcd;
183+ mcd.connection = 0;
184+ mcd.surface = 0;
185+ mcd.trust_session = 0;
186+ mcd.child_pid = child_pid;
187+ start_session(server, "trusted_helper", &mcd);
188+
189+ // We create a trust session
190+ mcd.trust_session = mir_connection_start_trust_session_sync(mcd.connection, getpid(), trust_session_event_callback, &mcd);
191+ assert(mcd.trust_session != NULL);
192+
193+ assert(mir_trust_session_get_state(mcd.trust_session) == mir_trust_session_state_started);
194+ puts("trusted_helper: Started trust session");
195+
196+ MirTrustSessionAddTrustResult add_result = mir_trust_session_add_trusted_session_sync(mcd.trust_session, child_pid);
197+ assert(add_result == mir_trust_session_add_tust_succeeded);
198+ printf("trusted_helper: added trusted session pid: %d\n", child_pid);
199+
200+ int status;
201+ printf("trusted_helper: waiting on child app: %d\n", child_pid);
202+ waitpid(child_pid, &status, 0);
203+
204+ if (mir_trust_session_get_state(mcd.trust_session) == mir_trust_session_state_started)
205+ {
206+ mir_trust_session_stop_sync(mcd.trust_session);
207+ assert(mir_trust_session_get_state(mcd.trust_session) == mir_trust_session_state_stopped);
208+ puts("trusted_helper: Stopped trust session");
209+ }
210+ else
211+ {
212+ puts("trusted_helper: Trusted session stoped by server");
213+ }
214+ puts("trusted_helper: Done");
215+
216+ stop_session(&mcd, "trusted_helper");
217+}
218+
219+void trust_session_app(const char* server)
220+{
221+ MirDemoState mcd;
222+ mcd.connection = 0;
223+ mcd.surface = 0;
224+ mcd.trust_session = 0;
225+ start_session(server, "trust_session_app", &mcd);
226+
227+ // Identify a supported pixel format
228+ MirPixelFormat pixel_format;
229+ unsigned int valid_formats;
230+ mir_connection_get_available_surface_formats(mcd.connection, &pixel_format, 1, &valid_formats);
231+ MirSurfaceParameters const request_params =
232+ {__PRETTY_FUNCTION__, 640, 480, pixel_format,
233+ mir_buffer_usage_hardware, mir_display_output_id_invalid};
234+
235+ // ...we create a surface using that format and wait for callback to complete.
236+ mcd.surface = mir_connection_create_surface_sync(mcd.connection, &request_params);
237+
238+ // We expect a surface handle;
239+ // we expect it to be valid; and,
240+ // we don't expect an error description
241+ assert(mcd.surface != NULL);
242+ assert(mir_surface_is_valid(mcd.surface));
243+ assert(strcmp(mir_surface_get_error_message(mcd.surface), "") == 0);
244+ puts("trust_session_app: Surface created");
245+
246+ puts("trust_session_app: Press any key to exit");
247+ // Wait for stdin
248+ getchar();
249+ puts("trust_session_app: Done");
250+
251+ stop_session(&mcd, "trust_session_app");
252+}
253+
254+// The main() function deals with parsing arguments and defaults
255+int main(int argc, char* argv[])
256+{
257+ // Some variables for holding command line options
258+ char const *server = NULL;
259+
260+ // Parse the command line
261+ {
262+ int arg;
263+ opterr = 0;
264+ while ((arg = getopt (argc, argv, "c:hm:")) != -1)
265+ {
266+ switch (arg)
267+ {
268+ case 'm':
269+ server = optarg;
270+ break;
271+
272+ case '?':
273+ case 'h':
274+ default:
275+ puts(argv[0]);
276+ puts("Usage:");
277+ puts(" -m <Mir server socket>");
278+ puts(" -h: this help text");
279+ return -1;
280+ }
281+ }
282+ }
283+
284+ // Start a new process.
285+ // This simulates the helper starting a new application which it adds to the trusted session.
286+ pid_t pid = fork();
287+
288+ if (pid == 0)
289+ {
290+ sleep(1);
291+ trust_session_app(server);
292+ }
293+ else if (pid > 0)
294+ {
295+ printf("trusted_helper: pid:%d , child:%d\n", getpid(), pid);
296+ trusted_helper(server, pid);
297+ }
298+
299+ return 0;
300+}
301
302=== added file 'include/client/mir_toolkit/mir_trust_session.h'
303--- include/client/mir_toolkit/mir_trust_session.h 1970-01-01 00:00:00 +0000
304+++ include/client/mir_toolkit/mir_trust_session.h 2014-05-15 13:19:23 +0000
305@@ -0,0 +1,119 @@
306+/*
307+ * Copyright © 2014 Canonical Ltd.
308+ *
309+ * This program is free software: you can redistribute it and/or modify it
310+ * under the terms of the GNU Lesser General Public License version 3,
311+ * as published by the Free Software Foundation.
312+ *
313+ * This program is distributed in the hope that it will be useful,
314+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
315+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
316+ * GNU Lesser General Public License for more details.
317+ *
318+ * You should have received a copy of the GNU Lesser General Public License
319+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
320+ */
321+
322+#ifndef MIR_TOOLKIT_MIR_TRUST_SESSION_H_
323+#define MIR_TOOLKIT_MIR_TRUST_SESSION_H_
324+
325+#include "mir_toolkit/mir_client_library.h"
326+
327+#include <sys/types.h>
328+
329+#ifdef __cplusplus
330+/**
331+ * \addtogroup mir_toolkit
332+ * @{
333+ */
334+extern "C" {
335+#endif
336+
337+/**
338+ * Create an new trust session
339+ * \param [in] connection The connection
340+ * \param [in] base_session_pid The process id of the initiating application
341+ * \param [in] start_callback Callback function to be invoked when request
342+ * completes
343+ * \param [in] start_callback The function to be called when the trust session event occurs
344+ * \param [in,out] context User data passed to the callback functions
345+ * \return A handle that can be passed to mir_wait_for
346+ */
347+MirWaitHandle *mir_connection_start_trust_session(MirConnection* connection,
348+ pid_t base_session_pid,
349+ mir_trust_session_callback start_callback,
350+ mir_trust_session_event_callback event_callback,
351+ void* context);
352+
353+/**
354+ * Create an new trust session
355+ * \param [in] connection The connection
356+ * \param [in] base_session_pid The process id of the initiating application
357+ * \param [in] callback Callback function to be invoked when request
358+ * completes
359+ * \param [in,out] context User data passed to the callback function
360+ * \param [in] callback The function to be called when the trust session event occurs
361+ * \return A handle that can be passed to mir_wait_for
362+ */
363+MirTrustSession *mir_connection_start_trust_session_sync(MirConnection* connection,
364+ pid_t base_session_pid,
365+ mir_trust_session_event_callback event_callback,
366+ void* context);
367+
368+/**
369+ * Add a process id to the trust session relationship
370+ * \param [in] trust_session The trust session
371+ * \param [in] session_pid The process id of the application to add
372+ * \param [in] callback Callback function to be invoked when request
373+ * completes
374+ * \return A MirTrustSessionAddTrustResult result of the call
375+ */
376+MirWaitHandle *mir_trust_session_add_trusted_session(MirTrustSession *trust_session,
377+ pid_t session_pid,
378+ mir_trust_session_add_trusted_session_callback callback,
379+ void* context);
380+
381+/**
382+ * Perform a mir_trust_session_add_trusted_pid() but also wait for and return the result.
383+ * \param [in] trust_session The trust session
384+ * \param [in] pid The process id of the application to add
385+ * \return A MirTrustSessionAddTrustResult result of the call
386+ */
387+MirTrustSessionAddTrustResult mir_trust_session_add_trusted_session_sync(MirTrustSession *trust_session,
388+ pid_t pid);
389+
390+/**
391+ * Request the cancellation of a trust session
392+ * \param [in] trust_session The trust session
393+ * \return True if the request was made successfully,
394+ * false otherwise
395+ */
396+MirWaitHandle *mir_trust_session_stop(MirTrustSession *trust_session, mir_trust_session_callback callback, void* context);
397+
398+/**
399+ * Perform a mir_trust_session_stop() but also wait for and return the result.
400+ * \param [in] trust_session The trust session
401+ * \return True if the request was made successfully,
402+ * false otherwise
403+ */
404+MirBool mir_trust_session_stop_sync(MirTrustSession *trust_session);
405+
406+/**
407+ * Return the state of trust session
408+ * \param [in] trust_session The trust session
409+ * \return The state of the trust session
410+ */
411+MirTrustSessionState mir_trust_session_get_state(MirTrustSession *trust_session);
412+
413+/**
414+ * Release a trust session
415+ * \param [in] trust_session The trust session to release
416+ */
417+void mir_trust_session_release(MirTrustSession* trust_session);
418+
419+#ifdef __cplusplus
420+}
421+/**@}*/
422+#endif
423+
424+#endif /* MIR_TOOLKIT_MIR_TRUST_SESSION_H_ */
425
426=== modified file 'include/server/mir/default_server_configuration.h'
427--- include/server/mir/default_server_configuration.h 2014-05-12 15:46:07 +0000
428+++ include/server/mir/default_server_configuration.h 2014-05-15 13:19:23 +0000
429@@ -85,6 +85,7 @@
430 class SurfaceStack;
431 class InputRegistrar;
432 class SceneReport;
433+class TrustSessionListener;
434 }
435 namespace graphics
436 {
437@@ -215,6 +216,7 @@
438 virtual std::shared_ptr<scene::PlacementStrategy> the_placement_strategy();
439 virtual std::shared_ptr<scene::SessionListener> the_session_listener();
440 virtual std::shared_ptr<shell::DisplayLayout> the_shell_display_layout();
441+ virtual std::shared_ptr<scene::TrustSessionListener> the_trust_session_listener();
442 /** @} */
443
444 /** @name internal scene configuration
445@@ -326,6 +328,7 @@
446 CachedPtr<scene::MediatingDisplayChanger> mediating_display_changer;
447 CachedPtr<graphics::GLProgramFactory> gl_program_factory;
448 CachedPtr<graphics::GLConfig> gl_config;
449+ CachedPtr<scene::TrustSessionListener> trust_session_listener;
450
451 private:
452 std::shared_ptr<options::Configuration> const configuration_options;
453
454=== modified file 'include/server/mir/frontend/event_sink.h'
455--- include/server/mir/frontend/event_sink.h 2013-08-28 03:41:48 +0000
456+++ include/server/mir/frontend/event_sink.h 2014-05-15 13:19:23 +0000
457@@ -35,6 +35,8 @@
458 virtual ~EventSink() = default;
459
460 virtual void handle_event(MirEvent const& e) = 0;
461+
462+ // TODO - remove these in favour of using handle_event
463 virtual void handle_lifecycle_event(MirLifecycleState state) = 0;
464 virtual void handle_display_config_change(graphics::DisplayConfiguration const& config) = 0;
465
466
467=== modified file 'include/server/mir/frontend/session.h'
468--- include/server/mir/frontend/session.h 2014-05-06 16:54:43 +0000
469+++ include/server/mir/frontend/session.h 2014-05-15 13:19:23 +0000
470@@ -50,6 +50,7 @@
471 virtual void destroy_surface(SurfaceId surface) = 0;
472 virtual std::shared_ptr<Surface> get_surface(SurfaceId surface) const = 0;
473
474+ virtual pid_t process_id() const = 0;
475 virtual std::string name() const = 0;
476
477 virtual void hide() = 0;
478
479=== modified file 'include/server/mir/frontend/session_mediator_report.h'
480--- include/server/mir/frontend/session_mediator_report.h 2014-03-06 06:05:17 +0000
481+++ include/server/mir/frontend/session_mediator_report.h 2014-05-15 13:19:23 +0000
482@@ -48,6 +48,12 @@
483
484 virtual void session_configure_display_called(std::string const& app_name) = 0;
485
486+ virtual void session_start_trust_session_called(std::string const& app_name, std::string const& trust_info) = 0;
487+
488+ virtual void session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info) = 0;
489+
490+ virtual void session_stop_trust_session_called(std::string const& app_name) = 0;
491+
492 virtual void session_error(
493 std::string const& app_name,
494 char const* method,
495
496=== modified file 'include/server/mir/frontend/shell.h'
497--- include/server/mir/frontend/shell.h 2014-04-15 05:31:19 +0000
498+++ include/server/mir/frontend/shell.h 2014-05-15 13:19:23 +0000
499@@ -20,6 +20,7 @@
500 #define MIR_FRONTEND_SHELL_H_
501
502 #include "mir/frontend/surface_id.h"
503+#include "mir_toolkit/common.h"
504
505 #include <sys/types.h>
506
507@@ -30,11 +31,13 @@
508 namespace scene
509 {
510 struct SurfaceCreationParameters;
511+struct TrustSessionCreationParameters;
512 }
513 namespace frontend
514 {
515 class EventSink;
516 class Session;
517+class TrustSession;
518
519 class Shell
520 {
521@@ -54,6 +57,12 @@
522
523 virtual void handle_surface_created(std::shared_ptr<Session> const& session) = 0;
524
525+ virtual std::shared_ptr<TrustSession> start_trust_session_for(std::shared_ptr<Session> const& session,
526+ scene::TrustSessionCreationParameters const& params) = 0;
527+ virtual MirTrustSessionAddTrustResult add_trusted_session_for(std::shared_ptr<TrustSession> const& trust_session,
528+ pid_t session_pid) = 0;
529+ virtual void stop_trust_session(std::shared_ptr<TrustSession> const& trust_session) = 0;
530+
531 protected:
532 Shell() = default;
533 Shell(const Shell&) = delete;
534
535=== added file 'include/server/mir/frontend/trust_session.h'
536--- include/server/mir/frontend/trust_session.h 1970-01-01 00:00:00 +0000
537+++ include/server/mir/frontend/trust_session.h 2014-05-15 13:19:23 +0000
538@@ -0,0 +1,53 @@
539+/*
540+ * Copyright © 2014 Canonical Ltd.
541+ *
542+ * This program is free software: you can redistribute it and/or modify it
543+ * under the terms of the GNU General Public License version 3,
544+ * as published by the Free Software Foundation.
545+ *
546+ * This program is distributed in the hope that it will be useful,
547+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
548+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
549+ * GNU General Public License for more details.
550+ *
551+ * You should have received a copy of the GNU General Public License
552+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
553+ *
554+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
555+ */
556+
557+#ifndef MIR_FRONTEND_TRUST_SESSION_H_
558+#define MIR_FRONTEND_TRUST_SESSION_H_
559+
560+#include "mir_toolkit/common.h"
561+
562+#include <sys/types.h>
563+#include <vector>
564+#include <string>
565+#include <memory>
566+
567+namespace mir
568+{
569+
570+namespace frontend
571+{
572+class TrustSession
573+{
574+public:
575+ virtual ~TrustSession() = default;
576+
577+ virtual MirTrustSessionState get_state() const = 0;
578+
579+ virtual void start() = 0;
580+ virtual void stop() = 0;
581+
582+protected:
583+ TrustSession() = default;
584+ TrustSession(const TrustSession&) = delete;
585+ TrustSession& operator=(const TrustSession&) = delete;
586+};
587+
588+}
589+}
590+
591+#endif // MIR_FRONTEND_TRUST_SESSION_H_
592
593=== added file 'include/server/mir/scene/null_trust_session_listener.h'
594--- include/server/mir/scene/null_trust_session_listener.h 1970-01-01 00:00:00 +0000
595+++ include/server/mir/scene/null_trust_session_listener.h 2014-05-15 13:19:23 +0000
596@@ -0,0 +1,50 @@
597+/*
598+ * Copyright © 2014 Canonical Ltd.
599+ *
600+ * This program is free software: you can redistribute it and/or modify it
601+ * under the terms of the GNU General Public License version 3,
602+ * as published by the Free Software Foundation.
603+ *
604+ * This program is distributed in the hope that it will be useful,
605+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
606+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
607+ * GNU General Public License for more details.
608+ *
609+ * You should have received a copy of the GNU General Public License
610+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
611+ *
612+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
613+ */
614+
615+#ifndef MIR_SCENE_NULL_TRUST_SESSION_LISTENER_H_
616+#define MIR_SCENE_NULL_TRUST_SESSION_LISTENER_H_
617+
618+#include "mir/scene/trust_session_listener.h"
619+
620+namespace mir
621+{
622+namespace scene
623+{
624+
625+class NullTrustSessionListener : public TrustSessionListener
626+{
627+public:
628+ NullTrustSessionListener() = default;
629+ virtual ~NullTrustSessionListener() noexcept(true) = default;
630+
631+ void starting(std::shared_ptr<TrustSession> const&) override {};
632+ void stopping(std::shared_ptr<TrustSession> const&) override {};
633+
634+ void trusted_session_beginning(TrustSession const&, std::shared_ptr<Session> const&) override {};
635+ void trusted_session_ending(TrustSession const&, std::shared_ptr<Session> const&) override {};
636+
637+protected:
638+ NullTrustSessionListener(const NullTrustSessionListener&) = delete;
639+ NullTrustSessionListener& operator=(const NullTrustSessionListener&) = delete;
640+};
641+
642+}
643+}
644+
645+
646+#endif // MIR_SHELL_NULL_TRUST_SESSION_LISTENER_H_
647
648=== modified file 'include/server/mir/scene/session.h'
649--- include/server/mir/scene/session.h 2014-04-15 05:31:19 +0000
650+++ include/server/mir/scene/session.h 2014-05-15 13:19:23 +0000
651@@ -34,12 +34,14 @@
652 {
653 public:
654 virtual void force_requests_to_complete() = 0;
655- virtual pid_t process_id() const = 0;
656
657 virtual void take_snapshot(SnapshotCallback const& snapshot_taken) = 0;
658 virtual std::shared_ptr<Surface> default_surface() const = 0;
659 virtual void set_lifecycle_state(MirLifecycleState state) = 0;
660 virtual void send_display_config(graphics::DisplayConfiguration const&) = 0;
661+
662+ virtual void begin_trust_session() = 0;
663+ virtual void end_trust_session() = 0;
664 };
665 }
666 }
667
668=== added file 'include/server/mir/scene/trust_session.h'
669--- include/server/mir/scene/trust_session.h 1970-01-01 00:00:00 +0000
670+++ include/server/mir/scene/trust_session.h 2014-05-15 13:19:23 +0000
671@@ -0,0 +1,43 @@
672+/*
673+ * Copyright © 2014 Canonical Ltd.
674+ *
675+ * This program is free software: you can redistribute it and/or modify it
676+ * under the terms of the GNU General Public License version 3,
677+ * as published by the Free Software Foundation.
678+ *
679+ * This program is distributed in the hope that it will be useful,
680+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
681+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
682+ * GNU General Public License for more details.
683+ *
684+ * You should have received a copy of the GNU General Public License
685+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
686+ *
687+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
688+ */
689+
690+#ifndef MIR_SCENE_TRUST_SESSION_H_
691+#define MIR_SCENE_TRUST_SESSION_H_
692+
693+#include "mir/frontend/trust_session.h"
694+
695+namespace mir
696+{
697+namespace scene
698+{
699+class Session;
700+
701+class TrustSession : public frontend::TrustSession
702+{
703+public:
704+ virtual std::weak_ptr<Session> get_trusted_helper() const = 0;
705+
706+ virtual bool add_trusted_child(std::shared_ptr<Session> const& session) = 0;
707+ virtual void remove_trusted_child(std::shared_ptr<Session> const& session) = 0;
708+ virtual void for_each_trusted_child(std::function<void(std::shared_ptr<Session> const&)> f) const = 0;
709+};
710+
711+}
712+}
713+
714+#endif // MIR_SHELL_TRUST_SESSION_H_
715
716=== added file 'include/server/mir/scene/trust_session_creation_parameters.h'
717--- include/server/mir/scene/trust_session_creation_parameters.h 1970-01-01 00:00:00 +0000
718+++ include/server/mir/scene/trust_session_creation_parameters.h 2014-05-15 13:19:23 +0000
719@@ -0,0 +1,46 @@
720+/*
721+ * Copyright © 2014 Canonical Ltd.
722+ *
723+ * This program is free software: you can redistribute it and/or modify it
724+ * under the terms of the GNU General Public License version 3,
725+ * as published by the Free Software Foundation.
726+ *
727+ * This program is distributed in the hope that it will be useful,
728+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
729+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
730+ * GNU General Public License for more details.
731+ *
732+ * You should have received a copy of the GNU General Public License
733+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
734+ *
735+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
736+ */
737+
738+#ifndef MIR_SCENE_TRUSTED_SESSION_CREATION_PARAMETERS_H_
739+#define MIR_SCENE_TRUSTED_SESSION_CREATION_PARAMETERS_H_
740+
741+#include <sys/types.h>
742+#include <vector>
743+
744+namespace mir
745+{
746+namespace scene
747+{
748+
749+struct TrustSessionCreationParameters
750+{
751+ TrustSessionCreationParameters();
752+
753+ TrustSessionCreationParameters& set_base_process_id(pid_t process_id);
754+
755+ pid_t base_process_id;
756+};
757+
758+bool operator==(const TrustSessionCreationParameters& lhs, const TrustSessionCreationParameters& rhs);
759+bool operator!=(const TrustSessionCreationParameters& lhs, const TrustSessionCreationParameters& rhs);
760+
761+TrustSessionCreationParameters a_trust_session();
762+}
763+}
764+
765+#endif /* MIR_SCENE_TRUSTED_SESSION_CREATION_PARAMETERS_H_ */
766
767=== added file 'include/server/mir/scene/trust_session_listener.h'
768--- include/server/mir/scene/trust_session_listener.h 1970-01-01 00:00:00 +0000
769+++ include/server/mir/scene/trust_session_listener.h 2014-05-15 13:19:23 +0000
770@@ -0,0 +1,52 @@
771+/*
772+ * Copyright © 2014 Canonical Ltd.
773+ *
774+ * This program is free software: you can redistribute it and/or modify it
775+ * under the terms of the GNU General Public License version 3,
776+ * as published by the Free Software Foundation.
777+ *
778+ * This program is distributed in the hope that it will be useful,
779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
781+ * GNU General Public License for more details.
782+ *
783+ * You should have received a copy of the GNU General Public License
784+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
785+ *
786+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
787+ */
788+
789+#ifndef MIR_SCENE_TRUST_SESSION_LISTENER_H_
790+#define MIR_SCENE_TRUST_SESSION_LISTENER_H_
791+
792+#include <memory>
793+
794+namespace mir
795+{
796+namespace scene
797+{
798+class Session;
799+class TrustSession;
800+
801+class TrustSessionListener
802+{
803+public:
804+ virtual void starting(std::shared_ptr<TrustSession> const& trust_session) = 0;
805+ virtual void stopping(std::shared_ptr<TrustSession> const& trust_session) = 0;
806+
807+ virtual void trusted_session_beginning(TrustSession const& trust_session, std::shared_ptr<Session> const& session) = 0;
808+ virtual void trusted_session_ending(TrustSession const& trust_session, std::shared_ptr<Session> const& session) = 0;
809+
810+protected:
811+ TrustSessionListener() = default;
812+ virtual ~TrustSessionListener() = default;
813+
814+ TrustSessionListener(const TrustSessionListener&) = delete;
815+ TrustSessionListener& operator=(const TrustSessionListener&) = delete;
816+};
817+
818+}
819+}
820+
821+
822+#endif // MIR_SCENE_TRUST_SESSION_LISTENER_H_
823
824=== modified file 'include/shared/mir_toolkit/client_types.h'
825--- include/shared/mir_toolkit/client_types.h 2014-05-08 11:48:23 +0000
826+++ include/shared/mir_toolkit/client_types.h 2014-05-15 13:19:23 +0000
827@@ -46,6 +46,7 @@
828 typedef struct MirConnection MirConnection;
829 typedef struct MirSurface MirSurface;
830 typedef struct MirScreencast MirScreencast;
831+typedef struct MirTrustSession MirTrustSession;
832
833 /**
834 * Returned by asynchronous functions. Must not be free'd by
835@@ -319,6 +320,31 @@
836 */
837 typedef void (*mir_screencast_callback)(MirScreencast *screencast, void *client_context);
838
839+/**
840+ * Callback member of MirTrustSession for handling of trust sessions.
841+ * \param [in] tps The trust session associated with the callback
842+ * \param [in,out] context The context provided by the client
843+ */
844+typedef void (*mir_trust_session_callback)(MirTrustSession* tps, void* context);
845+
846+/**
847+ * Callback member of MirTrustSession for adding trusted sessions
848+ * \param [in] trusted_session The trust session associated with the callback
849+ * \param [in] result The result of adding a trusted session
850+ * \param [in,out] context The context provided by the client
851+ */
852+typedef void (*mir_trust_session_add_trusted_session_callback)(
853+ MirTrustSession* trusted_session, MirTrustSessionAddTrustResult result, void* context);
854+
855+/**
856+ * Callback member of MirTrustSession for handling of trust sessions events.
857+ * \param [in] trusted_session The trust session associated with the callback
858+ * \param [in] state The state of the trust session
859+ * \param [in,out] context The context provided by the client
860+ */
861+typedef void (*mir_trust_session_event_callback)(
862+ MirTrustSession* trusted_session, MirTrustSessionState state, void* context);
863+
864 #ifdef __cplusplus
865 }
866 /**@}*/
867
868=== modified file 'include/shared/mir_toolkit/common.h'
869--- include/shared/mir_toolkit/common.h 2014-03-06 06:05:17 +0000
870+++ include/shared/mir_toolkit/common.h 2014-05-15 13:19:23 +0000
871@@ -87,6 +87,23 @@
872 mir_power_mode_off /* Powered down. */
873 } MirPowerMode;
874
875+typedef enum MirTrustSessionState
876+{
877+ mir_trust_session_state_stopped = 0,
878+ mir_trust_session_state_started
879+} MirTrustSessionState;
880+
881+/**
882+ * MirTrustSessionAddTrustResult specifies the result of a
883+ * call to add an app id to a trust session
884+ */
885+typedef enum
886+{
887+ mir_trust_session_add_tust_failed,
888+ mir_trust_session_add_tust_duplicate,
889+ mir_trust_session_add_tust_succeeded
890+} MirTrustSessionAddTrustResult;
891+
892 /**
893 * The order of components in a format enum matches the
894 * order of the components as they would be written in an
895
896=== modified file 'include/shared/mir_toolkit/event.h'
897--- include/shared/mir_toolkit/event.h 2014-03-06 06:05:17 +0000
898+++ include/shared/mir_toolkit/event.h 2014-05-15 13:19:23 +0000
899@@ -40,7 +40,8 @@
900 mir_event_type_key,
901 mir_event_type_motion,
902 mir_event_type_surface,
903- mir_event_type_resize
904+ mir_event_type_resize,
905+ mir_event_type_trust_session_state_change
906 } MirEventType;
907
908 typedef enum {
909@@ -204,6 +205,13 @@
910 int height;
911 } MirResizeEvent;
912
913+typedef struct
914+{
915+ MirEventType type;
916+
917+ MirTrustSessionState new_state;
918+} MirTrustSessionEvent;
919+
920 typedef union
921 {
922 MirEventType type;
923@@ -211,6 +219,7 @@
924 MirMotionEvent motion;
925 MirSurfaceEvent surface;
926 MirResizeEvent resize;
927+ MirTrustSessionEvent trust_session;
928 } MirEvent;
929
930 #ifdef __cplusplus
931
932=== modified file 'include/test/mir_test/test_protobuf_client.h'
933--- include/test/mir_test/test_protobuf_client.h 2013-08-28 03:41:48 +0000
934+++ include/test/mir_test/test_protobuf_client.h 2014-05-15 13:19:23 +0000
935@@ -21,6 +21,7 @@
936 #define MIR_TEST_TEST_CLIENT_H_
937
938 #include "mir_protobuf.pb.h"
939+#include "wait_condition.h"
940
941 #include <gmock/gmock.h>
942
943@@ -49,6 +50,10 @@
944 mir::protobuf::Connection connection;
945 mir::protobuf::DisplayConfiguration disp_config;
946 mir::protobuf::DisplayConfiguration disp_config_response;
947+ mir::protobuf::TrustSessionParameters trust_session_parameters;
948+ mir::protobuf::TrustedSession trusted_session;
949+ mir::protobuf::TrustSession trust_session;
950+ mir::protobuf::TrustSessionAddResult add_trust_result;
951
952 MOCK_METHOD0(connect_done, void());
953 MOCK_METHOD0(create_surface_done, void());
954@@ -57,6 +62,9 @@
955 MOCK_METHOD0(disconnect_done, void());
956 MOCK_METHOD0(drm_auth_magic_done, void());
957 MOCK_METHOD0(display_configure_done, void());
958+ MOCK_METHOD0(trust_session_start_done, void());
959+ MOCK_METHOD0(trust_session_add_trusted_session_done, void());
960+ MOCK_METHOD0(trust_session_stop_done, void());
961
962 void on_connect_done();
963
964@@ -94,6 +102,12 @@
965
966 void wait_for_configure_display_done();
967
968+ void wait_for_trust_session_start_done();
969+
970+ void wait_for_trust_session_add_trusted_session_done();
971+
972+ void wait_for_trust_session_stop_done();
973+
974 const int maxwait;
975 std::atomic<bool> connect_done_called;
976 std::atomic<bool> create_surface_called;
977@@ -104,6 +118,10 @@
978 std::atomic<bool> configure_display_done_called;
979 std::atomic<bool> tfd_done_called;
980
981+ WaitCondition wc_trust_session_start;
982+ WaitCondition wc_trust_session_add;
983+ WaitCondition wc_trust_session_stop;
984+
985 std::atomic<int> connect_done_count;
986 std::atomic<int> create_surface_done_count;
987 std::atomic<int> disconnect_done_count;
988
989=== modified file 'include/test/mir_test_doubles/mock_scene_session.h'
990--- include/test/mir_test_doubles/mock_scene_session.h 2014-05-07 14:25:45 +0000
991+++ include/test/mir_test_doubles/mock_scene_session.h 2014-05-15 13:19:23 +0000
992@@ -52,6 +52,9 @@
993 MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int));
994
995 MOCK_METHOD1(set_lifecycle_state, void(MirLifecycleState state));
996+
997+ MOCK_METHOD0(begin_trust_session, void());
998+ MOCK_METHOD0(end_trust_session, void());
999 };
1000
1001 }
1002
1003=== modified file 'include/test/mir_test_doubles/mock_shell.h'
1004--- include/test/mir_test_doubles/mock_shell.h 2014-04-15 05:31:19 +0000
1005+++ include/test/mir_test_doubles/mock_shell.h 2014-05-15 13:19:23 +0000
1006@@ -22,6 +22,7 @@
1007 #include "mir/scene/surface_creation_parameters.h"
1008 #include "mir/frontend/shell.h"
1009 #include "mir/frontend/surface_id.h"
1010+#include "mir/scene/trust_session_creation_parameters.h"
1011
1012 #include <gmock/gmock.h>
1013
1014@@ -43,6 +44,14 @@
1015
1016 MOCK_METHOD2(create_surface_for, frontend::SurfaceId(std::shared_ptr<frontend::Session> const&, scene::SurfaceCreationParameters const&));
1017 MOCK_METHOD1(handle_surface_created, void(std::shared_ptr<frontend::Session> const&));
1018+
1019+ MOCK_METHOD2(start_trust_session_for, std::shared_ptr<frontend::TrustSession>(
1020+ std::shared_ptr<frontend::Session> const&,
1021+ scene::TrustSessionCreationParameters const&));
1022+ MOCK_METHOD2(add_trusted_session_for, MirTrustSessionAddTrustResult(
1023+ std::shared_ptr<frontend::TrustSession> const&,
1024+ pid_t));
1025+ MOCK_METHOD1(stop_trust_session, void(std::shared_ptr<frontend::TrustSession> const&));
1026 };
1027
1028 }
1029
1030=== added file 'include/test/mir_test_doubles/mock_trust_session_listener.h'
1031--- include/test/mir_test_doubles/mock_trust_session_listener.h 1970-01-01 00:00:00 +0000
1032+++ include/test/mir_test_doubles/mock_trust_session_listener.h 2014-05-15 13:19:23 +0000
1033@@ -0,0 +1,48 @@
1034+/*
1035+ * Copyright © 2014 Canonical Ltd.
1036+ *
1037+ * This program is free software: you can redistribute it and/or modify it
1038+ * under the terms of the GNU General Public License version 3,
1039+ * as published by the Free Software Foundation.
1040+ *
1041+ * This program is distributed in the hope that it will be useful,
1042+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1043+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1044+ * GNU General Public License for more details.
1045+ *
1046+ * You should have received a copy of the GNU General Public License
1047+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1048+ *
1049+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
1050+ */
1051+
1052+#ifndef MIR_TEST_DOUBLES_MOCK_TRUST_SESSION_LISTENER_H_
1053+#define MIR_TEST_DOUBLES_MOCK_TRUST_SESSION_LISTENER_H_
1054+
1055+#include "mir/scene/trust_session_listener.h"
1056+
1057+#include <gmock/gmock.h>
1058+
1059+namespace mir
1060+{
1061+namespace test
1062+{
1063+namespace doubles
1064+{
1065+
1066+struct MockTrustSessionListener : public scene::TrustSessionListener
1067+{
1068+ virtual ~MockTrustSessionListener() noexcept(true) {}
1069+
1070+ MOCK_METHOD1(starting, void(std::shared_ptr<scene::TrustSession> const&));
1071+ MOCK_METHOD1(stopping, void(std::shared_ptr<scene::TrustSession> const&));
1072+
1073+ MOCK_METHOD2(trusted_session_beginning, void(scene::TrustSession const&, std::shared_ptr<scene::Session> const&));
1074+ MOCK_METHOD2(trusted_session_ending, void(scene::TrustSession const&, std::shared_ptr<scene::Session> const&));
1075+};
1076+
1077+}
1078+}
1079+} // namespace mir
1080+
1081+#endif // MIR_TEST_DOUBLES_MOCK_TRUST_SESSION_LISTENER_H_
1082
1083=== added file 'include/test/mir_test_doubles/null_trust_session.h'
1084--- include/test/mir_test_doubles/null_trust_session.h 1970-01-01 00:00:00 +0000
1085+++ include/test/mir_test_doubles/null_trust_session.h 2014-05-15 13:19:23 +0000
1086@@ -0,0 +1,69 @@
1087+/*
1088+ * Copyright © 2013 Canonical Ltd.
1089+ *
1090+ * This program is free software: you can redistribute it and/or modify it
1091+ * under the terms of the GNU General Public License version 3,
1092+ * as published by the Free Software Foundation.
1093+ *
1094+ * This program is distributed in the hope that it will be useful,
1095+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1096+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1097+ * GNU General Public License for more details.
1098+ *
1099+ * You should have received a copy of the GNU General Public License
1100+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1101+ *
1102+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
1103+ */
1104+
1105+#ifndef MIR_TEST_DOUBLES_NULL_TRUST_SESSION_H_
1106+#define MIR_TEST_DOUBLES_NULL_TRUST_SESSION_H_
1107+
1108+#include "mir/scene/trust_session.h"
1109+
1110+namespace mir
1111+{
1112+namespace test
1113+{
1114+namespace doubles
1115+{
1116+
1117+class NullTrustSession : public scene::TrustSession
1118+{
1119+ MirTrustSessionState get_state() const override
1120+ {
1121+ return mir_trust_session_state_stopped;
1122+ }
1123+
1124+ void start() override
1125+ {
1126+ }
1127+
1128+ void stop() override
1129+ {
1130+ }
1131+
1132+ std::weak_ptr<scene::Session> get_trusted_helper() const override
1133+ {
1134+ return std::weak_ptr<scene::Session>();
1135+ }
1136+
1137+ bool add_trusted_child(std::shared_ptr<scene::Session> const&) override
1138+ {
1139+ return false;
1140+ }
1141+
1142+ void remove_trusted_child(std::shared_ptr<scene::Session> const&) override
1143+ {
1144+ }
1145+
1146+ void for_each_trusted_child(std::function<void(std::shared_ptr<scene::Session> const&)>) const override
1147+ {
1148+ }
1149+};
1150+
1151+}
1152+}
1153+}
1154+
1155+#endif /* MIR_TEST_DOUBLES_NULL_TRUST_SESSION_H_ */
1156
1157=== modified file 'include/test/mir_test_doubles/stub_scene_session.h'
1158--- include/test/mir_test_doubles/stub_scene_session.h 2014-05-06 16:54:43 +0000
1159+++ include/test/mir_test_doubles/stub_scene_session.h 2014-05-15 13:19:23 +0000
1160@@ -76,6 +76,14 @@
1161 void set_lifecycle_state(MirLifecycleState /*state*/)
1162 {
1163 }
1164+
1165+ void begin_trust_session() override
1166+ {
1167+ }
1168+
1169+ void end_trust_session() override
1170+ {
1171+ }
1172 };
1173
1174 }
1175
1176=== modified file 'include/test/mir_test_doubles/stub_session.h'
1177--- include/test/mir_test_doubles/stub_session.h 2014-05-06 16:54:43 +0000
1178+++ include/test/mir_test_doubles/stub_session.h 2014-05-15 13:19:23 +0000
1179@@ -41,6 +41,10 @@
1180 {
1181 return std::shared_ptr<frontend::Surface>();
1182 }
1183+ pid_t process_id() const override
1184+ {
1185+ return 0;
1186+ }
1187 std::string name() const override
1188 {
1189 return std::string();
1190
1191=== modified file 'include/test/mir_test_doubles/stub_shell.h'
1192--- include/test/mir_test_doubles/stub_shell.h 2014-04-15 05:31:19 +0000
1193+++ include/test/mir_test_doubles/stub_shell.h 2014-05-15 13:19:23 +0000
1194@@ -49,6 +49,21 @@
1195 void handle_surface_created(std::shared_ptr<frontend::Session> const& /* session */) override
1196 {
1197 }
1198+ std::shared_ptr<frontend::TrustSession> start_trust_session_for(std::shared_ptr<frontend::Session> const& /* session */,
1199+ scene::TrustSessionCreationParameters const& /* params */)
1200+ {
1201+ return std::shared_ptr<frontend::TrustSession>();
1202+ }
1203+ MirTrustSessionAddTrustResult add_trusted_session_for(
1204+ std::shared_ptr<frontend::TrustSession> const& /* trust_session */,
1205+ pid_t /* session_pid */)
1206+ {
1207+ return mir_trust_session_add_tust_failed;
1208+ }
1209+ void stop_trust_session(std::shared_ptr<frontend::TrustSession> const& /* trust_session */)
1210+ {
1211+ }
1212+
1213 std::shared_ptr<StubSession> const stub_session;
1214 };
1215
1216
1217=== modified file 'src/client/CMakeLists.txt'
1218--- src/client/CMakeLists.txt 2014-04-29 18:40:27 +0000
1219+++ src/client/CMakeLists.txt 2014-05-15 13:19:23 +0000
1220@@ -48,6 +48,9 @@
1221 mir_screencast.cpp
1222 mir_screencast_api.cpp
1223 mir_cursor_api.cpp
1224+ mir_trust_session.cpp
1225+ mir_trust_session_api.cpp
1226+ event_distributor.cpp
1227 )
1228
1229 add_library(
1230@@ -82,7 +85,7 @@
1231 mirclientlttngstatic
1232
1233 ${MIR_COMMON_PLATFORM_LIBRARIES}
1234-
1235+
1236 3rd_party
1237 )
1238
1239
1240=== modified file 'src/client/connection_configuration.h'
1241--- src/client/connection_configuration.h 2014-03-06 06:05:17 +0000
1242+++ src/client/connection_configuration.h 2014-05-15 13:19:23 +0000
1243@@ -47,6 +47,7 @@
1244 class ClientPlatformFactory;
1245 class DisplayConfiguration;
1246 class LifecycleControl;
1247+class EventDistributor;
1248
1249 class ConnectionConfiguration
1250 {
1251@@ -60,6 +61,7 @@
1252 virtual std::shared_ptr<input::receiver::InputPlatform> the_input_platform() = 0;
1253 virtual std::shared_ptr<DisplayConfiguration> the_display_configuration() = 0;
1254 virtual std::shared_ptr<LifecycleControl> the_lifecycle_control() = 0;
1255+ virtual std::shared_ptr<EventDistributor> the_event_distributor() = 0;
1256
1257 protected:
1258 ConnectionConfiguration() = default;
1259
1260=== modified file 'src/client/default_connection_configuration.cpp'
1261--- src/client/default_connection_configuration.cpp 2014-03-26 05:48:59 +0000
1262+++ src/client/default_connection_configuration.cpp 2014-05-15 13:19:23 +0000
1263@@ -32,6 +32,7 @@
1264 #include "lifecycle_control.h"
1265 #include "mir/shared_library.h"
1266 #include "client_platform_factory.h"
1267+#include "event_distributor.h"
1268
1269 namespace mcl = mir::client;
1270
1271@@ -81,7 +82,7 @@
1272 [this]
1273 {
1274 return mcl::rpc::make_rpc_channel(
1275- the_socket_file(), the_surface_map(), the_display_configuration(), the_rpc_report(), the_lifecycle_control());
1276+ the_socket_file(), the_surface_map(), the_display_configuration(), the_rpc_report(), the_lifecycle_control(), the_event_distributor());
1277 });
1278 }
1279
1280@@ -182,3 +183,12 @@
1281 return std::make_shared<mcl::LifecycleControl>();
1282 });
1283 }
1284+
1285+std::shared_ptr<mcl::EventDistributor> mcl::DefaultConnectionConfiguration::the_event_distributor()
1286+{
1287+ return event_distributor(
1288+ []
1289+ {
1290+ return std::make_shared<mcl::EventDistributor>();
1291+ });
1292+}
1293
1294=== modified file 'src/client/default_connection_configuration.h'
1295--- src/client/default_connection_configuration.h 2014-03-06 06:05:17 +0000
1296+++ src/client/default_connection_configuration.h 2014-05-15 13:19:23 +0000
1297@@ -54,6 +54,7 @@
1298 std::shared_ptr<input::receiver::InputPlatform> the_input_platform();
1299 std::shared_ptr<DisplayConfiguration> the_display_configuration();
1300 std::shared_ptr<LifecycleControl> the_lifecycle_control();
1301+ std::shared_ptr<EventDistributor> the_event_distributor();
1302
1303 virtual std::string the_socket_file();
1304 virtual std::shared_ptr<rpc::RpcReport> the_rpc_report();
1305@@ -67,6 +68,7 @@
1306 CachedPtr<ConnectionSurfaceMap> surface_map;
1307 CachedPtr<DisplayConfiguration> display_configuration;
1308 CachedPtr<LifecycleControl> lifecycle_control;
1309+ CachedPtr<EventDistributor> event_distributor;
1310
1311 CachedPtr<rpc::RpcReport> rpc_report;
1312 CachedPtr<input::receiver::InputReceiverReport> input_receiver_report;
1313
1314=== added file 'src/client/event_distributor.cpp'
1315--- src/client/event_distributor.cpp 1970-01-01 00:00:00 +0000
1316+++ src/client/event_distributor.cpp 2014-05-15 13:19:23 +0000
1317@@ -0,0 +1,57 @@
1318+/*
1319+ * Copyright © 2014 Canonical Ltd.
1320+ *
1321+ * This program is free software: you can redistribute it and/or modify it
1322+ * under the terms of the GNU Lesser General Public License version 3,
1323+ * as published by the Free Software Foundation.
1324+ *
1325+ * This program is distributed in the hope that it will be useful,
1326+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1327+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1328+ * GNU Lesser General Public License for more details.
1329+ *
1330+ * You should have received a copy of the GNU Lesser General Public License
1331+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1332+ *
1333+ * Authored by: Nick Dedekind <nick.dedekind@gmail.com>
1334+ */
1335+
1336+#include "event_distributor.h"
1337+
1338+namespace mcl = mir::client;
1339+
1340+mcl::EventDistributor::EventDistributor() :
1341+ next_fn_id(0)
1342+{
1343+}
1344+
1345+int mcl::EventDistributor::register_event_handler(std::function<void(MirEvent const&)> const& fn)
1346+{
1347+ std::lock_guard<decltype(mutex)> lock(mutex);
1348+
1349+ int id = next_id();
1350+ event_handlers[id] = fn;
1351+ return id;
1352+}
1353+
1354+void mcl::EventDistributor::unregister_event_handler(int id)
1355+{
1356+ std::lock_guard<decltype(mutex)> lock(mutex);
1357+
1358+ event_handlers.erase(id);
1359+}
1360+
1361+void mcl::EventDistributor::handle_event(MirEvent const& event)
1362+{
1363+ std::lock_guard<decltype(mutex)> lock(mutex);
1364+
1365+ for (auto const& fn : event_handlers)
1366+ {
1367+ fn.second(event);
1368+ }
1369+}
1370+
1371+int mcl::EventDistributor::next_id()
1372+{
1373+ return ++next_fn_id;
1374+}
1375\ No newline at end of file
1376
1377=== added file 'src/client/event_distributor.h'
1378--- src/client/event_distributor.h 1970-01-01 00:00:00 +0000
1379+++ src/client/event_distributor.h 2014-05-15 13:19:23 +0000
1380@@ -0,0 +1,52 @@
1381+/*
1382+ * Copyright © 2014 Canonical Ltd.
1383+ *
1384+ * This program is free software: you can redistribute it and/or modify it
1385+ * under the terms of the GNU Lesser General Public License version 3,
1386+ * as published by the Free Software Foundation.
1387+ *
1388+ * This program is distributed in the hope that it will be useful,
1389+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1390+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1391+ * GNU Lesser General Public License for more details.
1392+ *
1393+ * You should have received a copy of the GNU Lesser General Public License
1394+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1395+ *
1396+ * Authored by: Nick Dedekind <nick.dedekind@gmail.com>
1397+ */
1398+
1399+#ifndef MIR_CLIENT_EVENT_DISTRIBUTOR_H
1400+
1401+#include "mir_toolkit/event.h"
1402+
1403+#include <functional>
1404+#include <mutex>
1405+#include <map>
1406+
1407+namespace mir
1408+{
1409+namespace client
1410+{
1411+class EventDistributor
1412+{
1413+public:
1414+ EventDistributor();
1415+ ~EventDistributor() = default;
1416+
1417+ int register_event_handler(std::function<void(MirEvent const&)> const&);
1418+ void unregister_event_handler(int id);
1419+
1420+ void handle_event(MirEvent const& event);
1421+
1422+private:
1423+ int next_id();
1424+
1425+ mutable std::mutex mutex;
1426+ std::map<int, std::function<void(MirEvent const&)>> event_handlers;
1427+ int next_fn_id;
1428+};
1429+}
1430+}
1431+
1432+#endif /* MIR_CLIENT_EVENT_DISTRIBUTOR_H */
1433
1434=== modified file 'src/client/mir_connection.cpp'
1435--- src/client/mir_connection.cpp 2014-05-07 13:51:38 +0000
1436+++ src/client/mir_connection.cpp 2014-05-15 13:19:23 +0000
1437@@ -18,6 +18,7 @@
1438
1439 #include "mir_connection.h"
1440 #include "mir_surface.h"
1441+#include "mir_trust_session.h"
1442 #include "client_platform.h"
1443 #include "client_platform_factory.h"
1444 #include "rpc/mir_basic_rpc_channel.h"
1445@@ -82,7 +83,8 @@
1446 input_platform(conf.the_input_platform()),
1447 display_configuration(conf.the_display_configuration()),
1448 lifecycle_control(conf.the_lifecycle_control()),
1449- surface_map(conf.the_surface_map())
1450+ surface_map(conf.the_surface_map()),
1451+ event_distributor(conf.the_event_distributor())
1452 {
1453 connect_result.set_error("connect not called");
1454 {
1455@@ -193,6 +195,11 @@
1456 return new_wait_handle;
1457 }
1458
1459+MirTrustSession* MirConnection::create_trust_session()
1460+{
1461+ return new MirTrustSession(display_server(), event_distributor);
1462+}
1463+
1464 namespace
1465 {
1466 void default_lifecycle_event_handler(MirLifecycleState transition)
1467@@ -522,6 +529,6 @@
1468 }
1469
1470 mir::protobuf::DisplayServer& MirConnection::display_server()
1471-{
1472+{
1473 return server;
1474 }
1475
1476=== modified file 'src/client/mir_connection.h'
1477--- src/client/mir_connection.h 2014-05-07 13:51:38 +0000
1478+++ src/client/mir_connection.h 2014-05-15 13:19:23 +0000
1479@@ -45,6 +45,7 @@
1480 class ConnectionSurfaceMap;
1481 class DisplayConfiguration;
1482 class LifecycleControl;
1483+class EventDistributor;
1484
1485 namespace rpc
1486 {
1487@@ -86,6 +87,8 @@
1488 mir_surface_callback callback,
1489 void *context);
1490
1491+ MirTrustSession* create_trust_session();
1492+
1493 char const * get_error_message();
1494
1495 MirWaitHandle* connect(
1496@@ -172,6 +175,8 @@
1497
1498 std::shared_ptr<mir::client::ConnectionSurfaceMap> const surface_map;
1499
1500+ std::shared_ptr<mir::client::EventDistributor> const event_distributor;
1501+
1502 std::vector<int> extra_platform_data;
1503
1504 struct SurfaceRelease;
1505
1506=== added file 'src/client/mir_trust_session.cpp'
1507--- src/client/mir_trust_session.cpp 1970-01-01 00:00:00 +0000
1508+++ src/client/mir_trust_session.cpp 2014-05-15 13:19:23 +0000
1509@@ -0,0 +1,182 @@
1510+/*
1511+ * Copyright © 2014 Canonical Ltd.
1512+ *
1513+ * This program is free software: you can redistribute it and/or modify it
1514+ * under the terms of the GNU Lesser General Public License version 3,
1515+ * as published by the Free Software Foundation.
1516+ *
1517+ * This program is distributed in the hope that it will be useful,
1518+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1519+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1520+ * GNU Lesser General Public License for more details.
1521+ *
1522+ * You should have received a copy of the GNU Lesser General Public License
1523+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1524+ *
1525+ * Authored by: Nick Dedekind <nick.dedekind@gmail.com>
1526+ */
1527+
1528+#include "mir_trust_session.h"
1529+#include "event_distributor.h"
1530+
1531+namespace mp = mir::protobuf;
1532+namespace mcl = mir::client;
1533+
1534+MirTrustSession::MirTrustSession(
1535+ mp::DisplayServer& server,
1536+ std::shared_ptr<mcl::EventDistributor> const& event_distributor)
1537+ : server(server),
1538+ event_distributor(event_distributor),
1539+ state(mir_trust_session_state_stopped)
1540+{
1541+ event_distributor_fn_id = event_distributor->register_event_handler(
1542+ [this](MirEvent const& event)
1543+ {
1544+ if (event.type != mir_event_type_trust_session_state_change)
1545+ return;
1546+
1547+ std::lock_guard<decltype(mutex_event_handler)> lock(mutex_event_handler);
1548+
1549+ set_state(event.trust_session.new_state);
1550+ if (handle_trust_session_event) {
1551+ handle_trust_session_event(event.trust_session.new_state);
1552+ }
1553+ }
1554+ );
1555+}
1556+
1557+MirTrustSession::~MirTrustSession()
1558+{
1559+ event_distributor->unregister_event_handler(event_distributor_fn_id);
1560+}
1561+
1562+MirTrustSessionState MirTrustSession::get_state() const
1563+{
1564+ std::lock_guard<decltype(mutex)> lock(mutex);
1565+
1566+ return state;
1567+}
1568+
1569+void MirTrustSession::set_state(MirTrustSessionState new_state)
1570+{
1571+ std::lock_guard<decltype(mutex)> lock(mutex);
1572+
1573+ state = new_state;
1574+}
1575+
1576+MirWaitHandle* MirTrustSession::start(pid_t pid, mir_trust_session_callback callback, void* context)
1577+{
1578+ mir::protobuf::TrustSessionParameters parameters;
1579+ parameters.mutable_base_trusted_session()->set_pid(pid);
1580+
1581+ server.start_trust_session(
1582+ 0,
1583+ &parameters,
1584+ &session,
1585+ google::protobuf::NewCallback(this, &MirTrustSession::done_start,
1586+ callback, context));
1587+
1588+ return &start_wait_handle;
1589+}
1590+
1591+MirWaitHandle* MirTrustSession::stop(mir_trust_session_callback callback, void* context)
1592+{
1593+ server.stop_trust_session(
1594+ 0,
1595+ &protobuf_void,
1596+ &protobuf_void,
1597+ google::protobuf::NewCallback(this, &MirTrustSession::done_stop,
1598+ callback, context));
1599+
1600+ return &stop_wait_handle;
1601+}
1602+
1603+MirWaitHandle* MirTrustSession::add_trusted_session(pid_t pid,
1604+ mir_trust_session_add_trusted_session_callback callback,
1605+ void* context)
1606+{
1607+ mir::protobuf::TrustedSession trusted_session;
1608+ trusted_session.set_pid(pid);
1609+
1610+ server.add_trusted_session(
1611+ 0,
1612+ &trusted_session,
1613+ &add_result,
1614+ google::protobuf::NewCallback(this, &MirTrustSession::done_add_trusted_session,
1615+ callback, context));
1616+
1617+ return &add_result_wait_handle;
1618+}
1619+
1620+void MirTrustSession::register_trust_session_event_callback(
1621+ mir_trust_session_event_callback callback,
1622+ void* context)
1623+{
1624+ std::lock_guard<decltype(mutex_event_handler)> lock(mutex_event_handler);
1625+
1626+ handle_trust_session_event =
1627+ [this, callback, context](MirTrustSessionState new_state)
1628+ {
1629+ callback(this, new_state, context);
1630+ };
1631+}
1632+
1633+void MirTrustSession::done_start(mir_trust_session_callback callback, void* context)
1634+{
1635+ std::string error;
1636+ MirTrustSessionState new_state = mir_trust_session_state_stopped;
1637+ {
1638+ std::lock_guard<decltype(mutex)> lock(mutex);
1639+
1640+ if (session.has_state())
1641+ new_state = (MirTrustSessionState)session.state();
1642+
1643+ error = session.error();
1644+ }
1645+ set_error_message(error);
1646+ set_state(new_state);
1647+
1648+ callback(this, context);
1649+ start_wait_handle.result_received();
1650+}
1651+
1652+void MirTrustSession::done_stop(mir_trust_session_callback callback, void* context)
1653+{
1654+ set_state(mir_trust_session_state_stopped);
1655+
1656+ callback(this, context);
1657+ stop_wait_handle.result_received();
1658+}
1659+
1660+void MirTrustSession::done_add_trusted_session(mir_trust_session_add_trusted_session_callback callback, void* context)
1661+{
1662+ MirTrustSessionAddTrustResult result = static_cast<MirTrustSessionAddTrustResult>(add_result.result());
1663+ if (add_result.has_error())
1664+ {
1665+ set_error_message(add_result.error());
1666+ result = mir_trust_session_add_tust_failed;
1667+ }
1668+ callback(this, result, context);
1669+ add_result_wait_handle.result_received();
1670+}
1671+
1672+char const* MirTrustSession::get_error_message()
1673+{
1674+ std::lock_guard<decltype(mutex)> lock(mutex);
1675+
1676+ if (session.has_error())
1677+ {
1678+ return session.error().c_str();
1679+ }
1680+ else
1681+ {
1682+ return error_message.c_str();
1683+ }
1684+}
1685+
1686+void MirTrustSession::set_error_message(std::string const& error)
1687+{
1688+ std::lock_guard<decltype(mutex)> lock(mutex);
1689+
1690+ error_message = error;
1691+}
1692
1693=== added file 'src/client/mir_trust_session.h'
1694--- src/client/mir_trust_session.h 1970-01-01 00:00:00 +0000
1695+++ src/client/mir_trust_session.h 2014-05-15 13:19:23 +0000
1696@@ -0,0 +1,88 @@
1697+/*
1698+ * Copyright © 2014 Canonical Ltd.
1699+ *
1700+ * This program is free software: you can redistribute it and/or modify it
1701+ * under the terms of the GNU Lesser General Public License version 3,
1702+ * as published by the Free Software Foundation.
1703+ *
1704+ * This program is distributed in the hope that it will be useful,
1705+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1706+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1707+ * GNU Lesser General Public License for more details.
1708+ *
1709+ * You should have received a copy of the GNU Lesser General Public License
1710+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1711+ *
1712+ * Authored by: Nick Dedekind <nick.dedekind@gmail.com>
1713+ */
1714+
1715+#ifndef MIR_CLIENT_MIR_TRUST_SESSION_H_
1716+#define MIR_CLIENT_MIR_TRUST_SESSION_H_
1717+
1718+#include "mir_toolkit/mir_client_library.h"
1719+
1720+#include "mir_protobuf.pb.h"
1721+#include "mir_wait_handle.h"
1722+
1723+#include <mutex>
1724+#include <memory>
1725+#include <atomic>
1726+
1727+namespace mir
1728+{
1729+/// The client-side library implementation namespace
1730+namespace client
1731+{
1732+class EventDistributor;
1733+}
1734+}
1735+
1736+struct MirTrustSession
1737+{
1738+public:
1739+ MirTrustSession(mir::protobuf::DisplayServer& server,
1740+ std::shared_ptr<mir::client::EventDistributor> const& event_distributor);
1741+
1742+ ~MirTrustSession();
1743+
1744+ MirTrustSession(MirTrustSession const&) = delete;
1745+ MirTrustSession& operator=(MirTrustSession const&) = delete;
1746+
1747+ MirWaitHandle* start(pid_t pid, mir_trust_session_callback callback, void* context);
1748+ MirWaitHandle* stop(mir_trust_session_callback callback, void* context);
1749+ MirWaitHandle* add_trusted_session(pid_t pid, mir_trust_session_add_trusted_session_callback callback, void* context);
1750+
1751+ void register_trust_session_event_callback(mir_trust_session_event_callback callback, void* context);
1752+
1753+ char const* get_error_message();
1754+ void set_error_message(std::string const& error);
1755+
1756+ MirTrustSessionState get_state() const;
1757+ void set_state(MirTrustSessionState new_state);
1758+
1759+private:
1760+ mutable std::mutex mutex; // Protects members of *this
1761+ mutable std::mutex mutex_event_handler; // Need another mutex for callback access to members
1762+
1763+ mir::protobuf::DisplayServer& server;
1764+ mir::protobuf::TrustSession session;
1765+ mir::protobuf::TrustSessionAddResult add_result;
1766+ mir::protobuf::Void protobuf_void;
1767+ std::string error_message;
1768+
1769+ std::shared_ptr<mir::client::EventDistributor> const event_distributor;
1770+ std::function<void(MirTrustSessionState)> handle_trust_session_event;
1771+ int event_distributor_fn_id;
1772+
1773+ MirWaitHandle start_wait_handle;
1774+ MirWaitHandle stop_wait_handle;
1775+ MirWaitHandle add_result_wait_handle;
1776+ MirTrustSessionState state;
1777+
1778+ void done_start(mir_trust_session_callback callback, void* context);
1779+ void done_stop(mir_trust_session_callback callback, void* context);
1780+ void done_add_trusted_session(mir_trust_session_add_trusted_session_callback callback, void* context);
1781+};
1782+
1783+#endif /* MIR_CLIENT_MIR_TRUST_SESSION_H_ */
1784+
1785
1786=== added file 'src/client/mir_trust_session_api.cpp'
1787--- src/client/mir_trust_session_api.cpp 1970-01-01 00:00:00 +0000
1788+++ src/client/mir_trust_session_api.cpp 2014-05-15 13:19:23 +0000
1789@@ -0,0 +1,133 @@
1790+/*
1791+ * Copyright © 2014 Canonical Ltd.
1792+ *
1793+ * This program is free software: you can redistribute it and/or modify it
1794+ * under the terms of the GNU Lesser General Public License version 3,
1795+ * as published by the Free Software Foundation.
1796+ *
1797+ * This program is distributed in the hope that it will be useful,
1798+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1799+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1800+ * GNU Lesser General Public License for more details.
1801+ *
1802+ * You should have received a copy of the GNU Lesser General Public License
1803+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1804+ */
1805+
1806+#include "mir_toolkit/mir_trust_session.h"
1807+#include "mir_trust_session.h"
1808+#include "mir_connection.h"
1809+
1810+#include <stdexcept>
1811+#include <boost/throw_exception.hpp>
1812+
1813+namespace
1814+{
1815+
1816+// assign_result is compatible with all 2-parameter callbacks
1817+void assign_result(void *result, void **context)
1818+{
1819+ if (context)
1820+ *context = result;
1821+}
1822+
1823+void add_trusted_session_callback(MirTrustSession*,
1824+ MirTrustSessionAddTrustResult result,
1825+ void* context)
1826+{
1827+ if (context)
1828+ *(MirTrustSessionAddTrustResult*)context = result;
1829+}
1830+
1831+}
1832+
1833+MirWaitHandle *mir_connection_start_trust_session(MirConnection* connection,
1834+ pid_t base_session_pid,
1835+ mir_trust_session_callback start_callback,
1836+ mir_trust_session_event_callback event_callback,
1837+ void* context)
1838+{
1839+ auto trust_session = connection->create_trust_session();
1840+ if (event_callback)
1841+ trust_session->register_trust_session_event_callback(event_callback, context);
1842+ return trust_session->start(base_session_pid, start_callback, context);
1843+}
1844+
1845+MirTrustSession *mir_connection_start_trust_session_sync(MirConnection* connection,
1846+ pid_t base_session_pid,
1847+ mir_trust_session_event_callback event_callback,
1848+ void* context)
1849+{
1850+ auto trust_session = connection->create_trust_session();
1851+ if (event_callback)
1852+ trust_session->register_trust_session_event_callback(event_callback, context);
1853+
1854+ mir_wait_for(trust_session->start(base_session_pid,
1855+ reinterpret_cast<mir_trust_session_callback>(assign_result),
1856+ nullptr));
1857+ return trust_session;
1858+}
1859+
1860+MirTrustSession* mir_connection_create_trust_session(MirConnection* connection)
1861+{
1862+ return connection->create_trust_session();
1863+}
1864+
1865+MirWaitHandle *mir_trust_session_add_trusted_session(MirTrustSession *trust_session,
1866+ pid_t session_pid,
1867+ mir_trust_session_add_trusted_session_callback callback,
1868+ void* context)
1869+{
1870+ try
1871+ {
1872+ return trust_session->add_trusted_session(session_pid, callback, context);
1873+ }
1874+ catch (std::exception const&)
1875+ {
1876+ // TODO callback with an error
1877+ return nullptr;
1878+ }
1879+}
1880+
1881+MirTrustSessionAddTrustResult mir_trust_session_add_trusted_session_sync(MirTrustSession *trust_session, pid_t base_session_pid)
1882+{
1883+ MirTrustSessionAddTrustResult result;
1884+ mir_wait_for(mir_trust_session_add_trusted_session(trust_session,
1885+ base_session_pid,
1886+ add_trusted_session_callback,
1887+ &result));
1888+ return result;
1889+}
1890+
1891+MirWaitHandle *mir_trust_session_stop(MirTrustSession *trust_session,
1892+ mir_trust_session_callback callback,
1893+ void* context)
1894+{
1895+ try
1896+ {
1897+ return trust_session->stop(callback, context);
1898+ }
1899+ catch (std::exception const&)
1900+ {
1901+ // TODO callback with an error
1902+ return nullptr;
1903+ }
1904+}
1905+
1906+MirBool mir_trust_session_stop_sync(MirTrustSession *trust_session)
1907+{
1908+ mir_wait_for(mir_trust_session_stop(trust_session,
1909+ reinterpret_cast<mir_trust_session_callback>(assign_result),
1910+ NULL));
1911+ return trust_session->get_state() == mir_trust_session_state_stopped ? mir_true : mir_false;
1912+}
1913+
1914+MirTrustSessionState mir_trust_session_get_state(MirTrustSession *trust_session)
1915+{
1916+ return trust_session->get_state();
1917+}
1918+
1919+void mir_trust_session_release(MirTrustSession* trust_session)
1920+{
1921+ delete trust_session;
1922+}
1923
1924=== modified file 'src/client/rpc/make_rpc_channel.h'
1925--- src/client/rpc/make_rpc_channel.h 2014-03-06 06:05:17 +0000
1926+++ src/client/rpc/make_rpc_channel.h 2014-05-15 13:19:23 +0000
1927@@ -29,6 +29,7 @@
1928 class SurfaceMap;
1929 class DisplayConfiguration;
1930 class LifecycleControl;
1931+class EventDistributor;
1932
1933 namespace rpc
1934 {
1935@@ -39,7 +40,8 @@
1936 std::shared_ptr<SurfaceMap> const& map,
1937 std::shared_ptr<DisplayConfiguration> const& disp_conf,
1938 std::shared_ptr<RpcReport> const& rpc_report,
1939- std::shared_ptr<LifecycleControl> const& lifecycle_control);
1940+ std::shared_ptr<LifecycleControl> const& lifecycle_control,
1941+ std::shared_ptr<EventDistributor> const& event_distributor);
1942 }
1943 }
1944 }
1945
1946=== modified file 'src/client/rpc/make_socket_rpc_channel.cpp'
1947--- src/client/rpc/make_socket_rpc_channel.cpp 2014-03-06 06:05:17 +0000
1948+++ src/client/rpc/make_socket_rpc_channel.cpp 2014-05-15 13:19:23 +0000
1949@@ -44,13 +44,14 @@
1950 std::shared_ptr<mcl::SurfaceMap> const& map,
1951 std::shared_ptr<mcl::DisplayConfiguration> const& disp_conf,
1952 std::shared_ptr<RpcReport> const& rpc_report,
1953- std::shared_ptr<mcl::LifecycleControl> const& lifecycle_control)
1954+ std::shared_ptr<mcl::LifecycleControl> const& lifecycle_control,
1955+ std::shared_ptr<mcl::EventDistributor> const& event_distributor)
1956 {
1957 if (fd_prefix.is_start_of(name))
1958 {
1959 auto const fd = atoi(name.c_str()+fd_prefix.size);
1960- return std::make_shared<MirSocketRpcChannel>(fd, map, disp_conf, rpc_report, lifecycle_control);
1961+ return std::make_shared<MirSocketRpcChannel>(fd, map, disp_conf, rpc_report, lifecycle_control, event_distributor);
1962 }
1963
1964- return std::make_shared<MirSocketRpcChannel>(name, map, disp_conf, rpc_report, lifecycle_control);
1965+ return std::make_shared<MirSocketRpcChannel>(name, map, disp_conf, rpc_report, lifecycle_control, event_distributor);
1966 }
1967
1968=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
1969--- src/client/rpc/mir_socket_rpc_channel.cpp 2014-05-06 14:53:36 +0000
1970+++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-05-15 13:19:23 +0000
1971@@ -24,6 +24,7 @@
1972 #include "../mir_surface.h"
1973 #include "../display_configuration.h"
1974 #include "../lifecycle_control.h"
1975+#include "../event_distributor.h"
1976
1977 #include "mir_protobuf.pb.h" // For Buffer frig
1978 #include "mir_protobuf_wire.pb.h"
1979@@ -49,7 +50,8 @@
1980 std::shared_ptr<mcl::SurfaceMap> const& surface_map,
1981 std::shared_ptr<DisplayConfiguration> const& disp_config,
1982 std::shared_ptr<RpcReport> const& rpc_report,
1983- std::shared_ptr<LifecycleControl> const& lifecycle_control) :
1984+ std::shared_ptr<LifecycleControl> const& lifecycle_control,
1985+ std::shared_ptr<EventDistributor> const& event_distributor) :
1986 rpc_report(rpc_report),
1987 pending_calls(rpc_report),
1988 work(io_service),
1989@@ -57,6 +59,7 @@
1990 surface_map(surface_map),
1991 display_configuration(disp_config),
1992 lifecycle_control(lifecycle_control),
1993+ event_distributor(event_distributor),
1994 disconnected(false)
1995 {
1996 socket.connect(endpoint);
1997@@ -68,7 +71,8 @@
1998 std::shared_ptr<mcl::SurfaceMap> const& surface_map,
1999 std::shared_ptr<DisplayConfiguration> const& disp_config,
2000 std::shared_ptr<RpcReport> const& rpc_report,
2001- std::shared_ptr<LifecycleControl> const& lifecycle_control) :
2002+ std::shared_ptr<LifecycleControl> const& lifecycle_control,
2003+ std::shared_ptr<EventDistributor> const& event_distributor) :
2004 rpc_report(rpc_report),
2005 pending_calls(rpc_report),
2006 work(io_service),
2007@@ -76,6 +80,7 @@
2008 surface_map(surface_map),
2009 display_configuration(disp_config),
2010 lifecycle_control(lifecycle_control),
2011+ event_distributor(event_distributor),
2012 disconnected(false)
2013 {
2014 socket.assign(boost::asio::local::stream_protocol(), native_socket);
2015@@ -405,11 +410,25 @@
2016
2017 rpc_report->event_parsing_succeeded(e);
2018
2019- surface_map->with_surface_do(e.surface.id,
2020- [&e](MirSurface* surface)
2021- {
2022- surface->handle_event(e);
2023- });
2024+ event_distributor->handle_event(e);
2025+
2026+ // todo - surfaces should register with the event distributor.
2027+ if (e.type == mir_event_type_surface)
2028+ {
2029+ surface_map->with_surface_do(e.surface.id,
2030+ [&e](MirSurface* surface)
2031+ {
2032+ surface->handle_event(e);
2033+ });
2034+ }
2035+ else if (e.type == mir_event_type_resize)
2036+ {
2037+ surface_map->with_surface_do(e.resize.surface_id,
2038+ [&e](MirSurface* surface)
2039+ {
2040+ surface->handle_event(e);
2041+ });
2042+ }
2043 }
2044 else
2045 {
2046
2047=== modified file 'src/client/rpc/mir_socket_rpc_channel.h'
2048--- src/client/rpc/mir_socket_rpc_channel.h 2014-05-05 03:36:45 +0000
2049+++ src/client/rpc/mir_socket_rpc_channel.h 2014-05-15 13:19:23 +0000
2050@@ -44,6 +44,7 @@
2051 class DisplayConfiguration;
2052 class SurfaceMap;
2053 class LifecycleControl;
2054+class EventDistributor;
2055 namespace rpc
2056 {
2057
2058@@ -56,13 +57,15 @@
2059 std::shared_ptr<SurfaceMap> const& surface_map,
2060 std::shared_ptr<DisplayConfiguration> const& disp_config,
2061 std::shared_ptr<RpcReport> const& rpc_report,
2062- std::shared_ptr<LifecycleControl> const& lifecycle_control);
2063+ std::shared_ptr<LifecycleControl> const& lifecycle_control,
2064+ std::shared_ptr<EventDistributor> const& event_distributor);
2065
2066 MirSocketRpcChannel(int native_socket,
2067 std::shared_ptr<SurfaceMap> const& surface_map,
2068 std::shared_ptr<DisplayConfiguration> const& disp_config,
2069 std::shared_ptr<RpcReport> const& rpc_report,
2070- std::shared_ptr<LifecycleControl> const& lifecycle_control);
2071+ std::shared_ptr<LifecycleControl> const& lifecycle_control,
2072+ std::shared_ptr<EventDistributor> const& event_distributor);
2073 ~MirSocketRpcChannel();
2074
2075 private:
2076@@ -102,6 +105,7 @@
2077 std::shared_ptr<SurfaceMap> surface_map;
2078 std::shared_ptr<DisplayConfiguration> display_configuration;
2079 std::shared_ptr<LifecycleControl> lifecycle_control;
2080+ std::shared_ptr<EventDistributor> event_distributor;
2081 std::atomic<bool> disconnected;
2082 };
2083
2084
2085=== modified file 'src/server/default_server_configuration.cpp'
2086--- src/server/default_server_configuration.cpp 2014-05-12 15:46:07 +0000
2087+++ src/server/default_server_configuration.cpp 2014-05-15 13:19:23 +0000
2088@@ -36,6 +36,7 @@
2089 #include "mir/time/high_resolution_clock.h"
2090 #include "mir/geometry/rectangles.h"
2091 #include "mir/default_configuration.h"
2092+#include "mir/scene/null_trust_session_listener.h"
2093
2094 #include <map>
2095
2096@@ -87,6 +88,16 @@
2097 });
2098 }
2099
2100+std::shared_ptr<ms::TrustSessionListener>
2101+mir::DefaultServerConfiguration::the_trust_session_listener()
2102+{
2103+ return trust_session_listener(
2104+ [this]
2105+ {
2106+ return std::make_shared<ms::NullTrustSessionListener>();
2107+ });
2108+}
2109+
2110 std::shared_ptr<mi::CursorListener>
2111 mir::DefaultServerConfiguration::the_cursor_listener()
2112 {
2113
2114=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
2115--- src/server/frontend/protobuf_message_processor.cpp 2014-05-13 11:59:40 +0000
2116+++ src/server/frontend/protobuf_message_processor.cpp 2014-05-15 13:19:23 +0000
2117@@ -187,6 +187,18 @@
2118 {
2119 invoke(this, display_server.get(), &protobuf::DisplayServer::new_fds_for_trusted_clients, invocation);
2120 }
2121+ else if ("start_trust_session" == invocation.method_name())
2122+ {
2123+ invoke(this, display_server.get(), &protobuf::DisplayServer::start_trust_session, invocation);
2124+ }
2125+ else if ("add_trusted_session" == invocation.method_name())
2126+ {
2127+ invoke(this, display_server.get(), &protobuf::DisplayServer::add_trusted_session, invocation);
2128+ }
2129+ else if ("stop_trust_session" == invocation.method_name())
2130+ {
2131+ invoke(this, display_server.get(), &protobuf::DisplayServer::stop_trust_session, invocation);
2132+ }
2133 else if ("disconnect" == invocation.method_name())
2134 {
2135 invoke(this, display_server.get(), &DisplayServer::disconnect, invocation);
2136
2137=== modified file 'src/server/frontend/session_mediator.cpp'
2138--- src/server/frontend/session_mediator.cpp 2014-05-13 11:59:40 +0000
2139+++ src/server/frontend/session_mediator.cpp 2014-05-15 13:19:23 +0000
2140@@ -40,6 +40,8 @@
2141 #include "mir/frontend/client_constants.h"
2142 #include "mir/frontend/event_sink.h"
2143 #include "mir/frontend/screencast.h"
2144+#include "mir/frontend/trust_session.h"
2145+#include "mir/scene/trust_session_creation_parameters.h"
2146
2147 #include "mir/geometry/rectangles.h"
2148 #include "client_buffer_tracker.h"
2149@@ -422,7 +424,14 @@
2150
2151 std::function<void(std::shared_ptr<mf::Session> const&)> mf::SessionMediator::trusted_connect_handler() const
2152 {
2153- return [](std::shared_ptr<frontend::Session> const&) {};
2154+ return [this](std::shared_ptr<frontend::Session> const& session)
2155+ {
2156+ auto trust_session = weak_trust_session.lock();
2157+ if (trust_session.get() == nullptr)
2158+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid trust session"));
2159+
2160+ shell->add_trusted_session_for(trust_session, session->process_id());
2161+ };
2162 }
2163
2164 void mf::SessionMediator::configure_cursor(
2165@@ -448,7 +457,6 @@
2166 if (session.get() == nullptr)
2167 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2168
2169- // TODO write a handler that connects the new session to our trust session
2170 auto const connect_handler = trusted_connect_handler();
2171
2172 auto const fds_requested = parameters->number();
2173@@ -506,6 +514,91 @@
2174 done->Run();
2175 }
2176
2177+void mf::SessionMediator::start_trust_session(::google::protobuf::RpcController*,
2178+ const ::mir::protobuf::TrustSessionParameters* request,
2179+ ::mir::protobuf::TrustSession* response,
2180+ ::google::protobuf::Closure* done)
2181+{
2182+ {
2183+ std::unique_lock<std::mutex> lock(session_mutex);
2184+ auto session = weak_session.lock();
2185+
2186+ if (session.get() == nullptr)
2187+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2188+
2189+ ms::TrustSessionCreationParameters parameters;
2190+ parameters.set_base_process_id(request->base_trusted_session().pid());
2191+
2192+ std::ostringstream stream;
2193+ stream << "process id: " << parameters.base_process_id;
2194+ report->session_start_trust_session_called(session->name(), stream.str());
2195+
2196+ auto current_trust_session = weak_trust_session.lock();
2197+ if (current_trust_session.get() != nullptr)
2198+ BOOST_THROW_EXCEPTION(std::runtime_error("Cannot start another trust session"));
2199+
2200+ auto trust_session = shell->start_trust_session_for(session, parameters);
2201+ weak_trust_session = trust_session;
2202+
2203+ if (trust_session)
2204+ {
2205+ response->set_state(trust_session->get_state());
2206+ }
2207+ }
2208+ done->Run();
2209+}
2210+
2211+void mf::SessionMediator::add_trusted_session(::google::protobuf::RpcController*,
2212+ const ::mir::protobuf::TrustedSession* request,
2213+ ::mir::protobuf::TrustSessionAddResult* response,
2214+ ::google::protobuf::Closure* done)
2215+{
2216+ {
2217+ std::unique_lock<std::mutex> lock(session_mutex);
2218+ auto session = weak_session.lock();
2219+
2220+ if (session.get() == nullptr)
2221+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2222+
2223+ auto trust_session = weak_trust_session.lock();
2224+
2225+ if (trust_session.get() == nullptr)
2226+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid trust session"));
2227+
2228+ std::ostringstream stream;
2229+ stream << "process id: " << request->pid();
2230+ report->session_add_trusted_session_called(session->name(), stream.str());
2231+
2232+ response->set_result(shell->add_trusted_session_for(trust_session, request->pid()));
2233+ }
2234+ done->Run();
2235+}
2236+
2237+void mf::SessionMediator::stop_trust_session(::google::protobuf::RpcController*,
2238+ const ::mir::protobuf::Void*,
2239+ ::mir::protobuf::Void*,
2240+ ::google::protobuf::Closure* done)
2241+{
2242+ {
2243+ std::unique_lock<std::mutex> lock(session_mutex);
2244+ auto session = weak_session.lock();
2245+
2246+ if (session.get() == nullptr)
2247+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2248+
2249+ auto trust_session = weak_trust_session.lock();
2250+ weak_trust_session.reset();
2251+
2252+ if (trust_session.get() == nullptr)
2253+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid trusted session"));
2254+
2255+ report->session_stop_trust_session_called(session->name());
2256+
2257+ shell->stop_trust_session(trust_session);
2258+ }
2259+ done->Run();
2260+}
2261+
2262 void mf::SessionMediator::pack_protobuf_buffer(
2263 protobuf::Buffer& protobuf_buffer,
2264 graphics::Buffer* graphics_buffer,
2265
2266=== modified file 'src/server/frontend/session_mediator.h'
2267--- src/server/frontend/session_mediator.h 2014-05-13 11:59:40 +0000
2268+++ src/server/frontend/session_mediator.h 2014-05-15 13:19:23 +0000
2269@@ -53,6 +53,7 @@
2270 class EventSink;
2271 class DisplayChanger;
2272 class Screencast;
2273+class TrustSession;
2274
2275 // SessionMediator relays requests from the client process into the server.
2276 class SessionMediator : public detail::DisplayServer
2277@@ -131,6 +132,21 @@
2278 mir::protobuf::Void*,
2279 google::protobuf::Closure* done);
2280
2281+ void start_trust_session(::google::protobuf::RpcController* controller,
2282+ const ::mir::protobuf::TrustSessionParameters* request,
2283+ ::mir::protobuf::TrustSession* response,
2284+ ::google::protobuf::Closure* done);
2285+
2286+ void add_trusted_session(::google::protobuf::RpcController* controller,
2287+ const ::mir::protobuf::TrustedSession* request,
2288+ ::mir::protobuf::TrustSessionAddResult* response,
2289+ ::google::protobuf::Closure* done);
2290+
2291+ void stop_trust_session(::google::protobuf::RpcController* controller,
2292+ const ::mir::protobuf::Void* request,
2293+ ::mir::protobuf::Void* response,
2294+ ::google::protobuf::Closure* done);
2295+
2296 /* Platform specific requests */
2297 void drm_auth_magic(google::protobuf::RpcController* controller,
2298 const mir::protobuf::DRMMagic* request,
2299@@ -169,6 +185,7 @@
2300
2301 std::mutex session_mutex;
2302 std::weak_ptr<Session> weak_session;
2303+ std::weak_ptr<TrustSession> weak_trust_session;
2304
2305 ConnectionContext const connection_context;
2306 };
2307
2308=== modified file 'src/server/report/logging/session_mediator_report.cpp'
2309--- src/server/report/logging/session_mediator_report.cpp 2014-03-06 06:05:17 +0000
2310+++ src/server/report/logging/session_mediator_report.cpp 2014-05-15 13:19:23 +0000
2311@@ -73,6 +73,21 @@
2312 log->log(ml::Logger::informational, "session_configure_display_called(\"" + app_name + "\")", component);
2313 }
2314
2315+void mrl::SessionMediatorReport::session_start_trust_session_called(std::string const& app_name, std::string const& trust_info)
2316+{
2317+ log->log(ml::Logger::informational, "session_start_trust_session_called(\"" + app_name + "\"):\n" + trust_info, component);
2318+}
2319+
2320+void mrl::SessionMediatorReport::session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info)
2321+{
2322+ log->log(ml::Logger::informational, "session_add_trusted_session_called(\"" + app_name + "\"):\n" + trust_info, component);
2323+}
2324+
2325+void mrl::SessionMediatorReport::session_stop_trust_session_called(std::string const& app_name)
2326+{
2327+ log->log(ml::Logger::informational, "session_stop_trust_session_called(\"" + app_name + "\")", component);
2328+}
2329+
2330 void mrl::SessionMediatorReport::session_error(
2331 std::string const& app_name,
2332 char const* method,
2333
2334=== modified file 'src/server/report/logging/session_mediator_report.h'
2335--- src/server/report/logging/session_mediator_report.h 2014-03-06 06:05:17 +0000
2336+++ src/server/report/logging/session_mediator_report.h 2014-05-15 13:19:23 +0000
2337@@ -57,6 +57,12 @@
2338
2339 virtual void session_configure_display_called(std::string const& app_name);
2340
2341+ virtual void session_start_trust_session_called(std::string const& app_name, std::string const& trust_info);
2342+
2343+ virtual void session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info);
2344+
2345+ virtual void session_stop_trust_session_called(std::string const& app_name);
2346+
2347 virtual void session_error(
2348 std::string const& app_name,
2349 char const* method,
2350
2351=== modified file 'src/server/report/lttng/session_mediator_report.cpp'
2352--- src/server/report/lttng/session_mediator_report.cpp 2014-02-09 16:18:16 +0000
2353+++ src/server/report/lttng/session_mediator_report.cpp 2014-05-15 13:19:23 +0000
2354@@ -38,6 +38,17 @@
2355 MIR_SESSION_MEDIATOR_EVENT_METHOD(session_drm_auth_magic_called)
2356 MIR_SESSION_MEDIATOR_EVENT_METHOD(session_configure_surface_called)
2357 MIR_SESSION_MEDIATOR_EVENT_METHOD(session_configure_display_called)
2358+MIR_SESSION_MEDIATOR_EVENT_METHOD(session_stop_trust_session_called)
2359+
2360+void mir::report::lttng::SessionMediatorReport::session_start_trust_session_called(std::string const& app_name, std::string const& trust_info)
2361+{
2362+ mir_tracepoint(mir_server_session_mediator, session_start_trust_session_called, app_name.c_str(), trust_info.c_str());
2363+}
2364+
2365+void mir::report::lttng::SessionMediatorReport::session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info)
2366+{
2367+ mir_tracepoint(mir_server_session_mediator, session_add_trusted_session_called, app_name.c_str(), trust_info.c_str());
2368+}
2369
2370 void mir::report::lttng::SessionMediatorReport::session_error(std::string const& app_name, char const* method, std::string const& what)
2371 {
2372
2373=== modified file 'src/server/report/lttng/session_mediator_report.h'
2374--- src/server/report/lttng/session_mediator_report.h 2014-02-09 16:18:16 +0000
2375+++ src/server/report/lttng/session_mediator_report.h 2014-05-15 13:19:23 +0000
2376@@ -41,6 +41,9 @@
2377 void session_drm_auth_magic_called(std::string const& app_name) override;
2378 void session_configure_surface_called(std::string const& app_name) override;
2379 void session_configure_display_called(std::string const& app_name) override;
2380+ void session_start_trust_session_called(std::string const& app_name, std::string const& trust_info) override;
2381+ void session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info) override;
2382+ void session_stop_trust_session_called(std::string const& app_name) override;
2383
2384 void session_error(std::string const& app_name, char const* method, std::string const& what) override;
2385 private:
2386
2387=== modified file 'src/server/report/lttng/session_mediator_report_tp.h'
2388--- src/server/report/lttng/session_mediator_report_tp.h 2014-02-03 11:44:32 +0000
2389+++ src/server/report/lttng/session_mediator_report_tp.h 2014-05-15 13:19:23 +0000
2390@@ -47,6 +47,27 @@
2391 MIR_SESSION_MEDIATOR_EVENT(session_drm_auth_magic_called)
2392 MIR_SESSION_MEDIATOR_EVENT(session_configure_surface_called)
2393 MIR_SESSION_MEDIATOR_EVENT(session_configure_display_called)
2394+MIR_SESSION_MEDIATOR_EVENT(session_stop_trust_session_called)
2395+
2396+TRACEPOINT_EVENT(
2397+ mir_server_session_mediator,
2398+ session_start_trust_session_called,
2399+ TP_ARGS(char const*, application, char const*, trust_info),
2400+ TP_FIELDS(
2401+ ctf_string(application, application)
2402+ ctf_string(trust_info, trust_info)
2403+ )
2404+ )
2405+
2406+TRACEPOINT_EVENT(
2407+ mir_server_session_mediator,
2408+ session_add_trusted_session_called,
2409+ TP_ARGS(char const*, application, char const*, trust_info),
2410+ TP_FIELDS(
2411+ ctf_string(application, application)
2412+ ctf_string(trust_info, trust_info)
2413+ )
2414+ )
2415
2416 TRACEPOINT_EVENT(
2417 mir_server_session_mediator,
2418
2419=== modified file 'src/server/report/null/session_mediator_report.cpp'
2420--- src/server/report/null/session_mediator_report.cpp 2014-03-06 06:05:17 +0000
2421+++ src/server/report/null/session_mediator_report.cpp 2014-05-15 13:19:23 +0000
2422@@ -50,6 +50,18 @@
2423 {
2424 }
2425
2426+void mir::report::null::SessionMediatorReport::session_start_trust_session_called(std::string const&, std::string const&)
2427+{
2428+}
2429+
2430+void mir::report::null::SessionMediatorReport::session_add_trusted_session_called(std::string const&, std::string const&)
2431+{
2432+}
2433+
2434+void mir::report::null::SessionMediatorReport::session_stop_trust_session_called(std::string const&)
2435+{
2436+}
2437+
2438 void mir::report::null::SessionMediatorReport::session_error(
2439 std::string const&,
2440 char const* ,
2441
2442=== modified file 'src/server/report/null/session_mediator_report.h'
2443--- src/server/report/null/session_mediator_report.h 2014-02-09 16:18:16 +0000
2444+++ src/server/report/null/session_mediator_report.h 2014-05-15 13:19:23 +0000
2445@@ -51,6 +51,12 @@
2446
2447 void session_configure_display_called(std::string const& app_name) override;
2448
2449+ void session_start_trust_session_called(std::string const& app_name, std::string const& trust_info) override;
2450+
2451+ void session_add_trusted_session_called(std::string const& app_name, std::string const& trust_info) override;
2452+
2453+ void session_stop_trust_session_called(std::string const& app_name) override;
2454+
2455 void session_error(
2456 std::string const& app_name,
2457 char const* method,
2458
2459=== modified file 'src/server/scene/CMakeLists.txt'
2460--- src/server/scene/CMakeLists.txt 2014-05-06 03:33:05 +0000
2461+++ src/server/scene/CMakeLists.txt 2014-05-15 13:19:23 +0000
2462@@ -20,4 +20,7 @@
2463 threaded_snapshot_strategy.cpp
2464 legacy_scene_change_notification.cpp
2465 legacy_surface_change_notification.cpp
2466+ trust_session_impl.cpp
2467+ trust_session_container.cpp
2468+ trust_session_creation_parameters.cpp
2469 )
2470
2471=== modified file 'src/server/scene/application_session.cpp'
2472--- src/server/scene/application_session.cpp 2014-05-06 16:54:43 +0000
2473+++ src/server/scene/application_session.cpp 2014-05-15 13:19:23 +0000
2474@@ -23,6 +23,7 @@
2475 #include "snapshot_strategy.h"
2476 #include "mir/scene/session_listener.h"
2477 #include "mir/frontend/event_sink.h"
2478+#include "default_session_container.h"
2479
2480 #include <boost/throw_exception.hpp>
2481
2482@@ -30,6 +31,7 @@
2483 #include <memory>
2484 #include <cassert>
2485 #include <algorithm>
2486+#include <cstring>
2487
2488 namespace mf = mir::frontend;
2489 namespace ms = mir::scene;
2490@@ -181,3 +183,22 @@
2491 {
2492 event_sink->handle_lifecycle_event(state);
2493 }
2494+
2495+void ms::ApplicationSession::begin_trust_session()
2496+{
2497+ // All sessions which are part of the trust session get this event.
2498+ MirEvent start_event;
2499+ memset(&start_event, 0, sizeof start_event);
2500+ start_event.type = mir_event_type_trust_session_state_change;
2501+ start_event.trust_session.new_state = mir_trust_session_state_started;
2502+ event_sink->handle_event(start_event);
2503+}
2504+
2505+void ms::ApplicationSession::end_trust_session()
2506+{
2507+ MirEvent stop_event;
2508+ memset(&stop_event, 0, sizeof stop_event);
2509+ stop_event.type = mir_event_type_trust_session_state_change;
2510+ stop_event.trust_session.new_state = mir_trust_session_state_stopped;
2511+ event_sink->handle_event(stop_event);
2512+}
2513
2514=== modified file 'src/server/scene/application_session.h'
2515--- src/server/scene/application_session.h 2014-05-06 16:54:43 +0000
2516+++ src/server/scene/application_session.h 2014-05-15 13:19:23 +0000
2517@@ -71,6 +71,9 @@
2518
2519 void set_lifecycle_state(MirLifecycleState state);
2520
2521+ void begin_trust_session() override;
2522+ void end_trust_session() override;
2523+
2524 protected:
2525 ApplicationSession(ApplicationSession const&) = delete;
2526 ApplicationSession& operator=(ApplicationSession const&) = delete;
2527
2528=== modified file 'src/server/scene/default_configuration.cpp'
2529--- src/server/scene/default_configuration.cpp 2014-05-12 15:46:07 +0000
2530+++ src/server/scene/default_configuration.cpp 2014-05-15 13:19:23 +0000
2531@@ -24,12 +24,12 @@
2532 #include "mir/abnormal_exit.h"
2533 #include "mir/scene/session.h"
2534
2535+#include "session_container.h"
2536 #include "broadcasting_session_event_sink.h"
2537 #include "default_session_container.h"
2538 #include "gl_pixel_buffer.h"
2539 #include "global_event_sender.h"
2540 #include "mediating_display_changer.h"
2541-#include "session_container.h"
2542 #include "session_manager.h"
2543 #include "surface_allocator.h"
2544 #include "surface_controller.h"
2545@@ -169,7 +169,8 @@
2546 the_shell_focus_setter(),
2547 the_snapshot_strategy(),
2548 the_session_event_sink(),
2549- the_session_listener());
2550+ the_session_listener(),
2551+ the_trust_session_listener());
2552 });
2553 }
2554
2555
2556=== modified file 'src/server/scene/session_manager.cpp'
2557--- src/server/scene/session_manager.cpp 2014-04-15 05:31:19 +0000
2558+++ src/server/scene/session_manager.cpp 2014-05-15 13:19:23 +0000
2559@@ -24,6 +24,12 @@
2560 #include "mir/scene/session.h"
2561 #include "mir/scene/session_listener.h"
2562 #include "session_event_sink.h"
2563+#include "mir/scene/trust_session_creation_parameters.h"
2564+#include "trust_session_impl.h"
2565+#include "trust_session_container.h"
2566+#include "mir/scene/trust_session_listener.h"
2567+
2568+#include <boost/throw_exception.hpp>
2569
2570 #include <memory>
2571 #include <cassert>
2572@@ -38,13 +44,16 @@
2573 std::shared_ptr<msh::FocusSetter> const& focus_setter,
2574 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
2575 std::shared_ptr<SessionEventSink> const& session_event_sink,
2576- std::shared_ptr<SessionListener> const& session_listener) :
2577+ std::shared_ptr<SessionListener> const& session_listener,
2578+ std::shared_ptr<TrustSessionListener> const& trust_session_listener) :
2579 surface_coordinator(surface_factory),
2580 app_container(container),
2581 focus_setter(focus_setter),
2582 snapshot_strategy(snapshot_strategy),
2583 session_event_sink(session_event_sink),
2584- session_listener(session_listener)
2585+ session_listener(session_listener),
2586+ trust_session_listener(trust_session_listener),
2587+ trust_session_container(std::make_shared<TrustSessionContainer>())
2588 {
2589 assert(surface_factory);
2590 assert(container);
2591@@ -85,6 +94,16 @@
2592
2593 session_listener->starting(new_session);
2594
2595+ {
2596+ trust_session_container->for_each_trust_session_for_process(client_pid,
2597+ [client_pid, new_session](std::shared_ptr<frontend::TrustSession> const& trust_session)
2598+ {
2599+ auto scene_trust_session = std::dynamic_pointer_cast<ms::TrustSession>(trust_session);
2600+
2601+ scene_trust_session->add_trusted_child(new_session);
2602+ });
2603+ }
2604+
2605 set_focus_to(new_session);
2606
2607 return new_session;
2608@@ -122,12 +141,45 @@
2609 scene_session->force_requests_to_complete();
2610
2611 session_event_sink->handle_session_stopping(scene_session);
2612+
2613+ {
2614+ std::unique_lock<std::mutex> lock(trust_sessions_mutex);
2615+
2616+ std::vector<std::shared_ptr<frontend::TrustSession>> trust_sessions;
2617+ trust_session_container->for_each_trust_session_for_process(scene_session->process_id(),
2618+ [&](std::shared_ptr<frontend::TrustSession> const& trust_session)
2619+ {
2620+ trust_sessions.push_back(trust_session);
2621+ });
2622+
2623+ for(auto trust_session : trust_sessions)
2624+ {
2625+ auto scene_trust_session = std::dynamic_pointer_cast<ms::TrustSession>(trust_session);
2626+
2627+ if (scene_trust_session->get_trusted_helper().lock() == scene_session)
2628+ {
2629+ stop_trust_session_locked(lock, scene_trust_session);
2630+ }
2631+ else
2632+ {
2633+ scene_trust_session->remove_trusted_child(scene_session);
2634+
2635+ trust_session_container->remove_process(scene_session->process_id());
2636+ }
2637+ }
2638+ }
2639+
2640 session_listener->stopping(scene_session);
2641
2642 app_container->remove_session(scene_session);
2643
2644 std::unique_lock<std::mutex> lock(mutex);
2645- set_focus_to_locked(lock, app_container->successor_of(std::shared_ptr<Session>()));
2646+ auto old_focus = focus_application.lock();
2647+ if (old_focus == scene_session)
2648+ {
2649+ // only reset the focus if this session had focus
2650+ set_focus_to_locked(lock, app_container->successor_of(std::shared_ptr<ms::Session>()));
2651+ }
2652 }
2653
2654 void ms::SessionManager::focus_next()
2655@@ -169,3 +221,73 @@
2656 {
2657 set_focus_to(std::dynamic_pointer_cast<Session>(session));
2658 }
2659+
2660+std::shared_ptr<mf::TrustSession> ms::SessionManager::start_trust_session_for(std::shared_ptr<mf::Session> const& session,
2661+ TrustSessionCreationParameters const& params)
2662+{
2663+ std::unique_lock<std::mutex> lock(trust_sessions_mutex);
2664+
2665+ auto shell_session = std::dynamic_pointer_cast<ms::Session>(session);
2666+
2667+ auto const trust_session = std::make_shared<TrustSessionImpl>(shell_session, params, trust_session_listener);
2668+
2669+ trust_session_container->insert(trust_session, shell_session->process_id());
2670+
2671+ trust_session->start();
2672+ trust_session_listener->starting(trust_session);
2673+
2674+ add_trusted_session_for_locked(lock, trust_session, params.base_process_id);
2675+ return trust_session;
2676+}
2677+
2678+MirTrustSessionAddTrustResult ms::SessionManager::add_trusted_session_for(std::shared_ptr<mf::TrustSession> const& trust_session,
2679+ pid_t session_pid)
2680+{
2681+ std::unique_lock<std::mutex> lock(trust_sessions_mutex);
2682+
2683+ return add_trusted_session_for_locked(lock, trust_session, session_pid);
2684+}
2685+
2686+MirTrustSessionAddTrustResult ms::SessionManager::add_trusted_session_for_locked(std::unique_lock<std::mutex> const&,
2687+ std::shared_ptr<mf::TrustSession> const& trust_session,
2688+ pid_t session_pid)
2689+{
2690+ auto scene_trust_session = std::dynamic_pointer_cast<ms::TrustSession>(trust_session);
2691+
2692+ if (!trust_session_container->insert(trust_session, session_pid))
2693+ {
2694+ // TODO - remove comment once we have pid update for child fd created sessions.
2695+ // BOOST_THROW_EXCEPTION(std::runtime_error("failed to add trusted session"));
2696+ }
2697+
2698+ app_container->for_each(
2699+ [&](std::shared_ptr<ms::Session> const& container_session)
2700+ {
2701+ if (container_session->process_id() == session_pid)
2702+ {
2703+ scene_trust_session->add_trusted_child(container_session);
2704+ }
2705+ });
2706+
2707+ return mir_trust_session_add_tust_succeeded;
2708+}
2709+
2710+void ms::SessionManager::stop_trust_session(std::shared_ptr<mf::TrustSession> const& trust_session)
2711+{
2712+ std::unique_lock<std::mutex> lock(trust_sessions_mutex);
2713+
2714+ stop_trust_session_locked(lock, trust_session);
2715+}
2716+
2717+void ms::SessionManager::stop_trust_session_locked(std::unique_lock<std::mutex> const&,
2718+ std::shared_ptr<mf::TrustSession> const& trust_session)
2719+{
2720+ auto scene_trust_session = std::dynamic_pointer_cast<ms::TrustSession>(trust_session);
2721+
2722+ trust_session->stop();
2723+
2724+ trust_session_container->remove_trust_session(trust_session);
2725+
2726+ trust_session_listener->stopping(scene_trust_session);
2727+}
2728+
2729
2730=== modified file 'src/server/scene/session_manager.h'
2731--- src/server/scene/session_manager.h 2014-04-15 05:31:19 +0000
2732+++ src/server/scene/session_manager.h 2014-05-15 13:19:23 +0000
2733@@ -26,6 +26,7 @@
2734 #include <mutex>
2735 #include <memory>
2736 #include <vector>
2737+#include <map>
2738
2739 namespace mir
2740 {
2741@@ -42,6 +43,8 @@
2742 class SessionListener;
2743 class SnapshotStrategy;
2744 class SurfaceCoordinator;
2745+class TrustSessionContainer;
2746+class TrustSessionListener;
2747
2748 class SessionManager : public frontend::Shell, public shell::FocusController
2749 {
2750@@ -51,7 +54,8 @@
2751 std::shared_ptr<shell::FocusSetter> const& focus_setter,
2752 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
2753 std::shared_ptr<SessionEventSink> const& session_event_sink,
2754- std::shared_ptr<SessionListener> const& session_listener);
2755+ std::shared_ptr<SessionListener> const& session_listener,
2756+ std::shared_ptr<TrustSessionListener> const& trust_session_listener);
2757 virtual ~SessionManager();
2758
2759 virtual std::shared_ptr<frontend::Session> open_session(
2760@@ -71,6 +75,12 @@
2761
2762 void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override;
2763
2764+ std::shared_ptr<frontend::TrustSession> start_trust_session_for(std::shared_ptr<frontend::Session> const& session,
2765+ TrustSessionCreationParameters const& params) override;
2766+ MirTrustSessionAddTrustResult add_trusted_session_for(std::shared_ptr<frontend::TrustSession> const& trust_session,
2767+ pid_t session_pid) override;
2768+ void stop_trust_session(std::shared_ptr<frontend::TrustSession> const& trust_session) override;
2769+
2770 protected:
2771 SessionManager(const SessionManager&) = delete;
2772 SessionManager& operator=(const SessionManager&) = delete;
2773@@ -82,11 +92,20 @@
2774 std::shared_ptr<SnapshotStrategy> const snapshot_strategy;
2775 std::shared_ptr<SessionEventSink> const session_event_sink;
2776 std::shared_ptr<SessionListener> const session_listener;
2777+ std::shared_ptr<TrustSessionListener> const trust_session_listener;
2778+ std::shared_ptr<TrustSessionContainer> trust_session_container;
2779
2780 std::mutex mutex;
2781 std::weak_ptr<Session> focus_application;
2782
2783 void set_focus_to_locked(std::unique_lock<std::mutex> const& lock, std::shared_ptr<Session> const& next_focus);
2784+
2785+ MirTrustSessionAddTrustResult add_trusted_session_for_locked(std::unique_lock<std::mutex> const&,
2786+ std::shared_ptr<frontend::TrustSession> const& trust_session,
2787+ pid_t session_pid);
2788+ void stop_trust_session_locked(std::unique_lock<std::mutex> const& lock,
2789+ std::shared_ptr<frontend::TrustSession> const& trust_session);
2790+ std::mutex mutable trust_sessions_mutex;
2791 };
2792
2793 }
2794
2795=== added file 'src/server/scene/trust_session_container.cpp'
2796--- src/server/scene/trust_session_container.cpp 1970-01-01 00:00:00 +0000
2797+++ src/server/scene/trust_session_container.cpp 2014-05-15 13:19:23 +0000
2798@@ -0,0 +1,95 @@
2799+/*
2800+ * Copyright © 2014 Canonical Ltd.
2801+ *
2802+ * This program is free software: you can redistribute it and/or modify it
2803+ * under the terms of the GNU General Public License version 3,
2804+ * as published by the Free Software Foundation.
2805+ *
2806+ * This program is distributed in the hope that it will be useful,
2807+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2808+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2809+ * GNU General Public License for more details.
2810+ *
2811+ * You should have received a copy of the GNU General Public License
2812+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2813+ *
2814+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
2815+ */
2816+
2817+#include "trust_session_container.h"
2818+
2819+namespace ms = mir::scene;
2820+namespace mf = mir::frontend;
2821+
2822+uint insertion_order = 0;
2823+
2824+ms::TrustSessionContainer::TrustSessionContainer()
2825+ : trust_session_index(process_map)
2826+ , process_index(get<1>(process_map))
2827+{
2828+}
2829+
2830+bool ms::TrustSessionContainer::insert(std::shared_ptr<mf::TrustSession> const& trust_session, ClientProcess const& process)
2831+{
2832+ std::unique_lock<std::mutex> lk(mutex);
2833+
2834+ object_by_trust_session::iterator it;
2835+ bool valid = false;
2836+
2837+ Object obj{trust_session, process, insertion_order++};
2838+ boost::tie(it,valid) = process_map.insert(obj);
2839+
2840+ return valid;
2841+}
2842+
2843+void ms::TrustSessionContainer::for_each_process_for_trust_session(
2844+ std::shared_ptr<mf::TrustSession> const& trust_session,
2845+ std::function<void(ClientProcess const& id)> f)
2846+{
2847+ std::unique_lock<std::mutex> lk(mutex);
2848+
2849+ object_by_trust_session::iterator it,end;
2850+ boost::tie(it,end) = trust_session_index.equal_range(trust_session);
2851+
2852+ for (; it != end; ++it)
2853+ {
2854+ Object const& obj = *it;
2855+ f(obj.client_process);
2856+ }
2857+}
2858+
2859+void ms::TrustSessionContainer::for_each_trust_session_for_process(
2860+ ClientProcess const& process,
2861+ std::function<void(std::shared_ptr<mf::TrustSession> const&)> f)
2862+{
2863+ std::unique_lock<std::mutex> lk(mutex);
2864+
2865+ object_by_process::iterator it,end;
2866+ boost::tie(it,end) = process_index.equal_range(process);
2867+
2868+ for (; it != end; ++it)
2869+ {
2870+ Object const& obj = *it;
2871+ f(obj.trust_session);
2872+ }
2873+}
2874+
2875+void ms::TrustSessionContainer::remove_trust_session(std::shared_ptr<frontend::TrustSession> const& trust_session)
2876+{
2877+ std::unique_lock<std::mutex> lk(mutex);
2878+
2879+ object_by_trust_session::iterator it,end;
2880+ boost::tie(it,end) = trust_session_index.equal_range(trust_session);
2881+
2882+ trust_session_index.erase(it, end);
2883+}
2884+
2885+void ms::TrustSessionContainer::remove_process(ClientProcess const& process)
2886+{
2887+ std::unique_lock<std::mutex> lk(mutex);
2888+
2889+ object_by_process::iterator it,end;
2890+ boost::tie(it,end) = process_index.equal_range(process);
2891+
2892+ process_index.erase(it, end);
2893+}
2894
2895=== added file 'src/server/scene/trust_session_container.h'
2896--- src/server/scene/trust_session_container.h 1970-01-01 00:00:00 +0000
2897+++ src/server/scene/trust_session_container.h 2014-05-15 13:19:23 +0000
2898@@ -0,0 +1,103 @@
2899+/*
2900+ * Copyright © 2014 Canonical Ltd.
2901+ *
2902+ * This program is free software: you can redistribute it and/or modify it
2903+ * under the terms of the GNU General Public License version 3,
2904+ * as published by the Free Software Foundation.
2905+ *
2906+ * This program is distributed in the hope that it will be useful,
2907+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2908+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2909+ * GNU General Public License for more details.
2910+ *
2911+ * You should have received a copy of the GNU General Public License
2912+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2913+ *
2914+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
2915+ */
2916+
2917+#ifndef MIR_SCENE_TRUST_SESSION_CONTAINER_H_
2918+#define MIR_SCENE_TRUST_SESSION_CONTAINER_H_
2919+
2920+#include <sys/types.h>
2921+#include <mutex>
2922+#include <map>
2923+
2924+#include <boost/multi_index_container.hpp>
2925+#include <boost/multi_index/member.hpp>
2926+#include <boost/multi_index/ordered_index.hpp>
2927+#include <boost/multi_index/hashed_index.hpp>
2928+#include <boost/multi_index/composite_key.hpp>
2929+
2930+namespace mir
2931+{
2932+namespace frontend
2933+{
2934+class TrustSession;
2935+class Session;
2936+}
2937+
2938+using boost::multi_index_container;
2939+using namespace boost::multi_index;
2940+
2941+namespace scene
2942+{
2943+
2944+class TrustSessionContainer
2945+{
2946+public:
2947+ TrustSessionContainer();
2948+ virtual ~TrustSessionContainer() = default;
2949+
2950+ typedef pid_t ClientProcess;
2951+
2952+ bool insert(std::shared_ptr<frontend::TrustSession> const& trust_session, ClientProcess const& process);
2953+
2954+ void for_each_process_for_trust_session(std::shared_ptr<frontend::TrustSession> const& trust_session, std::function<void(ClientProcess const&)> f);
2955+ void for_each_trust_session_for_process(ClientProcess const& process, std::function<void(std::shared_ptr<frontend::TrustSession> const&)> f);
2956+
2957+ void remove_trust_session(std::shared_ptr<frontend::TrustSession> const& trust_session);
2958+ void remove_process(ClientProcess const& process);
2959+
2960+private:
2961+ std::mutex mutable mutex;
2962+
2963+ typedef struct {
2964+ std::shared_ptr<frontend::TrustSession> trust_session;
2965+ ClientProcess client_process;
2966+ uint insert_order;
2967+ } Object;
2968+
2969+ typedef multi_index_container<
2970+ Object,
2971+ indexed_by<
2972+ ordered_non_unique<
2973+ composite_key<
2974+ Object,
2975+ member<Object, std::shared_ptr<frontend::TrustSession>, &Object::trust_session>,
2976+ member<Object, uint, &Object::insert_order>
2977+ >
2978+ >,
2979+ ordered_unique<
2980+ composite_key<
2981+ Object,
2982+ member<Object, ClientProcess, &Object::client_process>,
2983+ member<Object, std::shared_ptr<frontend::TrustSession>, &Object::trust_session>
2984+ >
2985+ >
2986+ >
2987+ > TrustSessionsProcesses;
2988+
2989+ typedef nth_index<TrustSessionsProcesses,0>::type object_by_trust_session;
2990+ typedef nth_index<TrustSessionsProcesses,1>::type object_by_process;
2991+
2992+
2993+ TrustSessionsProcesses process_map;
2994+ object_by_trust_session& trust_session_index;
2995+ object_by_process& process_index;
2996+};
2997+
2998+}
2999+}
3000+
3001+#endif // MIR_SCENE_TRUST_SESSION_CONTAINER_H_
3002
3003=== added file 'src/server/scene/trust_session_creation_parameters.cpp'
3004--- src/server/scene/trust_session_creation_parameters.cpp 1970-01-01 00:00:00 +0000
3005+++ src/server/scene/trust_session_creation_parameters.cpp 2014-05-15 13:19:23 +0000
3006@@ -0,0 +1,51 @@
3007+/*
3008+ * Copyright © 2014 Canonical Ltd.
3009+ *
3010+ * This program is free software: you can redistribute it and/or modify it
3011+ * under the terms of the GNU General Public License version 3,
3012+ * as published by the Free Software Foundation.
3013+ *
3014+ * This program is distributed in the hope that it will be useful,
3015+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3016+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3017+ * GNU General Public License for more details.
3018+ *
3019+ * You should have received a copy of the GNU General Public License
3020+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3021+ *
3022+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
3023+ */
3024+
3025+#include "mir/scene/trust_session_creation_parameters.h"
3026+
3027+namespace ms = mir::scene;
3028+
3029+ms::TrustSessionCreationParameters::TrustSessionCreationParameters()
3030+ : base_process_id(0)
3031+{
3032+}
3033+
3034+ms::TrustSessionCreationParameters& ms::TrustSessionCreationParameters::set_base_process_id(pid_t process_id)
3035+{
3036+ base_process_id = process_id;
3037+ return *this;
3038+}
3039+
3040+bool ms::operator==(
3041+ const TrustSessionCreationParameters& lhs,
3042+ const TrustSessionCreationParameters& rhs)
3043+{
3044+ return lhs.base_process_id == rhs.base_process_id;
3045+}
3046+
3047+bool ms::operator!=(
3048+ const TrustSessionCreationParameters& lhs,
3049+ const TrustSessionCreationParameters& rhs)
3050+{
3051+ return !(lhs == rhs);
3052+}
3053+
3054+ms::TrustSessionCreationParameters ms::a_trust_session()
3055+{
3056+ return TrustSessionCreationParameters();
3057+}
3058
3059=== added file 'src/server/scene/trust_session_impl.cpp'
3060--- src/server/scene/trust_session_impl.cpp 1970-01-01 00:00:00 +0000
3061+++ src/server/scene/trust_session_impl.cpp 2014-05-15 13:19:23 +0000
3062@@ -0,0 +1,175 @@
3063+/*
3064+ * Copyright © 2014 Canonical Ltd.
3065+ *
3066+ * This program is free software: you can redistribute it and/or modify it
3067+ * under the terms of the GNU General Public License version 3,
3068+ * as published by the Free Software Foundation.
3069+ *
3070+ * This program is distributed in the hope that it will be useful,
3071+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3072+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3073+ * GNU General Public License for more details.
3074+ *
3075+ * You should have received a copy of the GNU General Public License
3076+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3077+ *
3078+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
3079+ */
3080+
3081+#include "trust_session_impl.h"
3082+#include "mir/scene/session.h"
3083+#include "mir/scene/trust_session_creation_parameters.h"
3084+#include "mir/scene/trust_session_listener.h"
3085+#include "session_container.h"
3086+
3087+#include <sstream>
3088+#include <algorithm>
3089+
3090+namespace ms = mir::scene;
3091+
3092+int next_unique_id = 0;
3093+
3094+ms::TrustSessionImpl::TrustSessionImpl(
3095+ std::weak_ptr<ms::Session> const& session,
3096+ TrustSessionCreationParameters const&,
3097+ std::shared_ptr<TrustSessionListener> const& trust_session_listener) :
3098+ trusted_helper(session),
3099+ trust_session_listener(trust_session_listener),
3100+ state(mir_trust_session_state_stopped)
3101+{
3102+}
3103+
3104+ms::TrustSessionImpl::~TrustSessionImpl()
3105+{
3106+ TrustSessionImpl::stop();
3107+}
3108+
3109+MirTrustSessionState ms::TrustSessionImpl::get_state() const
3110+{
3111+ std::lock_guard<decltype(mutex)> lock(mutex);
3112+
3113+ return state;
3114+}
3115+
3116+std::weak_ptr<ms::Session> ms::TrustSessionImpl::get_trusted_helper() const
3117+{
3118+ std::lock_guard<decltype(mutex)> lock(mutex);
3119+
3120+ return trusted_helper;
3121+}
3122+
3123+void ms::TrustSessionImpl::start()
3124+{
3125+ std::lock_guard<decltype(mutex)> lock(mutex);
3126+
3127+ if (state == mir_trust_session_state_started)
3128+ return;
3129+
3130+ state = mir_trust_session_state_started;
3131+
3132+ auto helper = trusted_helper.lock();
3133+ if (helper) {
3134+ helper->begin_trust_session();
3135+ }
3136+}
3137+
3138+void ms::TrustSessionImpl::stop()
3139+{
3140+ std::lock_guard<decltype(mutex)> lock(mutex);
3141+
3142+ if (state == mir_trust_session_state_stopped)
3143+ return;
3144+
3145+ state = mir_trust_session_state_stopped;
3146+
3147+ auto helper = trusted_helper.lock();
3148+ if (helper) {
3149+ helper->end_trust_session();
3150+ }
3151+
3152+ std::vector<std::shared_ptr<ms::Session>> children;
3153+ {
3154+ std::lock_guard<decltype(mutex_children)> child_lock(mutex_children);
3155+
3156+ for (auto rit = trusted_children.rbegin(); rit != trusted_children.rend(); ++rit)
3157+ {
3158+ auto session = (*rit).lock();
3159+ if (session)
3160+ {
3161+ children.push_back(session);
3162+ }
3163+ }
3164+ trusted_children.clear();
3165+ }
3166+
3167+ for (auto session : children)
3168+ {
3169+ trust_session_listener->trusted_session_ending(*this, session);
3170+ }
3171+}
3172+
3173+bool ms::TrustSessionImpl::add_trusted_child(std::shared_ptr<ms::Session> const& session)
3174+{
3175+ std::lock_guard<decltype(mutex)> lock(mutex);
3176+
3177+ if (state == mir_trust_session_state_stopped)
3178+ return false;
3179+
3180+ {
3181+ std::lock_guard<decltype(mutex_children)> child_lock(mutex_children);
3182+
3183+ if (std::find_if(trusted_children.begin(), trusted_children.end(),
3184+ [session](std::weak_ptr<ms::Session> const& child)
3185+ {
3186+ return child.lock() == session;
3187+ }) != trusted_children.end())
3188+ {
3189+ return false;
3190+ }
3191+
3192+ trusted_children.push_back(session);
3193+ }
3194+
3195+ trust_session_listener->trusted_session_beginning(*this, session);
3196+ return true;
3197+}
3198+
3199+void ms::TrustSessionImpl::remove_trusted_child(std::shared_ptr<ms::Session> const& session)
3200+{
3201+ std::lock_guard<decltype(mutex)> lock(mutex);
3202+
3203+ if (state == mir_trust_session_state_stopped)
3204+ return;
3205+
3206+ bool found = false;
3207+ {
3208+ std::lock_guard<decltype(mutex_children)> child_lock(mutex_children);
3209+
3210+ for (auto it = trusted_children.begin(); it != trusted_children.end(); ++it)
3211+ {
3212+ auto trusted_child = (*it).lock();
3213+ if (trusted_child && trusted_child == session) {
3214+ found = true;
3215+ trusted_children.erase(it);
3216+ break;
3217+ }
3218+ }
3219+ }
3220+
3221+ if (found)
3222+ {
3223+ trust_session_listener->trusted_session_ending(*this, session);
3224+ }
3225+}
3226+
3227+void ms::TrustSessionImpl::for_each_trusted_child(
3228+ std::function<void(std::shared_ptr<ms::Session> const&)> f) const
3229+{
3230+ std::lock_guard<decltype(mutex_children)> child_lock(mutex_children);
3231+
3232+ for (auto it = trusted_children.begin(); it != trusted_children.end(); ++it)
3233+ {
3234+ if (auto trusted_child = (*it).lock())
3235+ f(trusted_child);
3236+ }
3237+}
3238
3239=== added file 'src/server/scene/trust_session_impl.h'
3240--- src/server/scene/trust_session_impl.h 1970-01-01 00:00:00 +0000
3241+++ src/server/scene/trust_session_impl.h 2014-05-15 13:19:23 +0000
3242@@ -0,0 +1,74 @@
3243+/*
3244+ * Copyright © 2014 Canonical Ltd.
3245+ *
3246+ * This program is free software: you can redistribute it and/or modify it
3247+ * under the terms of the GNU General Public License version 3,
3248+ * as published by the Free Software Foundation.
3249+ *
3250+ * This program is distributed in the hope that it will be useful,
3251+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3252+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3253+ * GNU General Public License for more details.
3254+ *
3255+ * You should have received a copy of the GNU General Public License
3256+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3257+ *
3258+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
3259+ */
3260+
3261+#ifndef MIR_SCENE_TRUST_SESSION_IMPL_H_
3262+#define MIR_SCENE_TRUST_SESSION_IMPL_H_
3263+
3264+#include "mir/scene/trust_session.h"
3265+
3266+#include <vector>
3267+#include <atomic>
3268+#include <mutex>
3269+
3270+namespace mir
3271+{
3272+
3273+namespace scene
3274+{
3275+class SessionContainer;
3276+class TrustSessionCreationParameters;
3277+class TrustSessionListener;
3278+
3279+class TrustSessionImpl : public TrustSession
3280+{
3281+public:
3282+ TrustSessionImpl(std::weak_ptr<Session> const& session,
3283+ TrustSessionCreationParameters const& parameters,
3284+ std::shared_ptr<TrustSessionListener> const& trust_session_listener);
3285+ ~TrustSessionImpl();
3286+
3287+ MirTrustSessionState get_state() const override;
3288+ std::weak_ptr<Session> get_trusted_helper() const override;
3289+
3290+ void start() override;
3291+ void stop() override;
3292+
3293+ bool add_trusted_child(std::shared_ptr<Session> const& session);
3294+ void remove_trusted_child(std::shared_ptr<Session> const& session);
3295+ void for_each_trusted_child(std::function<void(std::shared_ptr<Session> const&)> f) const;
3296+
3297+protected:
3298+ TrustSessionImpl(const TrustSessionImpl&) = delete;
3299+ TrustSessionImpl& operator=(const TrustSessionImpl&) = delete;
3300+
3301+private:
3302+ std::weak_ptr<Session> const trusted_helper;
3303+ std::shared_ptr<TrustSessionListener> const trust_session_listener;
3304+ MirTrustSessionState state;
3305+ std::string cookie;
3306+ std::mutex mutable mutex;
3307+
3308+ std::mutex mutable mutex_children;
3309+ std::vector<pid_t> client_processes;
3310+ std::vector<std::weak_ptr<Session>> trusted_children;
3311+};
3312+
3313+}
3314+}
3315+
3316+#endif // MIR_SCENE_TRUST_SESSION_H_
3317
3318=== modified file 'src/shared/protobuf/mir_protobuf.proto'
3319--- src/shared/protobuf/mir_protobuf.proto 2014-05-09 19:52:44 +0000
3320+++ src/shared/protobuf/mir_protobuf.proto 2014-05-15 13:19:23 +0000
3321@@ -100,7 +100,7 @@
3322 optional int32 pixel_format = 4;
3323 optional int32 buffer_usage = 5;
3324 optional Buffer buffer = 6;
3325-
3326+
3327 repeated sint32 fd = 7;
3328 optional int32 fds_on_side_channel = 8;
3329
3330@@ -185,7 +185,6 @@
3331 required int32 number = 1;
3332 }
3333
3334-
3335 message SocketFD {
3336 repeated sint32 fd = 1;
3337 optional int32 fds_on_side_channel = 2;
3338@@ -193,6 +192,24 @@
3339 optional string error = 127;
3340 }
3341
3342+message TrustedSession {
3343+ required int32 pid = 1;
3344+}
3345+
3346+message TrustSessionParameters {
3347+ required TrustedSession base_trusted_session = 1;
3348+}
3349+
3350+message TrustSession {
3351+ optional uint32 state = 1;
3352+ optional string error = 127;
3353+}
3354+
3355+message TrustSessionAddResult {
3356+ optional int32 result = 1;
3357+ optional string error = 127;
3358+}
3359+
3360 service DisplayServer {
3361 // Platform independent requests
3362 rpc connect(ConnectParameters) returns (Connection);
3363@@ -215,4 +232,8 @@
3364
3365 rpc configure_cursor(CursorSetting) returns (Void);
3366 rpc new_fds_for_trusted_clients(SocketFDRequest) returns (SocketFD);
3367+
3368+ rpc start_trust_session(TrustSessionParameters) returns (TrustSession);
3369+ rpc add_trusted_session(TrustedSession) returns (TrustSessionAddResult);
3370+ rpc stop_trust_session(Void) returns (Void);
3371 }
3372
3373=== modified file 'tests/acceptance-tests/CMakeLists.txt'
3374--- tests/acceptance-tests/CMakeLists.txt 2014-05-09 19:52:44 +0000
3375+++ tests/acceptance-tests/CMakeLists.txt 2014-05-15 13:19:23 +0000
3376@@ -28,6 +28,7 @@
3377 test_surfaces_with_output_id.cpp
3378 test_server_disconnect.cpp
3379 test_client_library_drm.cpp
3380+ test_client_trust_session_api.cpp
3381 test_protobuf.cpp
3382 test_client_screencast.cpp
3383 test_client_surface_swap_buffers.cpp
3384
3385=== added file 'tests/acceptance-tests/test_client_trust_session_api.cpp'
3386--- tests/acceptance-tests/test_client_trust_session_api.cpp 1970-01-01 00:00:00 +0000
3387+++ tests/acceptance-tests/test_client_trust_session_api.cpp 2014-05-15 13:19:23 +0000
3388@@ -0,0 +1,106 @@
3389+/*
3390+ * Copyright © 2013 Canonical Ltd.
3391+ *
3392+ * This program is free software: you can redistribute it and/or modify
3393+ * it under the terms of the GNU General Public License version 3 as
3394+ * published by the Free Software Foundation.
3395+ *
3396+ * This program is distributed in the hope that it will be useful,
3397+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3398+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3399+ * GNU General Public License for more details.
3400+ *
3401+ * You should have received a copy of the GNU General Public License
3402+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3403+ *
3404+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
3405+ */
3406+
3407+#include "mir_test_framework/display_server_test_fixture.h"
3408+
3409+#include "mir_toolkit/mir_client_library.h"
3410+#include "mir_toolkit/mir_trust_session.h"
3411+
3412+#include <gtest/gtest.h>
3413+
3414+namespace mtf = mir_test_framework;
3415+
3416+namespace
3417+{
3418+ char const* const mir_test_socket = mtf::test_socket_file().c_str();
3419+}
3420+
3421+using MirClientTrustSessionAPITest = DefaultDisplayServerTestFixture;
3422+
3423+namespace mir
3424+{
3425+namespace
3426+{
3427+struct ClientConfigCommon : TestingClientConfiguration
3428+{
3429+ ClientConfigCommon()
3430+ : connection(0)
3431+ , trust_session(0)
3432+ , started(0)
3433+ , stopped(0)
3434+ {
3435+ }
3436+
3437+ static void connection_callback(MirConnection * connection, void * context)
3438+ {
3439+ ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
3440+ config->connection = connection;
3441+ }
3442+
3443+ virtual void connected(MirConnection * new_connection)
3444+ {
3445+ connection = new_connection;
3446+ }
3447+
3448+ static void trust_session_start_callback(MirTrustSession * session, void * context)
3449+ {
3450+ ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
3451+ config->trust_session = session;
3452+ config->started++;
3453+ }
3454+
3455+ static void trust_session_stop_callback(MirTrustSession * /* session */, void * context)
3456+ {
3457+ ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
3458+ config->stopped++;
3459+ }
3460+
3461+ MirConnection* connection;
3462+ MirTrustSession* trust_session;
3463+ int started;
3464+ int stopped;
3465+};
3466+}
3467+
3468+TEST_F(MirClientTrustSessionAPITest, client_trust_session_api)
3469+{
3470+ struct ClientConfig : ClientConfigCommon
3471+ {
3472+ void exec()
3473+ {
3474+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
3475+
3476+ ASSERT_TRUE(connection != NULL);
3477+ EXPECT_TRUE(mir_connection_is_valid(connection));
3478+ EXPECT_STREQ("", mir_connection_get_error_message(connection));
3479+
3480+ mir_wait_for(mir_connection_start_trust_session(connection, __LINE__, trust_session_start_callback, NULL, this));
3481+ ASSERT_TRUE(trust_session != NULL);
3482+ EXPECT_EQ(started, 1);
3483+
3484+ mir_wait_for(mir_trust_session_stop(trust_session, trust_session_stop_callback, this));
3485+ EXPECT_EQ(stopped, 1);
3486+
3487+ mir_connection_release(connection);
3488+ }
3489+ } client_config;
3490+
3491+ launch_client_process(client_config);
3492+}
3493+
3494+}
3495
3496=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
3497--- tests/acceptance-tests/test_nested_mir.cpp 2014-03-06 06:05:17 +0000
3498+++ tests/acceptance-tests/test_nested_mir.cpp 2014-05-15 13:19:23 +0000
3499@@ -56,6 +56,9 @@
3500 MOCK_METHOD1(session_next_buffer_called, void (std::string const&));
3501 MOCK_METHOD1(session_release_surface_called, void (std::string const&));
3502 MOCK_METHOD1(session_disconnect_called, void (std::string const&));
3503+ MOCK_METHOD2(session_start_trust_session_called, void (std::string const&, std::string const&));
3504+ MOCK_METHOD2(session_add_trusted_session_called, void (std::string const&, std::string const&));
3505+ MOCK_METHOD1(session_stop_trust_session_called, void (std::string const&));
3506
3507 void session_drm_auth_magic_called(const std::string&) override {};
3508 void session_configure_surface_called(std::string const&) override {};
3509
3510=== modified file 'tests/integration-tests/frontend/test_application_mediator_report.cpp'
3511--- tests/integration-tests/frontend/test_application_mediator_report.cpp 2014-03-06 06:05:17 +0000
3512+++ tests/integration-tests/frontend/test_application_mediator_report.cpp 2014-05-15 13:19:23 +0000
3513@@ -50,6 +50,12 @@
3514
3515 EXPECT_CALL(*this, session_disconnect_called(testing::_)).
3516 Times(testing::AtLeast(0));
3517+
3518+ EXPECT_CALL(*this, session_start_trust_session_called(testing::_, testing::_)).
3519+ Times(testing::AtLeast(0));
3520+
3521+ EXPECT_CALL(*this, session_stop_trust_session_called(testing::_)).
3522+ Times(testing::AtLeast(0));
3523 }
3524
3525 MOCK_METHOD1(session_connect_called, void (std::string const&));
3526@@ -57,6 +63,9 @@
3527 MOCK_METHOD1(session_next_buffer_called, void (std::string const&));
3528 MOCK_METHOD1(session_release_surface_called, void (std::string const&));
3529 MOCK_METHOD1(session_disconnect_called, void (std::string const&));
3530+ MOCK_METHOD2(session_start_trust_session_called, void (std::string const&, std::string const&));
3531+ MOCK_METHOD2(session_add_trusted_session_called, void (std::string const&, std::string const&));
3532+ MOCK_METHOD1(session_stop_trust_session_called, void (std::string const&));
3533
3534 void session_drm_auth_magic_called(const std::string&) override {};
3535 void session_configure_surface_called(std::string const&) override {};
3536@@ -358,3 +367,175 @@
3537
3538 launch_client_process(client_process);
3539 }
3540+
3541+TEST_F(ApplicationMediatorReport, trust_session_start_called)
3542+{
3543+ struct Server : TestingServerConfiguration
3544+ {
3545+ std::shared_ptr<mf::SessionMediatorReport>
3546+ the_application_mediator_report()
3547+ {
3548+ auto result = std::make_shared<MockApplicationMediatorReport>();
3549+
3550+ EXPECT_CALL(*result, session_start_trust_session_called(testing::_, testing::_)).
3551+ Times(1);
3552+
3553+ return result;
3554+ }
3555+ } server_processing;
3556+
3557+ launch_server_process(server_processing);
3558+
3559+ struct Client: TestingClientConfiguration
3560+ {
3561+ void exec()
3562+ {
3563+ mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms);
3564+
3565+ client.connect_parameters.set_application_name(__PRETTY_FUNCTION__);
3566+ EXPECT_CALL(client, connect_done()).
3567+ Times(testing::AtLeast(0));
3568+ EXPECT_CALL(client, trust_session_start_done()).
3569+ Times(testing::AtLeast(0));
3570+
3571+ client.display_server.connect(
3572+ 0,
3573+ &client.connect_parameters,
3574+ &client.connection,
3575+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done));
3576+
3577+ client.wait_for_connect_done();
3578+
3579+ client.display_server.start_trust_session(
3580+ 0,
3581+ &client.trust_session_parameters,
3582+ &client.trust_session,
3583+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::trust_session_start_done));
3584+ client.wait_for_trust_session_start_done();
3585+
3586+ }
3587+ } client_process;
3588+
3589+ launch_client_process(client_process);
3590+}
3591+
3592+TEST_F(ApplicationMediatorReport, trust_session_add_trusted_session_called)
3593+{
3594+ struct Server : TestingServerConfiguration
3595+ {
3596+ std::shared_ptr<mf::SessionMediatorReport>
3597+ the_application_mediator_report()
3598+ {
3599+ auto result = std::make_shared<MockApplicationMediatorReport>();
3600+
3601+ EXPECT_CALL(*result, session_start_trust_session_called(testing::_, testing::_)).
3602+ Times(1);
3603+
3604+ return result;
3605+ }
3606+ } server_processing;
3607+
3608+ launch_server_process(server_processing);
3609+
3610+ struct Client: TestingClientConfiguration
3611+ {
3612+ void exec()
3613+ {
3614+ mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms);
3615+
3616+ client.connect_parameters.set_application_name(__PRETTY_FUNCTION__);
3617+ EXPECT_CALL(client, connect_done()).
3618+ Times(testing::AtLeast(0));
3619+ EXPECT_CALL(client, trust_session_start_done()).
3620+ Times(testing::AtLeast(0));
3621+ EXPECT_CALL(client, trust_session_add_trusted_session_done()).
3622+ Times(testing::AtLeast(0));
3623+
3624+ client.display_server.connect(
3625+ 0,
3626+ &client.connect_parameters,
3627+ &client.connection,
3628+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done));
3629+
3630+ client.wait_for_connect_done();
3631+
3632+ client.display_server.start_trust_session(
3633+ 0,
3634+ &client.trust_session_parameters,
3635+ &client.trust_session,
3636+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::trust_session_start_done));
3637+ client.wait_for_trust_session_start_done();
3638+
3639+ client.display_server.add_trusted_session(
3640+ 0,
3641+ &client.trusted_session,
3642+ &client.add_trust_result,
3643+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::trust_session_add_trusted_session_done));
3644+ client.wait_for_trust_session_add_trusted_session_done();
3645+
3646+ }
3647+ } client_process;
3648+
3649+ launch_client_process(client_process);
3650+}
3651+
3652+TEST_F(ApplicationMediatorReport, trust_session_stop_called)
3653+{
3654+ struct Server : TestingServerConfiguration
3655+ {
3656+ std::shared_ptr<mf::SessionMediatorReport>
3657+ the_application_mediator_report()
3658+ {
3659+ auto result = std::make_shared<MockApplicationMediatorReport>();
3660+
3661+ EXPECT_CALL(*result, session_stop_trust_session_called(testing::_)).
3662+ Times(1);
3663+
3664+ return result;
3665+ }
3666+ } server_processing;
3667+
3668+ launch_server_process(server_processing);
3669+
3670+ struct Client: TestingClientConfiguration
3671+ {
3672+ void exec()
3673+ {
3674+ mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms);
3675+
3676+ client.connect_parameters.set_application_name(__PRETTY_FUNCTION__);
3677+ EXPECT_CALL(client, connect_done()).
3678+ Times(testing::AtLeast(0));
3679+ EXPECT_CALL(client, trust_session_start_done()).
3680+ Times(testing::AtLeast(0));
3681+ EXPECT_CALL(client, trust_session_stop_done()).
3682+ Times(testing::AtLeast(0));
3683+
3684+ client.display_server.connect(
3685+ 0,
3686+ &client.connect_parameters,
3687+ &client.connection,
3688+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done));
3689+
3690+ client.wait_for_connect_done();
3691+
3692+ client.display_server.start_trust_session(
3693+ 0,
3694+ &client.trust_session_parameters,
3695+ &client.trust_session,
3696+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::trust_session_start_done));
3697+ client.wait_for_trust_session_start_done();
3698+
3699+ client.display_server.stop_trust_session(
3700+ 0,
3701+ &client.ignored,
3702+ &client.ignored,
3703+ google::protobuf::NewCallback(&client, &mt::TestProtobufClient::trust_session_stop_done));
3704+ client.wait_for_trust_session_stop_done();
3705+ }
3706+ } client_process;
3707+
3708+ launch_client_process(client_process);
3709+}
3710+
3711+
3712
3713=== modified file 'tests/integration-tests/test_session_manager.cpp'
3714--- tests/integration-tests/test_session_manager.cpp 2014-04-15 05:31:19 +0000
3715+++ tests/integration-tests/test_session_manager.cpp 2014-05-15 13:19:23 +0000
3716@@ -24,6 +24,7 @@
3717 #include "mir/compositor/buffer_stream.h"
3718 #include "src/server/scene/basic_surface.h"
3719 #include "mir/scene/surface_creation_parameters.h"
3720+#include "mir/scene/null_trust_session_listener.h"
3721
3722 #include "mir_test/gmock_fixes.h"
3723 #include "mir_test/fake_shared.h"
3724@@ -55,7 +56,8 @@
3725 mt::fake_shared(focus_setter),
3726 std::make_shared<mtd::NullSnapshotStrategy>(),
3727 std::make_shared<mtd::NullSessionEventSink>(),
3728- mt::fake_shared(session_listener))
3729+ mt::fake_shared(session_listener),
3730+ std::make_shared<ms::NullTrustSessionListener>())
3731 {
3732
3733 }
3734
3735=== modified file 'tests/mir_test_doubles/test_protobuf_client.cpp'
3736--- tests/mir_test_doubles/test_protobuf_client.cpp 2014-03-06 06:05:17 +0000
3737+++ tests/mir_test_doubles/test_protobuf_client.cpp 2014-05-15 13:19:23 +0000
3738@@ -22,6 +22,7 @@
3739 #include "src/client/connection_surface_map.h"
3740 #include "src/client/display_configuration.h"
3741 #include "src/client/lifecycle_control.h"
3742+#include "src/client/event_distributor.h"
3743 #include "src/client/rpc/make_rpc_channel.h"
3744 #include "src/client/rpc/mir_basic_rpc_channel.h"
3745
3746@@ -38,7 +39,8 @@
3747 std::make_shared<mir::client::ConnectionSurfaceMap>(),
3748 std::make_shared<mir::client::DisplayConfiguration>(),
3749 rpc_report,
3750- std::make_shared<mir::client::LifecycleControl>())),
3751+ std::make_shared<mir::client::LifecycleControl>(),
3752+ std::make_shared<mir::client::EventDistributor>())),
3753 display_server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
3754 maxwait(timeout_ms),
3755 connect_done_called(false),
3756@@ -59,6 +61,9 @@
3757 surface_parameters.set_buffer_usage(0);
3758 surface_parameters.set_output_id(mir_display_output_id_invalid);
3759
3760+ trusted_session.set_pid(__LINE__);
3761+ trust_session_parameters.mutable_base_trusted_session()->set_pid(__LINE__);
3762+
3763 ON_CALL(*this, connect_done())
3764 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_connect_done));
3765 ON_CALL(*this, create_surface_done())
3766@@ -73,6 +78,12 @@
3767 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_drm_auth_magic_done));
3768 ON_CALL(*this, display_configure_done())
3769 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_configure_display_done));
3770+ ON_CALL(*this, trust_session_start_done())
3771+ .WillByDefault(testing::Invoke(&wc_trust_session_start, &WaitCondition::wake_up_everyone));
3772+ ON_CALL(*this, trust_session_add_trusted_session_done())
3773+ .WillByDefault(testing::Invoke(&wc_trust_session_add, &WaitCondition::wake_up_everyone));
3774+ ON_CALL(*this, trust_session_stop_done())
3775+ .WillByDefault(testing::Invoke(&wc_trust_session_stop, &WaitCondition::wake_up_everyone));
3776 }
3777
3778 void mir::test::TestProtobufClient::on_connect_done()
3779@@ -225,3 +236,18 @@
3780 }
3781 tfd_done_called.store(false);
3782 }
3783+
3784+void mir::test::TestProtobufClient::wait_for_trust_session_start_done()
3785+{
3786+ wc_trust_session_start.wait_for_at_most_seconds(maxwait);
3787+}
3788+
3789+void mir::test::TestProtobufClient::wait_for_trust_session_add_trusted_session_done()
3790+{
3791+ wc_trust_session_add.wait_for_at_most_seconds(maxwait);
3792+}
3793+
3794+void mir::test::TestProtobufClient::wait_for_trust_session_stop_done()
3795+{
3796+ wc_trust_session_stop.wait_for_at_most_seconds(maxwait);
3797+}
3798
3799=== modified file 'tests/unit-tests/client/CMakeLists.txt'
3800--- tests/unit-tests/client/CMakeLists.txt 2014-03-06 06:05:17 +0000
3801+++ tests/unit-tests/client/CMakeLists.txt 2014-05-15 13:19:23 +0000
3802@@ -8,6 +8,7 @@
3803 ${CMAKE_CURRENT_SOURCE_DIR}/test_wait_handle.cpp
3804 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_display_conf.cpp
3805 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_screencast.cpp
3806+ ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_trust_session.cpp
3807 )
3808
3809 if(MIR_TEST_PLATFORM STREQUAL "android")
3810
3811=== added file 'tests/unit-tests/client/test_mir_trust_session.cpp'
3812--- tests/unit-tests/client/test_mir_trust_session.cpp 1970-01-01 00:00:00 +0000
3813+++ tests/unit-tests/client/test_mir_trust_session.cpp 2014-05-15 13:19:23 +0000
3814@@ -0,0 +1,244 @@
3815+/*
3816+ * Copyright © 2014 Canonical Ltd.
3817+ *
3818+ * This program is free software: you can redistribute it and/or modify it
3819+ * under the terms of the GNU General Public License version 3,
3820+ * as published by the Free Software Foundation.
3821+ *
3822+ * This program is distributed in the hope that it will be useful,
3823+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3824+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3825+ * GNU General Public License for more details.
3826+ *
3827+ * You should have received a copy of the GNU General Public License
3828+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3829+ *
3830+ * Authored by: Nick Dedekind <nick.dedekind <nick.dedekind@canonical.com>
3831+ */
3832+
3833+#include "src/client/mir_trust_session.h"
3834+#include "src/client/event_distributor.h"
3835+
3836+#include <gtest/gtest.h>
3837+#include <gmock/gmock.h>
3838+
3839+#include <thread>
3840+
3841+namespace mcl = mir::client;
3842+
3843+namespace google
3844+{
3845+namespace protobuf
3846+{
3847+class RpcController;
3848+}
3849+}
3850+
3851+namespace
3852+{
3853+
3854+struct MockProtobufServer : mir::protobuf::DisplayServer
3855+{
3856+
3857+ MOCK_METHOD4(start_trust_session,
3858+ void(::google::protobuf::RpcController* /*controller*/,
3859+ ::mir::protobuf::TrustSessionParameters const* /*request*/,
3860+ ::mir::protobuf::TrustSession* /*response*/,
3861+ ::google::protobuf::Closure* /*done*/));
3862+
3863+ MOCK_METHOD4(add_trusted_session,
3864+ void(::google::protobuf::RpcController* /*controller*/,
3865+ const ::mir::protobuf::TrustedSession* /*request*/,
3866+ ::mir::protobuf::TrustSessionAddResult* /*response*/,
3867+ ::google::protobuf::Closure* /*done*/));
3868+
3869+ MOCK_METHOD4(stop_trust_session,
3870+ void(::google::protobuf::RpcController* /*controller*/,
3871+ ::mir::protobuf::Void const* /*request*/,
3872+ ::mir::protobuf::Void* /*response*/,
3873+ ::google::protobuf::Closure* /*done*/));
3874+};
3875+
3876+class StubProtobufServer : public mir::protobuf::DisplayServer
3877+{
3878+public:
3879+ void start_trust_session(::google::protobuf::RpcController* /*controller*/,
3880+ ::mir::protobuf::TrustSessionParameters const* /*request*/,
3881+ ::mir::protobuf::TrustSession* response,
3882+ ::google::protobuf::Closure* done) override
3883+ {
3884+ if (server_thread.joinable())
3885+ server_thread.join();
3886+ server_thread = std::thread{
3887+ [response, done, this]
3888+ {
3889+ response->clear_error();
3890+ done->Run();
3891+ }};
3892+ }
3893+
3894+ void add_trusted_session(::google::protobuf::RpcController* /*controller*/,
3895+ const ::mir::protobuf::TrustedSession* /*request*/,
3896+ ::mir::protobuf::TrustSessionAddResult* /*response*/,
3897+ ::google::protobuf::Closure* done)
3898+ {
3899+ if (server_thread.joinable())
3900+ server_thread.join();
3901+ server_thread = std::thread{[done, this] { done->Run(); }};
3902+ }
3903+
3904+ void stop_trust_session(::google::protobuf::RpcController* /*controller*/,
3905+ mir::protobuf::Void const* /*request*/,
3906+ ::mir::protobuf::Void* /*response*/,
3907+ ::google::protobuf::Closure* done) override
3908+ {
3909+ if (server_thread.joinable())
3910+ server_thread.join();
3911+ server_thread = std::thread{[done, this] { done->Run(); }};
3912+ }
3913+
3914+ StubProtobufServer()
3915+ {
3916+ }
3917+
3918+ ~StubProtobufServer()
3919+ {
3920+ if (server_thread.joinable())
3921+ server_thread.join();
3922+ }
3923+
3924+private:
3925+ std::thread server_thread;
3926+};
3927+
3928+class MirTrustSessionTest : public testing::Test
3929+{
3930+public:
3931+ MirTrustSessionTest()
3932+ : event_distributor{std::make_shared<mcl::EventDistributor>()}
3933+ {
3934+ }
3935+
3936+ static void trust_session_event(MirTrustSession*, MirTrustSessionState new_state, void* context)
3937+ {
3938+ MirTrustSessionTest* test = static_cast<MirTrustSessionTest*>(context);
3939+ test->state_updated(new_state);
3940+ }
3941+
3942+ MOCK_METHOD1(state_updated, void(MirTrustSessionState));
3943+
3944+ testing::NiceMock<MockProtobufServer> mock_server;
3945+ StubProtobufServer stub_server;
3946+ std::shared_ptr<mcl::EventDistributor> event_distributor;
3947+};
3948+
3949+struct MockCallback
3950+{
3951+ MOCK_METHOD2(call, void(void*, void*));
3952+};
3953+
3954+void mock_callback_func(MirTrustSession* trust_session, void* context)
3955+{
3956+ auto mock_cb = static_cast<MockCallback*>(context);
3957+ mock_cb->call(trust_session, context);
3958+}
3959+
3960+void null_callback_func(MirTrustSession*, void*)
3961+{
3962+}
3963+
3964+ACTION(RunClosure)
3965+{
3966+ arg3->Run();
3967+}
3968+
3969+}
3970+
3971+TEST_F(MirTrustSessionTest, start_trust_session)
3972+{
3973+ using namespace testing;
3974+
3975+ EXPECT_CALL(mock_server,
3976+ start_trust_session(_,_,_,_))
3977+ .WillOnce(RunClosure());
3978+
3979+ MirTrustSession trust_session{
3980+ mock_server,
3981+ event_distributor};
3982+ trust_session.start(__LINE__, null_callback_func, nullptr);
3983+}
3984+
3985+TEST_F(MirTrustSessionTest, stop_trust_session)
3986+{
3987+ using namespace testing;
3988+
3989+ EXPECT_CALL(mock_server,
3990+ stop_trust_session(_,_,_,_))
3991+ .WillOnce(RunClosure());
3992+
3993+ MirTrustSession trust_session{
3994+ mock_server,
3995+ event_distributor};
3996+ trust_session.stop(null_callback_func, nullptr);
3997+}
3998+
3999+TEST_F(MirTrustSessionTest, executes_callback_on_start)
4000+{
4001+ using namespace testing;
4002+
4003+ MockCallback mock_cb;
4004+ EXPECT_CALL(mock_cb, call(_, &mock_cb));
4005+
4006+ MirTrustSession trust_session{
4007+ stub_server,
4008+ event_distributor};
4009+ trust_session.start(__LINE__, mock_callback_func, &mock_cb)->wait_for_all();
4010+}
4011+
4012+TEST_F(MirTrustSessionTest, executes_callback_on_stop)
4013+{
4014+ using namespace testing;
4015+
4016+ MockCallback mock_cb;
4017+ EXPECT_CALL(mock_cb, call(_, &mock_cb));
4018+
4019+ MirTrustSession trust_session{
4020+ stub_server,
4021+ event_distributor};
4022+ trust_session.stop(mock_callback_func, &mock_cb)->wait_for_all();
4023+}
4024+
4025+TEST_F(MirTrustSessionTest, state_change_event_handler_started)
4026+{
4027+ using namespace testing;
4028+
4029+ MirTrustSession trust_session{
4030+ mock_server,
4031+ event_distributor};
4032+ trust_session.register_trust_session_event_callback(&MirTrustSessionTest::trust_session_event, this);
4033+
4034+ EXPECT_CALL(*this, state_updated(mir_trust_session_state_started)).Times(1);
4035+
4036+ MirEvent e;
4037+ e.type = mir_event_type_trust_session_state_change;
4038+ e.trust_session.new_state = mir_trust_session_state_started;
4039+ event_distributor->handle_event(e);
4040+}
4041+
4042+TEST_F(MirTrustSessionTest, state_change_event_handler_stopped)
4043+{
4044+ using namespace testing;
4045+
4046+ MirTrustSession trust_session{
4047+ mock_server,
4048+ event_distributor};
4049+ trust_session.register_trust_session_event_callback(&MirTrustSessionTest::trust_session_event, this);
4050+
4051+ EXPECT_CALL(*this, state_updated(mir_trust_session_state_stopped)).Times(1);
4052+
4053+ MirEvent e;
4054+ e.type = mir_event_type_trust_session_state_change;
4055+ e.trust_session.new_state = mir_trust_session_state_stopped;
4056+ event_distributor->handle_event(e);
4057+}
4058+
4059
4060=== modified file 'tests/unit-tests/frontend/stress_protobuf_communicator.cpp'
4061--- tests/unit-tests/frontend/stress_protobuf_communicator.cpp 2014-03-06 06:05:17 +0000
4062+++ tests/unit-tests/frontend/stress_protobuf_communicator.cpp 2014-05-15 13:19:23 +0000
4063@@ -28,6 +28,7 @@
4064 #include "src/client/connection_surface_map.h"
4065 #include "src/client/display_configuration.h"
4066 #include "src/client/lifecycle_control.h"
4067+#include "src/client/event_distributor.h"
4068 #include "src/client/rpc/null_rpc_report.h"
4069 #include "src/client/rpc/make_rpc_channel.h"
4070 #include "src/client/rpc/mir_basic_rpc_channel.h"
4071@@ -178,7 +179,8 @@
4072 std::make_shared<mir::client::ConnectionSurfaceMap>(),
4073 std::make_shared<mir::client::DisplayConfiguration>(),
4074 rpc_report,
4075- std::make_shared<mir::client::LifecycleControl>())),
4076+ std::make_shared<mir::client::LifecycleControl>(),
4077+ std::make_shared<mir::client::EventDistributor>())),
4078 display_server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
4079 maxwait(timeout_ms),
4080 connect_done_called(false),
4081
4082=== added file 'tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved'
4083--- tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved 1970-01-01 00:00:00 +0000
4084+++ tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved 2014-05-15 13:19:23 +0000
4085@@ -0,0 +1,65 @@
4086+/*
4087+ * Copyright © 2014 Canonical Ltd.
4088+ *
4089+ * This program is free software: you can redistribute it and/or modify
4090+ * it under the terms of the GNU General Public License version 3 as
4091+ * published by the Free Software Foundation.
4092+ *
4093+ * This program is distributed in the hope that it will be useful,
4094+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4095+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4096+ * GNU General Public License for more details.
4097+ *
4098+ * You should have received a copy of the GNU General Public License
4099+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4100+ *
4101+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
4102+ */
4103+
4104+#include "src/platform/graphics/mesa/display_helpers.h"
4105+#include "mir/udev/wrapper.h"
4106+
4107+#include "mir_test_framework/udev_environment.h"
4108+#include "mir_test_doubles/mock_drm.h"
4109+
4110+#include <fcntl.h>
4111+
4112+#include <gtest/gtest.h>
4113+#include <gmock/gmock.h>
4114+
4115+namespace mgm = mir::graphics::mesa;
4116+namespace mtf = mir::mir_test_framework;
4117+namespace mtd = mir::test::doubles;
4118+
4119+namespace
4120+{
4121+
4122+MATCHER_P(FlagSet, flag, "")
4123+{
4124+ return (arg & flag);
4125+}
4126+
4127+class DRMHelperTest : public ::testing::Test
4128+{
4129+public:
4130+ DRMHelperTest()
4131+ {
4132+ fake_devices.add_standard_device("standard-drm-devices");
4133+ }
4134+
4135+protected:
4136+ ::testing::NiceMock<mtd::MockDRM> mock_drm;
4137+ mtf::UdevEnvironment fake_devices;
4138+};
4139+
4140+}
4141+
4142+TEST_F(DRMHelperTest, closes_drm_fd_on_exec)
4143+{
4144+ using namespace testing;
4145+
4146+ EXPECT_CALL(mock_drm, open(_, FlagSet(O_CLOEXEC), _));
4147+
4148+ mgm::helpers::DRMHelper drm_helper;
4149+ drm_helper.setup(std::make_shared<mir::udev::Context>());
4150+}
4151
4152=== modified file 'tests/unit-tests/scene/CMakeLists.txt'
4153--- tests/unit-tests/scene/CMakeLists.txt 2014-05-06 06:16:13 +0000
4154+++ tests/unit-tests/scene/CMakeLists.txt 2014-05-15 13:19:23 +0000
4155@@ -9,6 +9,8 @@
4156 ${CMAKE_CURRENT_SOURCE_DIR}/test_the_session_container_implementation.cpp
4157 ${CMAKE_CURRENT_SOURCE_DIR}/test_threaded_snapshot_strategy.cpp
4158 ${CMAKE_CURRENT_SOURCE_DIR}/test_mediating_display_changer.cpp
4159+ ${CMAKE_CURRENT_SOURCE_DIR}/test_trust_session.cpp
4160+ ${CMAKE_CURRENT_SOURCE_DIR}/test_trust_session_container.cpp
4161
4162 ${CMAKE_CURRENT_SOURCE_DIR}/test_surface.cpp
4163 ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_impl.cpp
4164
4165=== modified file 'tests/unit-tests/scene/test_application_session.cpp'
4166--- tests/unit-tests/scene/test_application_session.cpp 2014-04-15 10:19:19 +0000
4167+++ tests/unit-tests/scene/test_application_session.cpp 2014-05-15 13:19:23 +0000
4168@@ -27,6 +27,7 @@
4169 #include "mir_test_doubles/stub_display_configuration.h"
4170 #include "mir_test_doubles/null_snapshot_strategy.h"
4171 #include "mir_test_doubles/null_event_sink.h"
4172+#include "mir_test_doubles/null_trust_session.h"
4173
4174 #include <gmock/gmock.h>
4175 #include <gtest/gtest.h>
4176@@ -70,6 +71,10 @@
4177 arg.stride == mir::geometry::Stride{} &&
4178 arg.pixels == nullptr;
4179 }
4180+
4181+MATCHER_P(EqTrustedEventState, state, "") {
4182+ return arg.type == mir_event_type_trust_session_state_change && arg.trust_session.new_state == state;
4183+}
4184 }
4185
4186 TEST(ApplicationSession, create_and_destroy_surface)
4187@@ -380,3 +385,43 @@
4188
4189 EXPECT_THAT(app_session.process_id(), Eq(pid));
4190 }
4191+
4192+TEST(ApplicationSession, begin_trust_session)
4193+{
4194+ using namespace ::testing;
4195+
4196+ mtd::MockSurfaceCoordinator surface_coordinator;
4197+ MockEventSink sender;
4198+
4199+ ms::ApplicationSession app_session(
4200+ mt::fake_shared(surface_coordinator),
4201+ __LINE__,
4202+ "Foo",
4203+ std::make_shared<mtd::NullSnapshotStrategy>(),
4204+ std::make_shared<ms::NullSessionListener>(),
4205+ mt::fake_shared(sender));
4206+
4207+ EXPECT_CALL(sender, handle_event(EqTrustedEventState(mir_trust_session_state_started))).Times(1);
4208+
4209+ app_session.begin_trust_session();
4210+}
4211+
4212+TEST(ApplicationSession, end_trust_session)
4213+{
4214+ using namespace ::testing;
4215+
4216+ mtd::MockSurfaceCoordinator surface_coordinator;
4217+ MockEventSink sender;
4218+
4219+ ms::ApplicationSession app_session(
4220+ mt::fake_shared(surface_coordinator),
4221+ __LINE__,
4222+ "Foo",
4223+ std::make_shared<mtd::NullSnapshotStrategy>(),
4224+ std::make_shared<ms::NullSessionListener>(),
4225+ mt::fake_shared(sender));
4226+
4227+ EXPECT_CALL(sender, handle_event(EqTrustedEventState(mir_trust_session_state_stopped))).Times(1);
4228+
4229+ app_session.end_trust_session();
4230+}
4231
4232=== modified file 'tests/unit-tests/scene/test_session_manager.cpp'
4233--- tests/unit-tests/scene/test_session_manager.cpp 2014-04-15 10:19:19 +0000
4234+++ tests/unit-tests/scene/test_session_manager.cpp 2014-05-15 13:19:23 +0000
4235@@ -27,6 +27,9 @@
4236 #include "src/server/scene/session_event_sink.h"
4237 #include "src/server/scene/basic_surface.h"
4238 #include "src/server/report/null_report_factory.h"
4239+#include "mir/scene/trust_session_creation_parameters.h"
4240+#include "mir/scene/null_trust_session_listener.h"
4241+#include "mir/scene/trust_session.h"
4242
4243 #include "mir_test/fake_shared.h"
4244 #include "mir_test_doubles/mock_buffer_stream.h"
4245@@ -37,6 +40,8 @@
4246 #include "mir_test_doubles/null_snapshot_strategy.h"
4247 #include "mir_test_doubles/null_surface_configurator.h"
4248 #include "mir_test_doubles/null_session_event_sink.h"
4249+#include "mir_test_doubles/mock_trust_session_listener.h"
4250+#include "mir_test_doubles/null_event_sink.h"
4251
4252 #include <gmock/gmock.h>
4253 #include <gtest/gtest.h>
4254@@ -44,7 +49,6 @@
4255 namespace mc = mir::compositor;
4256 namespace mf = mir::frontend;
4257 namespace mi = mir::input;
4258-namespace msh = mir::shell;
4259 namespace ms = mir::scene;
4260 namespace geom = mir::geometry;
4261 namespace mt = mir::test;
4262@@ -78,7 +82,8 @@
4263 mt::fake_shared(focus_setter),
4264 std::make_shared<mtd::NullSnapshotStrategy>(),
4265 std::make_shared<mtd::NullSessionEventSink>(),
4266- mt::fake_shared(session_listener))
4267+ mt::fake_shared(session_listener),
4268+ std::make_shared<ms::NullTrustSessionListener>())
4269 {
4270 using namespace ::testing;
4271 ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
4272@@ -178,7 +183,8 @@
4273 mt::fake_shared(focus_setter),
4274 std::make_shared<mtd::NullSnapshotStrategy>(),
4275 std::make_shared<mtd::NullSessionEventSink>(),
4276- mt::fake_shared(session_listener))
4277+ mt::fake_shared(session_listener),
4278+ std::make_shared<ms::NullTrustSessionListener>())
4279 {
4280 using namespace ::testing;
4281 ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
4282@@ -187,7 +193,7 @@
4283 mtd::MockSurfaceCoordinator surface_coordinator;
4284 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
4285 testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
4286- mtd::MockSessionListener session_listener;
4287+ testing::NiceMock<mtd::MockSessionListener> session_listener;
4288
4289 ms::SessionManager session_manager;
4290 };
4291@@ -217,7 +223,8 @@
4292 mt::fake_shared(focus_setter),
4293 std::make_shared<mtd::NullSnapshotStrategy>(),
4294 mt::fake_shared(session_event_sink),
4295- std::make_shared<ms::NullSessionListener>())
4296+ std::make_shared<ms::NullSessionListener>(),
4297+ std::make_shared<ms::NullTrustSessionListener>())
4298 {
4299 using namespace ::testing;
4300 ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
4301@@ -257,3 +264,46 @@
4302 session_manager.close_session(session1);
4303 session_manager.close_session(session);
4304 }
4305+
4306+namespace
4307+{
4308+
4309+struct SessionManagerTrustSessionListenerSetup : public testing::Test
4310+{
4311+ SessionManagerTrustSessionListenerSetup()
4312+ : session_manager(mt::fake_shared(surface_coordinator),
4313+ mt::fake_shared(container),
4314+ mt::fake_shared(focus_setter),
4315+ std::make_shared<mtd::NullSnapshotStrategy>(),
4316+ std::make_shared<mtd::NullSessionEventSink>(),
4317+ std::make_shared<ms::NullSessionListener>(),
4318+ mt::fake_shared(trust_session_listener))
4319+ {
4320+ using namespace ::testing;
4321+ ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
4322+ }
4323+
4324+ mtd::MockSurfaceCoordinator surface_coordinator;
4325+ testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
4326+ testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
4327+ testing::NiceMock<mtd::MockTrustSessionListener> trust_session_listener;
4328+ mtd::NullEventSink event_sink;
4329+
4330+ ms::SessionManager session_manager;
4331+};
4332+}
4333+
4334+TEST_F(SessionManagerTrustSessionListenerSetup, trust_session_listener_is_notified_of_trust_session_start_and_stop)
4335+{
4336+ using namespace ::testing;
4337+
4338+ EXPECT_CALL(trust_session_listener, starting(_)).Times(1);
4339+ EXPECT_CALL(trust_session_listener, stopping(_)).Times(1);
4340+
4341+ auto helper = session_manager.open_session(__LINE__, "XPlane", mt::fake_shared(event_sink));
4342+
4343+ ms::TrustSessionCreationParameters parameters;
4344+
4345+ auto trust_session = session_manager.start_trust_session_for(helper, parameters);
4346+ session_manager.stop_trust_session(trust_session);
4347+}
4348
4349=== added file 'tests/unit-tests/scene/test_trust_session.cpp'
4350--- tests/unit-tests/scene/test_trust_session.cpp 1970-01-01 00:00:00 +0000
4351+++ tests/unit-tests/scene/test_trust_session.cpp 2014-05-15 13:19:23 +0000
4352@@ -0,0 +1,82 @@
4353+/*
4354+ * Copyright © 2014 Canonical Ltd.
4355+ *
4356+ * This program is free software: you can redistribute it and/or modify
4357+ * it under the terms of the GNU General Public License version 3 as
4358+ * published by the Free Software Foundation.
4359+ *
4360+ * This program is distributed in the hope that it will be useful,
4361+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4362+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4363+ * GNU General Public License for more details.
4364+ *
4365+ * You should have received a copy of the GNU General Public License
4366+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4367+ *
4368+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
4369+ */
4370+
4371+#include "mir/frontend/event_sink.h"
4372+#include "mir/scene/trust_session_creation_parameters.h"
4373+#include "src/server/scene/trust_session_impl.h"
4374+#include "mir_test/fake_shared.h"
4375+#include "mir_test_doubles/mock_scene_session.h"
4376+#include "mir_test_doubles/mock_trust_session_listener.h"
4377+
4378+#include <gmock/gmock.h>
4379+#include <gtest/gtest.h>
4380+
4381+namespace mf = mir::frontend;
4382+namespace ms = mir::scene;
4383+namespace mt = mir::test;
4384+namespace mtd = mir::test::doubles;
4385+
4386+
4387+namespace
4388+{
4389+
4390+struct TrustSession : public testing::Test
4391+{
4392+ TrustSession()
4393+ {
4394+ }
4395+
4396+ testing::NiceMock<mtd::MockTrustSessionListener> trust_session_listener;
4397+ testing::NiceMock<mtd::MockSceneSession> trusted_helper;
4398+ testing::NiceMock<mtd::MockSceneSession> trusted_app1;
4399+ testing::NiceMock<mtd::MockSceneSession> trusted_app2;
4400+};
4401+}
4402+
4403+TEST_F(TrustSession, start_and_stop)
4404+{
4405+ using namespace testing;
4406+
4407+ auto shared_helper = mt::fake_shared(trusted_helper);
4408+ std::shared_ptr<ms::Session> shared_app1 = mt::fake_shared(trusted_app1);
4409+ std::shared_ptr<ms::Session> shared_app2 = mt::fake_shared(trusted_app2);
4410+
4411+ ms::TrustSessionImpl trust_session(shared_helper,
4412+ ms::a_trust_session(),
4413+ mt::fake_shared(trust_session_listener));
4414+
4415+ EXPECT_CALL(trusted_helper, begin_trust_session()).Times(1);
4416+ EXPECT_CALL(trusted_helper, end_trust_session()).Times(1);
4417+
4418+ EXPECT_CALL(trusted_app1, begin_trust_session()).Times(0);
4419+ EXPECT_CALL(trusted_app1, end_trust_session()).Times(0);
4420+
4421+ EXPECT_CALL(trusted_app2, begin_trust_session()).Times(0);
4422+ EXPECT_CALL(trusted_app2, end_trust_session()).Times(0);
4423+
4424+ EXPECT_CALL(trust_session_listener, trusted_session_beginning(_, shared_app1)).Times(1);
4425+ EXPECT_CALL(trust_session_listener, trusted_session_beginning(_, shared_app2)).Times(1);
4426+
4427+ EXPECT_CALL(trust_session_listener, trusted_session_ending(_, shared_app1)).Times(1);
4428+ EXPECT_CALL(trust_session_listener, trusted_session_ending(_, shared_app2)).Times(1);
4429+
4430+ trust_session.start();
4431+ trust_session.add_trusted_child(shared_app1);
4432+ trust_session.add_trusted_child(shared_app2);
4433+ trust_session.stop();
4434+}
4435
4436=== added file 'tests/unit-tests/scene/test_trust_session_container.cpp'
4437--- tests/unit-tests/scene/test_trust_session_container.cpp 1970-01-01 00:00:00 +0000
4438+++ tests/unit-tests/scene/test_trust_session_container.cpp 2014-05-15 13:19:23 +0000
4439@@ -0,0 +1,167 @@
4440+/*
4441+ * Copyright © 2014 Canonical Ltd.
4442+ *
4443+ * This program is free software: you can redistribute it and/or modify
4444+ * it under the terms of the GNU General Public License version 3 as
4445+ * published by the Free Software Foundation.
4446+ *
4447+ * This program is distributed in the hope that it will be useful,
4448+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4449+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4450+ * GNU General Public License for more details.
4451+ *
4452+ * You should have received a copy of the GNU General Public License
4453+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4454+ *
4455+ * Authored By: Nick Dedekind <nick.dedekind@canonical.com>
4456+ */
4457+
4458+#include "src/server/scene/trust_session_container.h"
4459+#include "mir_test_doubles/mock_scene_session.h"
4460+#include "mir_test_doubles/null_trust_session.h"
4461+#include "mir_test/fake_shared.h"
4462+
4463+#include <gmock/gmock.h>
4464+#include <gtest/gtest.h>
4465+
4466+namespace ms = mir::scene;
4467+namespace mf = mir::frontend;
4468+namespace mt = mir::test;
4469+namespace mtd = mir::test::doubles;
4470+
4471+
4472+TEST(TrustSessionContainer, test_insert)
4473+{
4474+ using namespace testing;
4475+
4476+ testing::NiceMock<mtd::NullTrustSession> trust_session1;
4477+ testing::NiceMock<mtd::NullTrustSession> trust_session2;
4478+ testing::NiceMock<mtd::NullTrustSession> trust_session3;
4479+
4480+ ms::TrustSessionContainer container;
4481+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session1), 1), true);
4482+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session1), 2), true);
4483+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session1), 3), true);
4484+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session1), 1), false);
4485+
4486+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session2), 2), true);
4487+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session2), 3), true);
4488+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session2), 2), false);
4489+
4490+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session3), 3), true);
4491+ EXPECT_EQ(container.insert(mt::fake_shared(trust_session3), 3), false);
4492+}
4493+
4494+TEST(TrustSessionContainer, for_each_process_for_trust_session)
4495+{
4496+ using namespace testing;
4497+
4498+ testing::NiceMock<mtd::NullTrustSession> trust_session1;
4499+ testing::NiceMock<mtd::NullTrustSession> trust_session2;
4500+ testing::NiceMock<mtd::NullTrustSession> trust_session3;
4501+
4502+ ms::TrustSessionContainer container;
4503+ container.insert(mt::fake_shared(trust_session1), 1);
4504+ container.insert(mt::fake_shared(trust_session1), 2);
4505+ container.insert(mt::fake_shared(trust_session2), 3);
4506+ container.insert(mt::fake_shared(trust_session2), 1);
4507+ container.insert(mt::fake_shared(trust_session3), 2);
4508+ container.insert(mt::fake_shared(trust_session2), 4);
4509+
4510+ std::vector<ms::TrustSessionContainer::ClientProcess> results;
4511+ auto for_each_fn = [&results](ms::TrustSessionContainer::ClientProcess const& process)
4512+ {
4513+ results.push_back(process);
4514+ };
4515+
4516+ container.for_each_process_for_trust_session(mt::fake_shared(trust_session2), for_each_fn);
4517+ EXPECT_THAT(results, ElementsAre(3, 1, 4));
4518+}
4519+
4520+TEST(TrustSessionContainer, for_each_trust_session_for_process)
4521+{
4522+ using namespace testing;
4523+
4524+ testing::NiceMock<mtd::NullTrustSession> trust_session1;
4525+ testing::NiceMock<mtd::NullTrustSession> trust_session2;
4526+ testing::NiceMock<mtd::NullTrustSession> trust_session3;
4527+
4528+ ms::TrustSessionContainer container;
4529+ container.insert(mt::fake_shared(trust_session1), 1);
4530+ container.insert(mt::fake_shared(trust_session1), 2);
4531+ container.insert(mt::fake_shared(trust_session2), 3);
4532+ container.insert(mt::fake_shared(trust_session2), 1);
4533+ container.insert(mt::fake_shared(trust_session3), 2);
4534+ container.insert(mt::fake_shared(trust_session2), 4);
4535+
4536+ std::vector<std::shared_ptr<mf::TrustSession>> results;
4537+ auto for_each_fn = [&results](std::shared_ptr<mf::TrustSession> const& trust_session)
4538+ {
4539+ results.push_back(trust_session);
4540+ };
4541+
4542+ container.for_each_trust_session_for_process(2, for_each_fn);
4543+ EXPECT_THAT(results, ElementsAre(mt::fake_shared(trust_session1), mt::fake_shared(trust_session3)));
4544+}
4545+
4546+TEST(TrustSessionContainer, test_remove_trust_sesion)
4547+{
4548+ using namespace testing;
4549+
4550+ testing::NiceMock<mtd::NullTrustSession> trust_session1;
4551+
4552+ ms::TrustSessionContainer container;
4553+ container.insert(mt::fake_shared(trust_session1), 1);
4554+ container.insert(mt::fake_shared(trust_session1), 2);
4555+ container.insert(mt::fake_shared(trust_session1), 3);
4556+
4557+ int count = 0;
4558+ auto for_each_fn = [&count](ms::TrustSessionContainer::ClientProcess const&)
4559+ {
4560+ count++;
4561+ };
4562+
4563+ container.for_each_process_for_trust_session(mt::fake_shared(trust_session1), for_each_fn);
4564+ EXPECT_EQ(count, 3);
4565+
4566+ container.remove_trust_session(mt::fake_shared(trust_session1));
4567+
4568+ count = 0;
4569+ container.for_each_process_for_trust_session(mt::fake_shared(trust_session1), for_each_fn);
4570+ EXPECT_EQ(count, 0);
4571+}
4572+
4573+TEST(TrustSessionContainer, remove_process)
4574+{
4575+ using namespace testing;
4576+
4577+ testing::NiceMock<mtd::NullTrustSession> trust_session1;
4578+ testing::NiceMock<mtd::NullTrustSession> trust_session2;
4579+ testing::NiceMock<mtd::NullTrustSession> trust_session3;
4580+
4581+ ms::TrustSessionContainer container;
4582+ container.insert(mt::fake_shared(trust_session1), 1);
4583+ container.insert(mt::fake_shared(trust_session1), 2);
4584+
4585+ container.insert(mt::fake_shared(trust_session2), 1);
4586+ container.insert(mt::fake_shared(trust_session2), 3);
4587+
4588+ container.insert(mt::fake_shared(trust_session3), 1);
4589+ container.insert(mt::fake_shared(trust_session3), 4);
4590+
4591+ int count = 0;
4592+ auto for_each_fn = [&count](std::shared_ptr<mf::TrustSession> const&)
4593+ {
4594+ count++;
4595+ };
4596+
4597+ container.for_each_trust_session_for_process(1, for_each_fn);
4598+ EXPECT_EQ(count, 3);
4599+
4600+ container.remove_process(1);
4601+
4602+ count = 0;
4603+ container.for_each_trust_session_for_process(1, for_each_fn);
4604+ EXPECT_EQ(count, 0);
4605+}
4606+

Subscribers

People subscribed via source and target branches