Mir

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

Proposed by Nick Dedekind
Status: Superseded
Proposed branch: lp:~nick-dedekind/mir/trusted_sessions
Merge into: lp:mir
Diff against target: 4768 lines (+3439/-57) (has conflicts)
81 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/connection_context.h (+58/-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 (+40/-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 (+70/-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 (+23/-4)
src/server/frontend/session_mediator.cpp (+133/-0)
src/server/frontend/session_mediator.h (+29/-3)
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 (+187/-0)
src/server/scene/trust_session_impl.h (+74/-0)
src/shared/protobuf/mir_protobuf.proto (+54/-14)
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/acceptance-tests/test_server_shutdown.cpp (+43/-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/frontend/test_session_mediator.cpp (+52/-0)
tests/unit-tests/graphics/mesa/test_drm_helper.cpp.moved (+65/-0)
tests/unit-tests/scene/CMakeLists.txt (+1/-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 (+73/-0)
Text conflict in include/server/mir/frontend/connection_context.h
Text conflict in include/shared/mir_toolkit/client_types.h
Text conflict in src/server/frontend/protobuf_message_processor.cpp
Text conflict in src/server/frontend/session_mediator.cpp
Text conflict in src/server/frontend/session_mediator.h
Text conflict in src/shared/protobuf/mir_protobuf.proto
Text conflict in tests/acceptance-tests/test_server_shutdown.cpp
Text conflict in tests/unit-tests/frontend/test_session_mediator.cpp
To merge this branch: bzr merge lp:~nick-dedekind/mir/trusted_sessions
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis (community) Needs Fixing
Andreas Pokorny (community) Needs Fixing
Review via email: mp+209224@code.launchpad.net

This proposal has been superseded by a proposal from 2014-05-09.

Commit message

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

A mir client is now able to create a relationship between one or more process sessions and itself. This will manifest in the server as the trusted helper (the client using the api) being set as the parent of the trusted sessions. The shell is responsible for determining what this relationship "means", visually.

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 :

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 :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

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 :

(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 :

> 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 :

> (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 :

> > 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 :

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 :

> 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 :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

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 :

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 :

> 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 :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

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 :

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 :
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 :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :
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 :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

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 :

> 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 :

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 :

> > 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 :

> 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 :
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
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

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 :

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 :

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 :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

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 :

Fixed conflicts.

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

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

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(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 :

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 :

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 :
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 :

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 :

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 :

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 :

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 :

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 :

+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 :

+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 :

> 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 :

> 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 :

> 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 :

> +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 :

> +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.

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

Subscribers

People subscribed via source and target branches