Merge lp:~mir-team/mir/trusted_sessions into lp:mir
- trusted_sessions
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | kevin gunn |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1701 |
Proposed branch: | lp:~mir-team/mir/trusted_sessions |
Merge into: | lp:mir |
Diff against target: |
6122 lines (+4349/-363) 87 files modified
examples/CMakeLists.txt (+6/-2) examples/demo-inprocess-surface-client/inprocess_egl_client.cpp (+1/-1) examples/prompt_session.c (+231/-0) include/client/mir_toolkit/mir_connection.h (+0/-20) include/client/mir_toolkit/mir_prompt_session.h (+87/-0) include/server/mir/default_server_configuration.h (+6/-0) include/server/mir/frontend/prompt_session.h (+48/-0) include/server/mir/frontend/session_mediator_report.h (+9/-1) include/server/mir/frontend/shell.h (+10/-0) include/server/mir/scene/null_prompt_session_listener.h (+40/-0) include/server/mir/scene/prompt_session.h (+37/-0) include/server/mir/scene/prompt_session_creation_parameters.h (+36/-0) include/server/mir/scene/prompt_session_listener.h (+52/-0) include/server/mir/scene/prompt_session_manager.h (+110/-0) include/server/mir/scene/session.h (+3/-0) include/server/mir/shell/session_coordinator_wrapper.h (+14/-0) include/shared/mir_toolkit/client_types.h (+28/-2) include/shared/mir_toolkit/common.h (+6/-0) include/shared/mir_toolkit/event.h (+10/-1) include/test/mir_test/test_protobuf_client.h (+17/-0) include/test/mir_test_doubles/mock_prompt_session_listener.h (+48/-0) include/test/mir_test_doubles/mock_scene_session.h (+3/-0) include/test/mir_test_doubles/mock_shell.h (+12/-0) include/test/mir_test_doubles/null_client_event_sink.h (+42/-0) include/test/mir_test_doubles/null_prompt_session.h (+37/-0) include/test/mir_test_doubles/null_prompt_session_manager.h (+82/-0) include/test/mir_test_doubles/stub_scene_session.h (+14/-1) include/test/mir_test_doubles/stub_shell.h (+19/-0) src/client/CMakeLists.txt (+4/-1) src/client/connection_configuration.h (+4/-0) src/client/default_connection_configuration.cpp (+20/-1) src/client/default_connection_configuration.h (+4/-0) src/client/event_distributor.h (+37/-0) src/client/event_handler_register.h (+47/-0) src/client/event_sink.h (+44/-0) src/client/mir_connection.cpp (+9/-36) src/client/mir_connection.h (+5/-8) src/client/mir_connection_api.cpp (+0/-18) src/client/mir_event_distributor.cpp (+56/-0) src/client/mir_event_distributor.h (+43/-0) src/client/mir_prompt_session.cpp (+203/-0) src/client/mir_prompt_session.h (+94/-0) src/client/mir_prompt_session_api.cpp (+118/-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 (+15/-3) src/server/frontend/session_mediator.cpp (+91/-6) src/server/frontend/session_mediator.h (+23/-6) 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 (+2/-0) src/server/scene/application_session.cpp (+21/-0) src/server/scene/application_session.h (+3/-0) src/server/scene/default_configuration.cpp (+15/-1) src/server/scene/prompt_session_container.cpp (+189/-0) src/server/scene/prompt_session_container.h (+158/-0) src/server/scene/prompt_session_manager_impl.cpp (+232/-0) src/server/scene/prompt_session_manager_impl.h (+96/-0) src/server/scene/session_manager.cpp (+47/-3) src/server/scene/session_manager.h (+14/-2) src/server/shell/session_coordinator_wrapper.cpp (+28/-2) src/shared/protobuf/mir_protobuf.proto (+15/-4) tests/acceptance-tests/CMakeLists.txt (+1/-1) tests/acceptance-tests/test_nested_mir.cpp (+3/-0) tests/acceptance-tests/test_prompt_session_client_api.cpp (+421/-0) tests/acceptance-tests/test_trust_session_helper.cpp (+0/-218) 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 (+2/-0) tests/unit-tests/client/test_event_distributor.cpp (+152/-0) tests/unit-tests/client/test_mir_prompt_session.cpp (+233/-0) tests/unit-tests/frontend/stress_protobuf_communicator.cpp (+4/-1) tests/unit-tests/frontend/test_session_mediator.cpp (+4/-4) tests/unit-tests/scene/CMakeLists.txt (+2/-0) tests/unit-tests/scene/test_application_session.cpp (+45/-0) tests/unit-tests/scene/test_prompt_session_container.cpp (+273/-0) tests/unit-tests/scene/test_prompt_session_manager.cpp (+217/-0) tests/unit-tests/scene/test_session_manager.cpp (+12/-5) |
To merge this branch: | bzr merge lp:~mir-team/mir/trusted_sessions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Alan Griffiths | Abstain | ||
Alexandros Frantzis (community) | Approve | ||
Cemil Azizoglu (community) | Approve | ||
Kevin DuBois (community) | Needs Information | ||
Daniel van Vugt | Pending | ||
Review via email: mp+221191@code.launchpad.net |
This proposal supersedes a proposal from 2014-05-28.
Commit message
support for trusted prompt sessions: https:/
Description of the change
support for trusted prompt sessions: https:/
This branch is to try and shepherd code from lp:~nick-dedekind/mir/trusted_sessions towards landing
As a guide to understanding:
A "prompt sessions" is a tag used by a shell to associate the surfaces belonging to one application to another. The use case is to allow, e.g. pickers to embed surfaces into the client UI.
A scene "session" is a grouping of surfaces associated with a Mir connection.
This MP allows scene "sessions" to be associated with a "prompt session" either by the PID (for processes that are already running) or by the socket connection (for processes that have to be started). Each associated "session" will have the role "application", "helper" or "prompt provider"
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
The tests that fail shouldn't have been affected: triggering a rebuild.
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
3072 + typedef enum {
3073 + HelperSession,
3074 + TrustedSession,
3075 + } TrustType;
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1518
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
[ FAILED ] 9 tests, listed below:
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
[ FAILED ] TestClientInput
I still don't see how these tests are broken by this MP (and just on g++/utopic/armhf too!)
But it's Sunday so I'm leaving the tests running (on my trusty laptop) to see if I can reproduce while I go for a walk.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1518
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1519
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1520
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1521
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1523
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
A different (probably unrelated) failure.
[----------] 5 tests from ServerShutdown/
[----------] Global test environment tear-down
[==========] 92 tests from 22 test cases ran. (184934 ms total)
[ PASSED ] 92 tests.
YOU HAVE 11 DISABLED TESTS
==12239==
==12239== HEAP SUMMARY:
==12239== in use at exit: 4,359 bytes in 18 blocks
==12239== total heap usage: 233,099 allocs, 233,081 frees, 12,409,967 bytes allocated
==12239==
==12239== 744 (120 direct, 624 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 17
==12239== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/
==12239== by 0x56FD701: std::_Function_
==12239== by 0x56FDCD6: mir::client:
==12239== by 0x57012CF: std::_Function_
==12239== by 0x56FFE86: mir::client:
==12239== by 0x56E30BC: MirConnection:
==12239== by 0x56E5AE5: (anonymous namespace)
==12239== by 0x56E6484: mir_connect (mir_connection
==12239== by 0x56E64F5: mir_connect_sync (mir_connection
==12239== by 0x682752: mir_test_
==12239== by 0x832042: void testing:
==12239== by 0x8251BD: testing:
==12239==
==12239== LEAK SUMMARY:
==12239== definitely lost: 120 bytes in 1 blocks
==12239== indirectly lost: 624 bytes in 3 blocks
==12239== possibly lost: 34 bytes in 1 blocks
==12239== still reachable: 3,581 bytes in 13 blocks
==12239== suppressed: 0 bytes in 0 blocks
==12239== Reachable blocks (those to which a pointer was found) are not shown.
==12239== To see them, rerun with: --leak-check=full --show-
==12239==
==12239== For counts of detected and suppressed errors, rerun with: -v
==12239== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I'm going to resubmit with the pre-req on lp:~alan-griffiths/mir/remove-process-compexity-from-TestClientInput to reduce the diff while I look into this.
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal | # |
First run - not understanding the details completely yet - but here are some nits from the first read:
+ 1163 authored by Alexandros?
+ 1678 , 3314 egyptian style braces
+ 1763 std::string error not used
+ 1764ff why not just call set_state( session.has_error() ? ... )
+ 3160, 3122 style guide
+ 2901 ", "
+ 2991,3012 tsit->second should be easier to
+ 2881 uint?
+ 3294 why the class scope
+ 3495 add_add?
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1523
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
OK, tracked down the leaky test...
$ valgrind bin/mir_
==10781== Memcheck, a memory error detector
==10781== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==10781== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==10781== Command: bin/mir_
==10781==
Running main() from command_
Note: Google Test filter = TrustSessionCli
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TrustSessionCli
[ RUN ] TrustSessionCli
[ OK ] TrustSessionCli
[----------] 1 test from TrustSessionCli
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1168 ms total)
[ PASSED ] 1 test.
==10781==
==10781== HEAP SUMMARY:
==10781== in use at exit: 4,359 bytes in 18 blocks
==10781== total heap usage: 7,096 allocs, 7,078 frees, 454,206 bytes allocated
==10781==
==10781== LEAK SUMMARY:
==10781== definitely lost: 120 bytes in 1 blocks
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal | # |
343 + * \param [in] start_callback The function to be called when the trust session event occurs
s/event_callback/
s/the trusted session event/a trusted session event/ ?
338 + * Create an new trust session
347 +MirWaitHandle *mir_connection
Do we 'create' a new trust session or 'start' it? (also see the last note in this comment).
376 +MirWaitHandle *mir_trust_
377 + pid_t session_pid,
378 + mir_trust_
379 + void* context);
... and in other functions
Inconsistent '*' placement (void* vs MirTrustSession *trust_session).
379 + void* context);
Missing \param.
374 + * \return A MirTrustSession
Erroneous comment: function returns MirWaitHandle*
385 + * \return A MirTrustSession
Erroneous comment: function returns MirBool
390 +/**
391 + * Request the cancellation of a trust session
392 + * \param [in] trust_session The trust session
393 + * \return True if the request was made successfully,
394 + * false otherwise
395 + */
Missing \params, erroneous \return.
417 +void mir_trust_
Why do we have 'release' as a separate step from 'stop'? I don't see a way to resume a trust session. I am probably missing some background information, but perhaps we can streamline the interfaces or at least improve the documentation.
We have 'start', 'stop' but also 'release', and no matching 'create'. This violates the principle of least surprise (it surprises me at least!). Perhaps create_and_start()?
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> + 1764ff why not just call set_state( session.has_error() ? ... )
I assume it is to avoid accessing session without a lock.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Just an amber light on this one; Mir 0.2.0 is already way oversized so we should not land something this size until that's out the way.
kevin gunn (kgunn72) wrote : Posted in a previous version of this proposal | # |
> Just an amber light on this one; Mir 0.2.0 is already way oversized so we
> should not land something this size until that's out the way.
wait, if we treat devel as sacred, it shouldn't matter what the delta is. unless there is a verifiable lack of test/validation for this change?
This is a key item on our list for malta & i had requested that we actually hold off on 0.2.0 until we landed this.
kevin gunn (kgunn72) wrote : Posted in a previous version of this proposal | # |
> Just an amber light on this one; Mir 0.2.0 is already way oversized so we
> should not land something this size until that's out the way.
wait, if we treat devel as sacred, it shouldn't matter what the delta is. unless there is a verifiable lack of test/validation for this change?
This is a key item on our list for malta & i had requested that we actually hold off on 0.2.0 until we landed this.
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> Just an amber light on this one; Mir 0.2.0 is already way oversized so we
> should not land something this size until that's out the way.
Getting this reviewed, fixed and landed is a team goal for this week.
If you really feel there is benefit in landing both 0.2.0 and 0.2.1 then I won't argue. But the real problem is that you don't have confidence in our automated testing. Delaying landing this MP won't change that.
Nick Dedekind (nick-dedekind) wrote : Posted in a previous version of this proposal | # |
> 343 + * \param [in] start_callback The function to be called when the trust
> session event occurs
>
> s/event_callback/
> s/the trusted session event/a trusted session event/ ?
>
> 338 + * Create an new trust session
> 347 +MirWaitHandle *mir_connection
> connection,
>
> Do we 'create' a new trust session or 'start' it? (also see the last note in
> this comment).
>
> 376 +MirWaitHandle *mir_trust_
> *trust_session,
> 377 + pid_t session_pid,
> 378 + mir_trust_
> 379 + void* context);
> ... and in other functions
>
> Inconsistent '*' placement (void* vs MirTrustSession *trust_session).
>
> 379 + void* context);
>
> Missing \param.
>
> 374 + * \return A MirTrustSession
>
> Erroneous comment: function returns MirWaitHandle*
>
> 385 + * \return A MirTrustSession
>
> Erroneous comment: function returns MirBool
>
> 390 +/**
> 391 + * Request the cancellation of a trust session
> 392 + * \param [in] trust_session The trust session
> 393 + * \return True if the request was made successfully,
> 394 + * false otherwise
> 395 + */
>
> Missing \params, erroneous \return.
>
> 417 +void mir_trust_
>
> Why do we have 'release' as a separate step from 'stop'? I don't see a way to
> resume a trust session. I am probably missing some background information, but
> perhaps we can streamline the interfaces or at least improve the
> documentation.
>
> We have 'start', 'stop' but also 'release', and no matching 'create'. This
> violates the principle of least surprise (it surprises me at least!). Perhaps
> create_and_start()?
There was a separate create & start, but we removed the create because it was somewhat unnecessary. The reason I left the stop/release as separate methods was that we get asynchronous stop events from the server, so we need to be able to release without sending a stop.
I could change to create_and_start, but the same applies for mir_connect (not mir_create_
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1527
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
Broken tests seem fixed
kevin gunn (kgunn72) wrote : Posted in a previous version of this proposal | # |
> > Just an amber light on this one; Mir 0.2.0 is already way oversized so we
> > should not land something this size until that's out the way.
>
> wait, if we treat devel as sacred, it shouldn't matter what the delta is.
> unless there is a verifiable lack of test/validation for this change?
> This is a key item on our list for malta & i had requested that we actually
> hold off on 0.2.0 until we landed this.
replying to myself - given that we are sacred on devel. we can certainly land 0.2.0 now, and just work to release this as part of 0.2.1 soon after.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1529
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1529
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
CI seems to have mislaid boost on amd64
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> There was a separate create & start, but we removed the create because it was
> somewhat unnecessary. The reason I left the stop/release as separate methods
> was that we get asynchronous stop events from the server, so we need to be
> able to release without sending a stop.
> I could change to create_and_start, but the same applies for mir_connect (not
> mir_create_
[after some f2f discussion]
We can release in the API the object "automatically" after signaling the wait handle returned from the mir_trust_
*s/Needs information/Needs discussion/*
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal | # |
358 + * \param [in] callback Callback function to be invoked when request
359 + * completes
361 + * \param [in] callback The function to be called when the trust session event occurs
Duplicate \param and wrong param name.
615 + NullTrustSessio
616 + virtual ~NullTrustSessi
625 + NullTrustSessio
626 + NullTrustSessio
No need to re-default/
916 +typedef void (*mir_trust_
tps?
1747 +void MirTrustSession
1748 + mir_trust_
1749 + void* context)
1948 + auto trust_session = connection-
1949 + if (event_callback)
1950 + trust_session-
... and similar code
It seems like the callback information should be passed in the constructor of
MirTrustSession (and MirConnection:
1680 + if (handle_
1681 + {
1682 + handle_
1683 + })
We could initialize handler_
so we don't need to check if it is valid.
To be continued...
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> 358 + * \param [in] callback Callback function to be invoked when request
> 359 + * completes
> 361 + * \param [in] callback The function to be called when the trust session
> event occurs
>
> Duplicate \param and wrong param name.
>
> 615 + NullTrustSessio
> 616 + virtual ~NullTrustSessi
> 625 + NullTrustSessio
> 626 + NullTrustSessio
> delete;
>
> No need to re-default/
>
> 916 +typedef void (*mir_trust_
> context);
>
> tps?
fixed
Alan Griffiths (alan-griffiths) wrote : | # |
Resubmitted to remove prerequisite that creates spurious conflicts.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1532
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1533
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
1957 +MirTrustSession* mir_connection_
Not used.
3852 +TEST_F(
It seems like this test would benefit from mocks (instead of checking the
expectations manually).
2592 +void ms::Application
2602 +void ms::Application
It would be nice to keep the terminology consistent (start/stop vs begin/end).
4964 +TEST_F(
... and similar tests
This test and other similar ones are just testing that the function doesn't
throw; they don't validate that a participant has been added. So, we should
either change the names or change the tests.
529 +class EventDistributor
We should avoid depending on concrete classes. Perhaps something like:
class EventHandlerReg
{
virtual void register_
virtual void unregister_
};
class EventSink // perhaps reuse the class from the server?
{
virtual void handle_event(...) = 0;
};
class EventDistributor : public EventHandlerReg
MirTrustSession
MirSocketRpcCha
To be continued...
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1527
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
> 3852 +TEST_F(
>
> It seems like this test would benefit from mocks (instead of checking the
> expectations manually).
Done
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1527
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1534
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nick Dedekind (nick-dedekind) wrote : | # |
> 1957 +MirTrustSession* mir_connection_
> connection)
>
> Not used.
>
> 3852 +TEST_F(
>
> It seems like this test would benefit from mocks (instead of checking the
> expectations manually).
Alan has done this.
>
> 2592 +void ms::Application
> 2602 +void ms::Application
>
> It would be nice to keep the terminology consistent (start/stop vs begin/end).
Changed:
ms::Session:
ms::Session:
ms::TrustSessio
ms::TrustSessio
>
> 4964 +TEST_F(
> ... and similar tests
>
> This test and other similar ones are just testing that the function doesn't
> throw; they don't validate that a participant has been added. So, we should
> either change the names or change the tests.
>
> 529 +class EventDistributor
>
> We should avoid depending on concrete classes. Perhaps something like:
>
> class EventHandlerReg
> {
> virtual void register_
> virtual void unregister_
> };
>
> class EventSink // perhaps reuse the class from the server?
> {
> virtual void handle_event(...) = 0;
>
> };
>
> class EventDistributor : public EventHandlerReg
>
> MirTrustSession
> const&);
> MirSocketRpcCha
>
> To be continued...
Nick Dedekind (nick-dedekind) wrote : | # |
Sorry, mean to say "done with all those :)
ms::Session:
ms::Session:
ms::TrustSessio
ms::TrustSessio
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1537
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1541
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1542
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
How does the trust session app (i.e. child in the example) know that the trusted session is established by the parent? In the example, this is not a problem, because of the sleep(1). If we remove it, things may not work. In general, shouldn't the child have a way to know this?
Nick Dedekind (nick-dedekind) wrote : | # |
The child doesn't know anything about the fact it's running in a trust session. If the child's mir connection is established after the trust session starts, it will be added as a result of:
2852 + trust_session_
I used to call the scene::
Alan Griffiths (alan-griffiths) : | # |
Alan Griffiths (alan-griffiths) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1543
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1544
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
> ms::TrustSessio
> trusted_
> ms::TrustSessio
> trusted_
How about:
s/trusted_
s/trusted_
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1545
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1546
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Kevin DuBois (kdub) wrote : | # |
I took a crack at a review. Forgive me if some of the questions are elementary; I haven't wrapped my head around everything that's going on. I guess needs info is the most appropriate review type.
Could you elaborate a bit more on why trust sessions need to be stopped and started?
Alan Griffiths (alan-griffiths) wrote : | # |
> I took a crack at a review. Forgive me if some of the questions are
> elementary; I haven't wrapped my head around everything that's going on. I
> guess needs info is the most appropriate review type.
I've addressed a lot of the inline comments.
> Could you elaborate a bit more on why trust sessions need to be stopped and
> started?
This was discussed in Malta: Alexandros and I thought the two-phase teardown probably unnecessary, Nick thought there were synchronization issues with the client code when the (unity) server initiated a stop. We haven't reached consensus yet.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1548
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1553
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
1684 + std::lock_
1695 + std::lock_
Are these used to ensure that after returning from unregister() the corresponding handler will not be invoked (i.e. that it can't be in the process of being dispatched currently)?
1714 + for (int id : delete_later_ids)
1715 + event_handlers.
We also need to clear delete_later_ids.
2131 + if (trust_
2132 + mir_wait_
This doesn't look right (if trust session is stopped, then stop it?)
2765 + the_surface_
2766 + the_session_
2767 + the_shell_
...
Not indented properly.
2853 + auto old_focus = focus_applicati
2854 + if (old_focus == scene_session)
2855 + {
2856 + // only reset the focus if this session had focus
2857 + set_focus_
2858 + }
How is this related to the trusted sessions functionality?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1558
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Kevin DuBois (kdub) wrote : | # |
~~~~~
1771 + std::atomic<int> next_fn_id;
1772 + std::unordered_
1773 + std::atomic<bool> in_event;
do these have to be atomic? seems they could just be protected by the mutex. Also would be better to do without the recursive_mutex...
~~~~~
1760 + int register_
1761 + void unregister_
unregister_
1760 + RegisteredHandler register_
and handle the unregistration via RAII?
~~~~
src/client/
seems very close to mf::EventSink, should the interface be shared between client and server?
~~~
Seems strange that we could call 'delete this' in the constructor, depending on ow the event handler register works.
1827 + if (event.
1828 + delete this;
~~~~~~
2257 + // todo - surfaces should register with the event handler register.
TODO
~~~~
I'm not really sure how the boost containers work... but this doesn't seem right:
3226 + Session* session_fun() const { return session.
Alan Griffiths (alan-griffiths) wrote : | # |
> 2131 + if (trust_
> 2132 + mir_wait_
>
> This doesn't look right (if trust session is stopped, then stop it?)
It isn't right.
But if we had "!=" then we'd hit another problem:
1. The server generates a "mir_event_
1.1 the handler registered in the constructor deletes the MirTrustSession.
2. This typically happens before the call to the server receives its completion message - which is then routed to just deleted MirTrustSession which causes "pure virtual method called".
3. If we got past that then we'd delete the MirTrustSession again in mir_trust_
Basically, this whole stop/release area of code needs fixing.
Alan Griffiths (alan-griffiths) wrote : | # |
> > 2131 + if (trust_
> > 2132 + mir_wait_
> >
> > This doesn't look right (if trust session is stopped, then stop it?)
>
> It isn't right.
>
> But if we had "!=" then we'd hit another problem:
>
> 1. The server generates a "mir_event_
> mir_trust_
> 1.1 the handler registered in the constructor deletes the MirTrustSession.
>
> 2. This typically happens before the call to the server receives its
> completion message - which is then routed to just deleted MirTrustSession
> which causes "pure virtual method called".
>
> 3. If we got past that then we'd delete the MirTrustSession again in
> mir_trust_
>
> Basically, this whole stop/release area of code needs fixing.
Alan Griffiths (alan-griffiths) wrote : | # |
> Seems strange that we could call 'delete this' in the constructor, depending
> on ow the event handler register works.
> 1827 + if (event.
> mir_trust_
> 1828 + delete this;
It is in a lambda created by the constructor - which might be right if it didn't interact so badly with other code.
Alan Griffiths (alan-griffiths) wrote : | # |
> ~~~~~
> 1771 + std::atomic<int> next_fn_id;
> 1772 + std::unordered_
> 1773 + std::atomic<bool> in_event;
>
> do these have to be atomic? seems they could just be protected by the mutex.
They not only could, they already are. On our target architectures the generated code should be identical, so this is just needless verbosity.
I'll push an update.
> Also would be better to do without the recursive_mutex...
I told Nick this before he pushed it. ;)
The problem is that the "stopped" event handler can delete the MirTrustSession - which then unregisters the event handler. (As this is the one handler we can be sure that won't be encountered again during the iteration I'm not sure of the benefits of delete_later_ids vs "thou shalt not unregister other event handlers when processing events".)
*Needs Discussion* on this last point
Alan Griffiths (alan-griffiths) wrote : | # |
> > Also would be better to do without the recursive_mutex...
...
> *Needs Discussion* on this last point
Nevermind, found a simple solution
Alan Griffiths (alan-griffiths) wrote : | # |
> > > Also would be better to do without the recursive_mutex...
> ...
> > *Needs Discussion* on this last point
>
> Nevermind, found a simple solution
Oh rats! That doesn't work
Alan Griffiths (alan-griffiths) wrote : | # |
> > ~~~~~
> > 1771 + std::atomic<int> next_fn_id;
> > 1772 + std::unordered_
> > 1773 + std::atomic<bool> in_event;
> >
> > do these have to be atomic? seems they could just be protected by the mutex.
>
> They not only could, they already are. On our target architectures the
> generated code should be identical, so this is just needless verbosity.
>
> I'll push an update.
>
> > Also would be better to do without the recursive_mutex...
>
> I told Nick this before he pushed it. ;)
>
> The problem is that the "stopped" event handler can delete the MirTrustSession
> - which then unregisters the event handler. (As this is the one handler we can
> be sure that won't be encountered again during the iteration I'm not sure of
> the benefits of delete_later_ids vs "thou shalt not unregister other event
> handlers when processing events".)
>
> *Needs Discussion* on this last point
The tricky part is that with a single lock there can be an unregister() call after the "unlock()" in handle_event(). But after unregister() returns the client justifiably expects there to be no further callbacks.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1561
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1565
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1569
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1573
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1576
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
(Finally I was able to catch back up on this. It's a bit long, so please bear with me.)
First and foremost, it's important for us (the Mir team) to minimize the impact of ABI/API breaks for obvious reasons. So we shall try to get it as close to right as possible the first time. I'm sure there will be inevitable iterations, but we need to make a conscious effort to minimize breaks. From that perspective, the focus is still on defining an API that captures the minimum requirements for the primary trusted sessions use-case, while leaving open the possibility to a more generalized usage.
That said, here are my thoughts in no particular order :
- The phrase "trusted session" probably makes sense when considering the primary use-case where the normal flow of an application is interrupted with a prompt to get a user to confirm her intent. In Mir, being lower on the stack and unaware of the use-case details, I am not convinced "trusted" is the best choice for this name, as there may be (non-security related use-) cases where surfaces originating from different connections would be considered belonging to the same "logical" mir connection for focus and LC purposes. Perhaps, SuperSession, SessionClique, SessionGroup, etc might work better. (I'll continue calling it "trusted session" until we converge on a name.)
- In the primary use-case mentioned above, the TPP's surface(s) would have to be always on top to prevent the app from proceeding without user's confirmation. In general, should the order of surfaces in aggregate and focus policy be selectable? For example, we could have an enum (say, ALWAYS_ON_TOP) passed into mir_connection_
- For the primary use-case, it makes sense for a third process (in this case, the trusted helper) to request a trusted session be created on behalf of another process. From Mir's perspective, in a more general sense, the process making the request may at times be starting a trusted session for its own use. Api-wise, the pid passed into mir_connection_
- In general, how does Mir stop malicious applications from pretending to be trusted helpers and trying to establish a "trusted" session with just any process?
- mir_trust_
- Assuming the FD method is kept, we should call it something like : mir_trust_
Alan Griffiths (alan-griffiths) wrote : | # |
> (Finally I was able to catch back up on this. It's a bit long, so please bear
> with me.)
>
> First and foremost, it's important for us (the Mir team) to minimize the
> impact of ABI/API breaks for obvious reasons. So we shall try to get it as
> close to right as possible the first time. I'm sure there will be inevitable
> iterations, but we need to make a conscious effort to minimize breaks. From
> that perspective, the focus is still on defining an API that captures the
> minimum requirements for the primary trusted sessions use-case, while leaving
> open the possibility to a more generalized usage.
>
> That said, here are my thoughts in no particular order :
>
> - The phrase "trusted session" probably makes sense when considering the
> primary use-case where the normal flow of an application is interrupted with a
> prompt to get a user to confirm her intent. In Mir, being lower on the stack
> and unaware of the use-case details, I am not convinced "trusted" is the best
> choice for this name, as there may be (non-security related use-) cases where
> surfaces originating from different connections would be considered belonging
> to the same "logical" mir connection for focus and LC purposes. Perhaps,
> SuperSession, SessionClique, SessionGroup, etc might work better. (I'll
> continue calling it "trusted session" until we converge on a name.)
Once you've been reading the code a bit it becomes clear that there is a fine distinction between "trust session" and "trusted session".
A "trust session" is what https:/
This usage isn't consistent: some of the code uses "participant" for "application or trust prompt provider"; and, this branch name should be "trust_sessions" not "trusted _sessions".
> - In the primary use-case mentioned above, the TPP's surface(s) would have to
> be always on top to prevent the app from proceeding without user's
> confirmation. In general, should the order of surfaces in aggregate and focus
> policy be selectable? For example, we could have an enum (say, ALWAYS_ON_TOP)
> passed into mir_connection_
> add more when the need arises.
>
> - For the primary use-case, it makes sense for a third process (in this case,
> the trusted helper) to request a trusted session be created on behalf of
> another process. From Mir's perspective, in a more general sense, the process
> making the request may at times be starting a trusted session for its own use.
> Api-wise, the pid passed into mir_connection_
> the pid of the process making the call. As in the examples/
> this should work, so no problem there.
>
> - In general, how does Mir stop malicious applications from pretending to be
> trusted helpers and trying to establish a "trusted" session with just any
> process?
>
> - mir_trust_
> this was invented in the first place. In general, I don'...
Thomas Voß (thomas-voss) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1580
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
The new names make things a lot clearer.
~~~~
410 +/**
411 + * Return the state of prompt session
412 + * \param [in] prompt_session The prompt session
413 + * \return The state of the prompt session
414 + */
415 +MirPromptSessi
Is there a need for this function? The client registers an event handler to process state changes, why would it need this as well?
~~~~
815 + virtual std::shared_
816 +
817 + virtual std::shared_
818 +
819 + virtual void for_each_
820 + std::function<
821 +
The names for these functions are verbose - I don't think they need the "_prompt_session" suffix as the argument supplied ought to make the meaning clear.
Also they are not used in the acceptance tests - which should be delineating the functionality Mir needs to provide. I.e. either there are missing tests or these functions are not needed.
~~~~
370 +MirPromptSession *mir_connection
371 + pid_t application_pid,
372 + mir_prompt_
373 + void *context);
Better as "create" to match the "release"
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Still reviewing... I still see "trusted" in a few places :
87 +///\page prompt_session.c prompt_session.c: A mir client which starts a prompt session and trusted client app.
126 + printf("Trust Session state updated to %d\n", state);
192 + printf("helper: added trusted session pid: %d\n", child_pid);
206 + puts("helper: Trusted session stoped by server");
279 + // This simulates the helper starting a new application which it adds to the trusted session.
Alan Griffiths (alan-griffiths) wrote : | # |
> Still reviewing... I still see "trusted" in a few places :
>
> 87 +///\page prompt_session.c prompt_session.c: A mir client which starts
> a prompt session and trusted client app.
> 126 + printf("Trust Session state updated to %d\n", state);
> 192 + printf("helper: added trusted session pid: %d\n", child_pid);
> 206 + puts("helper: Trusted session stoped by server");
> 279 + // This simulates the helper starting a new application which it
> adds to the trusted session.
Seems to be just the example .c file. Note also "s/stoped/stopped/
Alan Griffiths (alan-griffiths) wrote : | # |
70 +#define _POSIX_SOURCE
Not needed
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1584
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1589
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
A bunch of comments inlined. After going through it, I have yet to understand what this has to do with Mir. Mir definitely can support it but this functionality doesn't really interact much with other parts of Mir, or conversely, (other parts of) Mir doesn't really depend on it. Hopefully I'm missing something.
Cemil Azizoglu (cemil-azizoglu) : | # |
Nick Dedekind (nick-dedekind) wrote : | # |
> 70 +#define _POSIX_SOURCE
>
> Not needed
kill() seems to require this.
Alan Griffiths (alan-griffiths) wrote : | # |
I hate diff comments in their current form. Too much scrolling to find them.
Nick Dedekind (nick-dedekind) wrote : | # |
Commented on one's that need commenting on. Fixed others.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1596
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
478 +#include "mir_toolkit/
479 +
480 +#include <sys/types.h>
481 +#include <vector>
482 +#include <string>
483 +#include <memory>
Not needed.
1307 + return std::shared_
Indentation.
1895 + std::unique_
1904 + std::unique_
1911 + std::unique_
No need for (the more expensive) std::unique_lock<>. std::lock_guard<> is sufficient.
1913 + auto const event_handlers_
1917 + // Ensure handler wasn't unregistered since making copy
1918 + if (event_
With the current state of the code (handler called under lock) we don't have to worry about "event_handlers" changing beneath our feet, so neither the copy nor the unregistration check is needed. I presume that the pros and cons of calling the handler under lock have been considered and we have explicitly decided to go with the current approach (I have probably missed some of the discussion around this).
Alan Griffiths (alan-griffiths) wrote : | # |
> 1913 + auto const event_handlers_
> 1917 + // Ensure handler wasn't unregistered since making copy
> 1918 + if (event_
>
> With the current state of the code (handler called under lock) we don't have
> to worry about "event_handlers" changing beneath our feet, so neither the copy
> nor the unregistration check is needed. I presume that the pros and cons of
> calling the handler under lock have been considered and we have explicitly
> decided to go with the current approach (I have probably missed some of the
> discussion around this).
It is a *recursive* mutex so a handler can deregister itself - but it *could* make other changes.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1597
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
> It is a *recursive* mutex so a handler can deregister itself - but it *could* make other changes.
Right, I forgot that we had a recursive mutex (and using decltype didn't help reminding me).
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1598
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
> I hate diff comments in their current form. Too much scrolling to find them.
The "Needs fixing" was accidental
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1599
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
> I'm not really sure how the boost containers work... but this doesn't seem
> right:
> 3226 + Session* session_fun() const { return session.
It doesn't seem right to me either.
Using the referent of a weak pointer as a key is going to lead to undefined behavior when the key changes. (I'm not sure why the weak pointer isn't used directly which would avoid problems.)
Alan Griffiths (alan-griffiths) wrote : | # |
> > I'm not really sure how the boost containers work... but this doesn't seem
> > right:
> > 3226 + Session* session_fun() const { return session.
>
> It doesn't seem right to me either.
>
> Using the referent of a weak pointer as a key is going to lead to undefined
> behavior when the key changes. (I'm not sure why the weak pointer isn't used
> directly which would avoid problems.)
Oops! I thought I'd voted for fixing.
Alexandros Frantzis (afrantzis) wrote : | # |
I am OK with this as a first take on prompt/trust/? sessions. The size of the MP means that it is likely that we missed something, but we can keep refactoring as the requirements crystallize.
Alan Griffiths (alan-griffiths) wrote : | # |
> > > I'm not really sure how the boost containers work... but this doesn't seem
> > > right:
> > > 3226 + Session* session_fun() const { return session.
> >
> > It doesn't seem right to me either.
> >
> > Using the referent of a weak pointer as a key is going to lead to undefined
> > behavior when the key changes. (I'm not sure why the weak pointer isn't used
> > directly which would avoid problems.)
>
> Oops! I thought I'd voted for fixing.
And fixed
Alan Griffiths (alan-griffiths) wrote : | # |
Hmm! There should be acceptance tests that use fds for prompt providers.
(I won't block as I don't mind adding those in a followup MP.)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1600
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1601
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
kevin gunn (kgunn72) wrote : | # |
re-top-
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'examples/CMakeLists.txt' |
2 | --- examples/CMakeLists.txt 2014-06-02 17:07:02 +0000 |
3 | +++ examples/CMakeLists.txt 2014-06-16 15:01:17 +0000 |
4 | @@ -92,6 +92,9 @@ |
5 | |
6 | ) |
7 | |
8 | +add_executable(mir_demo_client_prompt_session prompt_session.c) |
9 | +target_link_libraries(mir_demo_client_prompt_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_prompt_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-06-16 15:01:17 +0000 |
38 | @@ -102,7 +102,7 @@ |
39 | |
40 | auto input_platform = mircv::InputPlatform::create(); |
41 | input_thread = input_platform->create_input_thread( |
42 | - surface->client_input_fd(), |
43 | + surface->client_input_fd(), |
44 | std::bind(std::mem_fn(&me::InprocessEGLClient::handle_event), this, std::placeholders::_1)); |
45 | input_thread->start(); |
46 | |
47 | |
48 | === added file 'examples/prompt_session.c' |
49 | --- examples/prompt_session.c 1970-01-01 00:00:00 +0000 |
50 | +++ examples/prompt_session.c 2014-06-16 15:01:17 +0000 |
51 | @@ -0,0 +1,231 @@ |
52 | +/* |
53 | + * Copyright © 2014 Canonical Ltd. |
54 | + * |
55 | + * This program is free software: you can redistribute it and/or modify |
56 | + * it under the terms of the GNU General Public License version 3 as |
57 | + * published by the Free Software Foundation. |
58 | + * |
59 | + * This program is distributed in the hope that it will be useful, |
60 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
61 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
62 | + * GNU General Public License for more details. |
63 | + * |
64 | + * You should have received a copy of the GNU General Public License |
65 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
66 | + * |
67 | + * Authored by: Nick Dedekind <nick.dedekind <nick.dedekind@canonical.com> |
68 | + */ |
69 | + |
70 | +#define _POSIX_SOURCE |
71 | + |
72 | +#include "mir_toolkit/mir_client_library.h" |
73 | +#include "mir_toolkit/mir_prompt_session.h" |
74 | + |
75 | +#undef NDEBUG |
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 prompt_session.c prompt_session.c: A mir client which starts a prompt session and prompt client app. |
88 | +/// mir_demo_client_prompt_session shows the use of mir prompt session API. |
89 | +/// This program opens a mir connection and creates a prompt session. |
90 | +///\section helper helper() |
91 | +/// Opens a mir connection and creates a prompt session |
92 | +/// before closing the prompt session and connection. |
93 | +///\section prompt_session_app prompt_session_app() |
94 | +/// Opens a mir connection and creates a surface |
95 | +/// before releasing the surface and closing the connection. |
96 | +///\example prompt_session.c A mir client demonstrating prompt sessions. |
97 | +///\section MirDemoState MirDemoState |
98 | +/// The handles needs to be accessible both to callbacks and to the control function. |
99 | +///\snippet prompt_session.c MirDemoState_tag |
100 | +///\section Callbacks Callbacks |
101 | +///\snippet prompt_session.c Callback_tag |
102 | +/// This program creates two processes, both opening a mir connection, one starting |
103 | +/// a prompt 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 | + MirPromptSession *prompt_session; |
112 | + pid_t child_pid; |
113 | + MirPromptSessionState state; |
114 | + |
115 | + int* client_fds; |
116 | + unsigned int client_fd_count; |
117 | +} MirDemoState; |
118 | +///\internal [MirDemoState_tag] |
119 | + |
120 | + |
121 | +///\internal [Callback_tag] |
122 | +// Callback to update MirDemoState on prompt_session_event |
123 | +static void prompt_session_event_callback(MirPromptSession* prompt_session, |
124 | + MirPromptSessionState state, |
125 | + void* context) |
126 | +{ |
127 | + (void)prompt_session; |
128 | + MirDemoState* demo_state = (MirDemoState*)context; |
129 | + demo_state->state = state; |
130 | + |
131 | + printf("helper: Prompt Session state updated to %d\n", state); |
132 | + if (state == mir_prompt_session_state_stopped) |
133 | + { |
134 | + kill(demo_state->child_pid, SIGINT); |
135 | + } |
136 | +} |
137 | + |
138 | +static void client_fd_callback(MirPromptSession* prompt_session, size_t count, int const* fds, void* context) |
139 | +{ |
140 | + (void)prompt_session; |
141 | + ((MirDemoState*)context)->client_fds = malloc(sizeof(int)*count); |
142 | + unsigned int i = 0; |
143 | + for (; i < count; i++) |
144 | + { |
145 | + ((MirDemoState*)context)->client_fds[i] = fds[i]; |
146 | + } |
147 | + ((MirDemoState*)context)->client_fd_count = count; |
148 | +} |
149 | +///\internal [Callback_tag] |
150 | + |
151 | +void start_session(const char* server, const char* name, MirDemoState* mcd) |
152 | +{ |
153 | + // Call mir_connect synchronously |
154 | + mcd->connection = mir_connect_sync(server, name); |
155 | + |
156 | + // We expect a connection handle; |
157 | + // we expect it to be valid; and, |
158 | + // we don't expect an error description |
159 | + assert(mcd->connection != NULL); |
160 | + assert(mir_connection_is_valid(mcd->connection)); |
161 | + assert(strcmp(mir_connection_get_error_message(mcd->connection), "") == 0); |
162 | + printf("%s: Connected\n", name); |
163 | + |
164 | + // We can query information about the platform we're running on |
165 | + { |
166 | + MirPlatformPackage platform_package; |
167 | + platform_package.data_items = -1; |
168 | + platform_package.fd_items = -1; |
169 | + |
170 | + mir_connection_get_platform(mcd->connection, &platform_package); |
171 | + assert(0 <= platform_package.data_items); |
172 | + assert(0 <= platform_package.fd_items); |
173 | + } |
174 | +} |
175 | + |
176 | +void stop_session(MirDemoState* mcd, const char* name) |
177 | +{ |
178 | + if (mcd->surface) |
179 | + { |
180 | + // We should release our surface |
181 | + mir_surface_release_sync(mcd->surface); |
182 | + mcd->surface = 0; |
183 | + printf("%s: Surface released\n", name); |
184 | + } |
185 | + |
186 | + // We should release our connection |
187 | + mir_connection_release(mcd->connection); |
188 | + printf("%s: Connection released\n", name); |
189 | +} |
190 | + |
191 | +void helper(const char* server) |
192 | +{ |
193 | + MirDemoState mcd; |
194 | + mcd.connection = 0; |
195 | + mcd.surface = 0; |
196 | + mcd.prompt_session = 0; |
197 | + mcd.state = mir_prompt_session_state_stopped; |
198 | + mcd.client_fd_count = 0; |
199 | + start_session(server, "helper", &mcd); |
200 | + |
201 | + // We create a prompt session |
202 | + mcd.prompt_session = mir_connection_create_prompt_session_sync(mcd.connection, getpid(), prompt_session_event_callback, &mcd); |
203 | + assert(mcd.prompt_session != NULL); |
204 | + |
205 | + assert(mcd.state == mir_prompt_session_state_started); |
206 | + puts("helper: Started prompt session"); |
207 | + |
208 | + mir_wait_for(mir_prompt_session_new_fds_for_prompt_providers(mcd.prompt_session, 1, client_fd_callback, &mcd)); |
209 | + assert(mcd.client_fd_count == 1); |
210 | + puts("helper: Added waiting FD"); |
211 | + |
212 | + printf("helper: Starting child application 'mir_demo_client_basic' with fd://%d\n", mcd.client_fds[0]); |
213 | + mcd.child_pid = fork(); |
214 | + |
215 | + if (mcd.child_pid == 0) |
216 | + { |
217 | + char buffer[128] = {0}; |
218 | + sprintf(buffer, "fd://%d", mcd.client_fds[0]); |
219 | + |
220 | + char* args[4]; |
221 | + args[0] = "mir_demo_client_basic"; |
222 | + args[1] = "-m"; |
223 | + args[2] = &buffer[0]; |
224 | + args[3] = NULL; |
225 | + |
226 | + errno = 0; |
227 | + execvp("mir_demo_client_basic", args); |
228 | + return; |
229 | + } |
230 | + |
231 | + int status; |
232 | + printf("helper: Waiting on child application: %d\n", mcd.child_pid); |
233 | + waitpid(mcd.child_pid, &status, 0); |
234 | + |
235 | + if (mcd.state == mir_prompt_session_state_started) |
236 | + { |
237 | + mir_prompt_session_release_sync(mcd.prompt_session); |
238 | + mcd.prompt_session = NULL; |
239 | + puts("helper: Stopped prompt session"); |
240 | + } |
241 | + else |
242 | + { |
243 | + puts("helper: Prompt session stopped by server"); |
244 | + } |
245 | + puts("helper: Done"); |
246 | + |
247 | + stop_session(&mcd, "helper"); |
248 | +} |
249 | + |
250 | +// The main() function deals with parsing arguments and defaults |
251 | +int main(int argc, char* argv[]) |
252 | +{ |
253 | + // Some variables for holding command line options |
254 | + char const *server = NULL; |
255 | + |
256 | + // Parse the command line |
257 | + { |
258 | + int arg; |
259 | + opterr = 0; |
260 | + while ((arg = getopt (argc, argv, "c:hm:")) != -1) |
261 | + { |
262 | + switch (arg) |
263 | + { |
264 | + case 'm': |
265 | + server = optarg; |
266 | + break; |
267 | + |
268 | + case '?': |
269 | + case 'h': |
270 | + default: |
271 | + puts(argv[0]); |
272 | + puts("Usage:"); |
273 | + puts(" -m <Mir server socket>"); |
274 | + puts(" -h: this help text"); |
275 | + return -1; |
276 | + } |
277 | + } |
278 | + } |
279 | + |
280 | + helper(server); |
281 | + return 0; |
282 | +} |
283 | |
284 | === modified file 'include/client/mir_toolkit/mir_connection.h' |
285 | --- include/client/mir_toolkit/mir_connection.h 2014-06-02 17:07:02 +0000 |
286 | +++ include/client/mir_toolkit/mir_connection.h 2014-06-16 15:01:17 +0000 |
287 | @@ -169,26 +169,6 @@ |
288 | MirConnection* connection, MirPixelFormat* formats, |
289 | unsigned const int format_size, unsigned int *num_valid_formats); |
290 | |
291 | -/** |
292 | - * Allocate some FDs for trusted clients to connect on |
293 | - * |
294 | - * Trust session helpers need to allocate connection FDs it will pass to |
295 | - * trusted clients to use when connecting to the server. The server can |
296 | - * then associate them with the trust session. |
297 | - * |
298 | - * \warning This API is tentative until the implementation of trust sessions is complete |
299 | - * \param [in] connection The connection |
300 | - * \param [in] no_of_fds The number of fds to allocate |
301 | - * \param [in] callback Callback invoked when request completes |
302 | - * \param [in,out] context User data passed to the callback function |
303 | - * \return A handle that can be passed to mir_wait_for |
304 | - */ |
305 | -MirWaitHandle* mir_connection_new_fds_for_trusted_clients( |
306 | - MirConnection* connection, |
307 | - unsigned int no_of_fds, |
308 | - mir_client_fd_callback callback, |
309 | - void * context); |
310 | - |
311 | #ifdef __cplusplus |
312 | } |
313 | /**@}*/ |
314 | |
315 | === added file 'include/client/mir_toolkit/mir_prompt_session.h' |
316 | --- include/client/mir_toolkit/mir_prompt_session.h 1970-01-01 00:00:00 +0000 |
317 | +++ include/client/mir_toolkit/mir_prompt_session.h 2014-06-16 15:01:17 +0000 |
318 | @@ -0,0 +1,87 @@ |
319 | +/* |
320 | + * Copyright © 2014 Canonical Ltd. |
321 | + * |
322 | + * This program is free software: you can redistribute it and/or modify it |
323 | + * under the terms of the GNU Lesser General Public License version 3, |
324 | + * as published by the Free Software Foundation. |
325 | + * |
326 | + * This program is distributed in the hope that it will be useful, |
327 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
328 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
329 | + * GNU Lesser General Public License for more details. |
330 | + * |
331 | + * You should have received a copy of the GNU Lesser General Public License |
332 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
333 | + */ |
334 | + |
335 | +#ifndef MIR_TOOLKIT_MIR_PROMPT_SESSION_H_ |
336 | +#define MIR_TOOLKIT_MIR_PROMPT_SESSION_H_ |
337 | + |
338 | +#include "mir_toolkit/mir_client_library.h" |
339 | + |
340 | +#include <sys/types.h> |
341 | + |
342 | +#ifdef __cplusplus |
343 | +/** |
344 | + * \addtogroup mir_toolkit |
345 | + * @{ |
346 | + */ |
347 | +extern "C" { |
348 | +#endif |
349 | + |
350 | +/** |
351 | + * Create and start a new prompt session |
352 | + * \param [in] connection The connection |
353 | + * \param [in] application_pid The process id of the initiating application |
354 | + * \param [in] state_change_callback The function to be called when a prompt session state change occurs |
355 | + * \param [in,out] context User data passed to the callback functions |
356 | + * \return A handle that can be passed to mir_wait_for |
357 | + */ |
358 | +MirPromptSession *mir_connection_create_prompt_session_sync( |
359 | + MirConnection* connection, |
360 | + pid_t application_pid, |
361 | + mir_prompt_session_state_change_callback state_change_callback, |
362 | + void *context); |
363 | + |
364 | +/** |
365 | + * Add a prompt provider process id to the prompt session |
366 | + * \param [in] prompt_session The prompt session |
367 | + * \param [in] provider_pid The process id of the prompt provider to add |
368 | + * \return True if the process id was added, false otherwise |
369 | + */ |
370 | +MirBool mir_prompt_session_add_prompt_provider_sync( |
371 | + MirPromptSession *prompt_session, |
372 | + pid_t provider_pid); |
373 | + |
374 | +/** |
375 | + * Allocate some FDs for prompt providers to connect on |
376 | + * |
377 | + * Prompt helpers need to allocate connection FDs it will pass to |
378 | + * prompt providers to use when connecting to the server. The server can |
379 | + * then associate them with the prompt session. |
380 | + * |
381 | + * \warning This API is tentative until the implementation of prompt sessions is complete |
382 | + * \param [in] prompt_session The prompt session |
383 | + * \param [in] no_of_fds The number of fds to allocate |
384 | + * \param [in] callback Callback invoked when request completes |
385 | + * \param [in,out] context User data passed to the callback function |
386 | + * \return A handle that can be passed to mir_wait_for |
387 | + */ |
388 | +MirWaitHandle* mir_prompt_session_new_fds_for_prompt_providers( |
389 | + MirPromptSession *prompt_session, |
390 | + unsigned int no_of_fds, |
391 | + mir_client_fd_callback callback, |
392 | + void * context); |
393 | + |
394 | +/** |
395 | + * Stop and release the specified prompt session |
396 | + * \param [in] prompt_session The prompt session |
397 | + */ |
398 | +void mir_prompt_session_release_sync(MirPromptSession *prompt_session); |
399 | + |
400 | +#ifdef __cplusplus |
401 | +} |
402 | +/**@}*/ |
403 | +#endif |
404 | + |
405 | +#endif /* MIR_TOOLKIT_MIR_PROMPT_SESSION_H_ */ |
406 | |
407 | === modified file 'include/server/mir/default_server_configuration.h' |
408 | --- include/server/mir/default_server_configuration.h 2014-06-09 17:16:32 +0000 |
409 | +++ include/server/mir/default_server_configuration.h 2014-06-16 15:01:17 +0000 |
410 | @@ -93,6 +93,8 @@ |
411 | class SurfaceStackModel; |
412 | class SurfaceStack; |
413 | class SceneReport; |
414 | +class PromptSessionListener; |
415 | +class PromptSessionManager; |
416 | } |
417 | namespace graphics |
418 | { |
419 | @@ -231,6 +233,8 @@ |
420 | virtual std::shared_ptr<scene::PlacementStrategy> the_placement_strategy(); |
421 | virtual std::shared_ptr<scene::SessionListener> the_session_listener(); |
422 | virtual std::shared_ptr<shell::DisplayLayout> the_shell_display_layout(); |
423 | + virtual std::shared_ptr<scene::PromptSessionListener> the_prompt_session_listener(); |
424 | + virtual std::shared_ptr<scene::PromptSessionManager> the_prompt_session_manager(); |
425 | /** @} */ |
426 | |
427 | /** @name internal scene configuration |
428 | @@ -365,6 +369,8 @@ |
429 | CachedPtr<scene::MediatingDisplayChanger> mediating_display_changer; |
430 | CachedPtr<graphics::GLProgramFactory> gl_program_factory; |
431 | CachedPtr<graphics::GLConfig> gl_config; |
432 | + CachedPtr<scene::PromptSessionListener> prompt_session_listener; |
433 | + CachedPtr<scene::PromptSessionManager> prompt_session_manager; |
434 | CachedPtr<scene::SessionCoordinator> session_coordinator; |
435 | CachedPtr<EmergencyCleanup> emergency_cleanup; |
436 | |
437 | |
438 | === added file 'include/server/mir/frontend/prompt_session.h' |
439 | --- include/server/mir/frontend/prompt_session.h 1970-01-01 00:00:00 +0000 |
440 | +++ include/server/mir/frontend/prompt_session.h 2014-06-16 15:01:17 +0000 |
441 | @@ -0,0 +1,48 @@ |
442 | +/* |
443 | + * Copyright © 2014 Canonical Ltd. |
444 | + * |
445 | + * This program is free software: you can redistribute it and/or modify it |
446 | + * under the terms of the GNU General Public License version 3, |
447 | + * as published by the Free Software Foundation. |
448 | + * |
449 | + * This program is distributed in the hope that it will be useful, |
450 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
451 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
452 | + * GNU General Public License for more details. |
453 | + * |
454 | + * You should have received a copy of the GNU General Public License |
455 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
456 | + * |
457 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
458 | + */ |
459 | + |
460 | +#ifndef MIR_FRONTEND_PROMPT_SESSION_H_ |
461 | +#define MIR_FRONTEND_PROMPT_SESSION_H_ |
462 | + |
463 | +#include "mir_toolkit/common.h" |
464 | + |
465 | +#include <sys/types.h> |
466 | +#include <vector> |
467 | +#include <string> |
468 | +#include <memory> |
469 | + |
470 | +namespace mir |
471 | +{ |
472 | + |
473 | +namespace frontend |
474 | +{ |
475 | +class PromptSession |
476 | +{ |
477 | +public: |
478 | + virtual ~PromptSession() = default; |
479 | + |
480 | +protected: |
481 | + PromptSession() = default; |
482 | + PromptSession(const PromptSession&) = delete; |
483 | + PromptSession& operator=(const PromptSession&) = delete; |
484 | +}; |
485 | + |
486 | +} |
487 | +} |
488 | + |
489 | +#endif // MIR_FRONTEND_PROMPT_SESSION_H_ |
490 | |
491 | === modified file 'include/server/mir/frontend/session_mediator_report.h' |
492 | --- include/server/mir/frontend/session_mediator_report.h 2014-05-12 21:11:05 +0000 |
493 | +++ include/server/mir/frontend/session_mediator_report.h 2014-06-16 15:01:17 +0000 |
494 | @@ -1,5 +1,5 @@ |
495 | /* |
496 | - * Copyright © 2012 Canonical Ltd. |
497 | + * Copyright © 2012-2014 Canonical Ltd. |
498 | * |
499 | * This program is free software: you can redistribute it and/or modify it |
500 | * under the terms of the GNU General Public License version 3, |
501 | @@ -22,6 +22,8 @@ |
502 | |
503 | #include <string> |
504 | |
505 | +#include <sys/types.h> |
506 | + |
507 | namespace mir |
508 | { |
509 | namespace frontend |
510 | @@ -50,6 +52,12 @@ |
511 | |
512 | virtual void session_configure_display_called(std::string const& app_name) = 0; |
513 | |
514 | + virtual void session_start_prompt_session_called(std::string const& app_name, pid_t application_process) = 0; |
515 | + |
516 | + virtual void session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process) = 0; |
517 | + |
518 | + virtual void session_stop_prompt_session_called(std::string const& app_name) = 0; |
519 | + |
520 | virtual void session_error( |
521 | std::string const& app_name, |
522 | char const* method, |
523 | |
524 | === modified file 'include/server/mir/frontend/shell.h' |
525 | --- include/server/mir/frontend/shell.h 2014-04-15 05:31:19 +0000 |
526 | +++ include/server/mir/frontend/shell.h 2014-06-16 15:01:17 +0000 |
527 | @@ -30,11 +30,13 @@ |
528 | namespace scene |
529 | { |
530 | struct SurfaceCreationParameters; |
531 | +struct PromptSessionCreationParameters; |
532 | } |
533 | namespace frontend |
534 | { |
535 | class EventSink; |
536 | class Session; |
537 | +class PromptSession; |
538 | |
539 | class Shell |
540 | { |
541 | @@ -54,6 +56,14 @@ |
542 | |
543 | virtual void handle_surface_created(std::shared_ptr<Session> const& session) = 0; |
544 | |
545 | + virtual std::shared_ptr<PromptSession> start_prompt_session_for(std::shared_ptr<Session> const& session, |
546 | + scene::PromptSessionCreationParameters const& params) = 0; |
547 | + virtual void add_prompt_provider_process_for(std::shared_ptr<PromptSession> const& prompt_session, |
548 | + pid_t process_id) = 0; |
549 | + virtual void add_prompt_provider_for(std::shared_ptr<PromptSession> const& prompt_session, |
550 | + std::shared_ptr<Session> const& session) = 0; |
551 | + virtual void stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) = 0; |
552 | + |
553 | protected: |
554 | Shell() = default; |
555 | Shell(const Shell&) = delete; |
556 | |
557 | === added file 'include/server/mir/scene/null_prompt_session_listener.h' |
558 | --- include/server/mir/scene/null_prompt_session_listener.h 1970-01-01 00:00:00 +0000 |
559 | +++ include/server/mir/scene/null_prompt_session_listener.h 2014-06-16 15:01:17 +0000 |
560 | @@ -0,0 +1,40 @@ |
561 | +/* |
562 | + * Copyright © 2014 Canonical Ltd. |
563 | + * |
564 | + * This program is free software: you can redistribute it and/or modify it |
565 | + * under the terms of the GNU General Public License version 3, |
566 | + * as published by the Free Software Foundation. |
567 | + * |
568 | + * This program is distributed in the hope that it will be useful, |
569 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
570 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
571 | + * GNU General Public License for more details. |
572 | + * |
573 | + * You should have received a copy of the GNU General Public License |
574 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
575 | + * |
576 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
577 | + */ |
578 | + |
579 | +#ifndef MIR_SCENE_NULL_PROMPT_SESSION_LISTENER_H_ |
580 | +#define MIR_SCENE_NULL_PROMPT_SESSION_LISTENER_H_ |
581 | + |
582 | +#include "mir/scene/prompt_session_listener.h" |
583 | + |
584 | +namespace mir |
585 | +{ |
586 | +namespace scene |
587 | +{ |
588 | +class NullPromptSessionListener : public PromptSessionListener |
589 | +{ |
590 | +public: |
591 | + void starting(std::shared_ptr<PromptSession> const&) override {} |
592 | + void stopping(std::shared_ptr<PromptSession> const&) override {} |
593 | + |
594 | + void prompt_provider_added(PromptSession const&, std::shared_ptr<Session> const&) override {} |
595 | + void prompt_provider_removed(PromptSession const&, std::shared_ptr<Session> const&) override {} |
596 | +}; |
597 | +} |
598 | +} |
599 | + |
600 | +#endif // MIR_SHELL_NULL_PROMPT_SESSION_LISTENER_H_ |
601 | |
602 | === added file 'include/server/mir/scene/prompt_session.h' |
603 | --- include/server/mir/scene/prompt_session.h 1970-01-01 00:00:00 +0000 |
604 | +++ include/server/mir/scene/prompt_session.h 2014-06-16 15:01:17 +0000 |
605 | @@ -0,0 +1,37 @@ |
606 | +/* |
607 | + * Copyright © 2014 Canonical Ltd. |
608 | + * |
609 | + * This program is free software: you can redistribute it and/or modify it |
610 | + * under the terms of the GNU General Public License version 3, |
611 | + * as published by the Free Software Foundation. |
612 | + * |
613 | + * This program is distributed in the hope that it will be useful, |
614 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
615 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
616 | + * GNU General Public License for more details. |
617 | + * |
618 | + * You should have received a copy of the GNU General Public License |
619 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
620 | + * |
621 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
622 | + */ |
623 | + |
624 | +#ifndef MIR_SCENE_PROMPT_SESSION_H_ |
625 | +#define MIR_SCENE_PROMPT_SESSION_H_ |
626 | + |
627 | +#include "mir/frontend/prompt_session.h" |
628 | + |
629 | +namespace mir |
630 | +{ |
631 | +namespace scene |
632 | +{ |
633 | +class Session; |
634 | + |
635 | +class PromptSession : public frontend::PromptSession |
636 | +{ |
637 | +}; |
638 | + |
639 | +} |
640 | +} |
641 | + |
642 | +#endif // MIR_SHELL_PROMPT_SESSION_H_ |
643 | |
644 | === added file 'include/server/mir/scene/prompt_session_creation_parameters.h' |
645 | --- include/server/mir/scene/prompt_session_creation_parameters.h 1970-01-01 00:00:00 +0000 |
646 | +++ include/server/mir/scene/prompt_session_creation_parameters.h 2014-06-16 15:01:17 +0000 |
647 | @@ -0,0 +1,36 @@ |
648 | +/* |
649 | + * Copyright © 2014 Canonical Ltd. |
650 | + * |
651 | + * This program is free software: you can redistribute it and/or modify it |
652 | + * under the terms of the GNU General Public License version 3, |
653 | + * as published by the Free Software Foundation. |
654 | + * |
655 | + * This program is distributed in the hope that it will be useful, |
656 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
657 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
658 | + * GNU General Public License for more details. |
659 | + * |
660 | + * You should have received a copy of the GNU General Public License |
661 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
662 | + * |
663 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
664 | + */ |
665 | + |
666 | +#ifndef MIR_SCENE_PROMPT_SESSION_CREATION_PARAMETERS_H_ |
667 | +#define MIR_SCENE_PROMPT_SESSION_CREATION_PARAMETERS_H_ |
668 | + |
669 | +#include <sys/types.h> |
670 | + |
671 | +namespace mir |
672 | +{ |
673 | +namespace scene |
674 | +{ |
675 | + |
676 | +struct PromptSessionCreationParameters |
677 | +{ |
678 | + pid_t application_pid = 0; |
679 | +}; |
680 | +} |
681 | +} |
682 | + |
683 | +#endif /* MIR_SCENE_PROMPT_SESSION_CREATION_PARAMETERS_H_ */ |
684 | |
685 | === added file 'include/server/mir/scene/prompt_session_listener.h' |
686 | --- include/server/mir/scene/prompt_session_listener.h 1970-01-01 00:00:00 +0000 |
687 | +++ include/server/mir/scene/prompt_session_listener.h 2014-06-16 15:01:17 +0000 |
688 | @@ -0,0 +1,52 @@ |
689 | +/* |
690 | + * Copyright © 2014 Canonical Ltd. |
691 | + * |
692 | + * This program is free software: you can redistribute it and/or modify it |
693 | + * under the terms of the GNU General Public License version 3, |
694 | + * as published by the Free Software Foundation. |
695 | + * |
696 | + * This program is distributed in the hope that it will be useful, |
697 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
698 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
699 | + * GNU General Public License for more details. |
700 | + * |
701 | + * You should have received a copy of the GNU General Public License |
702 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
703 | + * |
704 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
705 | + */ |
706 | + |
707 | +#ifndef MIR_SCENE_PROMPT_SESSION_LISTENER_H_ |
708 | +#define MIR_SCENE_PROMPT_SESSION_LISTENER_H_ |
709 | + |
710 | +#include <memory> |
711 | + |
712 | +namespace mir |
713 | +{ |
714 | +namespace scene |
715 | +{ |
716 | +class Session; |
717 | +class PromptSession; |
718 | + |
719 | +class PromptSessionListener |
720 | +{ |
721 | +public: |
722 | + virtual void starting(std::shared_ptr<PromptSession> const& prompt_session) = 0; |
723 | + virtual void stopping(std::shared_ptr<PromptSession> const& prompt_session) = 0; |
724 | + |
725 | + virtual void prompt_provider_added(PromptSession const& prompt_session, std::shared_ptr<Session> const& prompt_provider) = 0; |
726 | + virtual void prompt_provider_removed(PromptSession const& prompt_session, std::shared_ptr<Session> const& prompt_provider) = 0; |
727 | + |
728 | +protected: |
729 | + PromptSessionListener() = default; |
730 | + virtual ~PromptSessionListener() = default; |
731 | + |
732 | + PromptSessionListener(const PromptSessionListener&) = delete; |
733 | + PromptSessionListener& operator=(const PromptSessionListener&) = delete; |
734 | +}; |
735 | + |
736 | +} |
737 | +} |
738 | + |
739 | + |
740 | +#endif // MIR_SCENE_PROMPT_SESSION_LISTENER_H_ |
741 | |
742 | === added file 'include/server/mir/scene/prompt_session_manager.h' |
743 | --- include/server/mir/scene/prompt_session_manager.h 1970-01-01 00:00:00 +0000 |
744 | +++ include/server/mir/scene/prompt_session_manager.h 2014-06-16 15:01:17 +0000 |
745 | @@ -0,0 +1,110 @@ |
746 | +/* |
747 | + * Copyright © 2014 Canonical Ltd. |
748 | + * |
749 | + * This program is free software: you can redistribute it and/or modify it |
750 | + * under the terms of the GNU General Public License version 3, |
751 | + * as published by the Free Software Foundation. |
752 | + * |
753 | + * This program is distributed in the hope that it will be useful, |
754 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
755 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
756 | + * GNU General Public License for more details. |
757 | + * |
758 | + * You should have received a copy of the GNU General Public License |
759 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
760 | + * |
761 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
762 | + */ |
763 | + |
764 | +#ifndef MIR_SCENE_PROMPT_SESSION_MANAGER_H_ |
765 | +#define MIR_SCENE_PROMPT_SESSION_MANAGER_H_ |
766 | + |
767 | +#include <sys/types.h> |
768 | +#include <memory> |
769 | +#include <functional> |
770 | + |
771 | +namespace mir |
772 | +{ |
773 | +namespace scene |
774 | +{ |
775 | +class Session; |
776 | +class PromptSession; |
777 | +struct PromptSessionCreationParameters; |
778 | + |
779 | +class PromptSessionManager |
780 | +{ |
781 | +public: |
782 | + virtual ~PromptSessionManager() = default; |
783 | + |
784 | + /** |
785 | + * Start a new prompt session |
786 | + * \param [in] session The prompt helper session |
787 | + * \param [in] params The creation parameters for constructing the prompt session |
788 | + */ |
789 | + virtual std::shared_ptr<PromptSession> start_prompt_session_for(std::shared_ptr<Session> const& session, |
790 | + PromptSessionCreationParameters const& params) const = 0; |
791 | + |
792 | + /** |
793 | + * Stop a started prompt session |
794 | + * \param [in] prompt_session The prompt session |
795 | + */ |
796 | + virtual void stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) const = 0; |
797 | + |
798 | + /** |
799 | + * Add a prompt provider to an existing prompt session |
800 | + * \param [in] prompt_session The prompt session |
801 | + * \param [in] prompt_provider The prompt provider to add to the prompt session |
802 | + */ |
803 | + virtual void add_prompt_provider(std::shared_ptr<PromptSession> const& prompt_session, |
804 | + std::shared_ptr<Session> const& prompt_provider) const = 0; |
805 | + |
806 | + /** |
807 | + * Add a process id to wait for to the prompt session |
808 | + * \param [in] prompt_session The prompt session |
809 | + * \param [in] process_id The process id to wait for |
810 | + */ |
811 | + virtual void add_prompt_provider_by_pid(std::shared_ptr<PromptSession> const& prompt_session, |
812 | + pid_t process_id) const = 0; |
813 | + |
814 | + /** |
815 | + * Add a session that may have been expected by a prompt session. |
816 | + * \param [in] session The new session that was being expected |
817 | + */ |
818 | + virtual void add_expected_session(std::shared_ptr<Session> const& new_session) const = 0; |
819 | + |
820 | + /** |
821 | + * Remove a session from all associated prompt sessions |
822 | + * \param [in] session The new session that is to be removed |
823 | + */ |
824 | + virtual void remove_session(std::shared_ptr<Session> const& session) const = 0; |
825 | + |
826 | + /** |
827 | + * Retrieve the application session for a prompt session |
828 | + * \param [in] prompt_session The prompt session |
829 | + */ |
830 | + virtual std::shared_ptr<Session> application_for(std::shared_ptr<PromptSession> const& prompt_session) const = 0; |
831 | + |
832 | + /** |
833 | + * Retrieve the helper session for a prompt session |
834 | + * \param [in] prompt_session The prompt session |
835 | + */ |
836 | + virtual std::shared_ptr<Session> helper_for(std::shared_ptr<PromptSession> const& prompt_session) const = 0; |
837 | + |
838 | + /** |
839 | + * Iterate over all the prompt providers associated with a prompt session |
840 | + * \param [in] prompt_session The prompt session |
841 | + * \param [in] f The callback function to call for each provider |
842 | + */ |
843 | + virtual void for_each_provider_in(std::shared_ptr<PromptSession> const& prompt_session, |
844 | + std::function<void(std::shared_ptr<Session> const& prompt_provider)> const& f) const = 0; |
845 | + |
846 | +protected: |
847 | + PromptSessionManager() = default; |
848 | + PromptSessionManager(const PromptSessionManager&) = delete; |
849 | + PromptSessionManager& operator=(const PromptSessionManager&) = delete; |
850 | +}; |
851 | + |
852 | +} |
853 | +} |
854 | + |
855 | +#endif // MIR_SCENE_PROMPT_SESSION_MANAGER_H_ |
856 | |
857 | === modified file 'include/server/mir/scene/session.h' |
858 | --- include/server/mir/scene/session.h 2014-04-15 05:31:19 +0000 |
859 | +++ include/server/mir/scene/session.h 2014-06-16 15:01:17 +0000 |
860 | @@ -40,6 +40,9 @@ |
861 | virtual std::shared_ptr<Surface> default_surface() const = 0; |
862 | virtual void set_lifecycle_state(MirLifecycleState state) = 0; |
863 | virtual void send_display_config(graphics::DisplayConfiguration const&) = 0; |
864 | + |
865 | + virtual void start_prompt_session() = 0; |
866 | + virtual void stop_prompt_session() = 0; |
867 | }; |
868 | } |
869 | } |
870 | |
871 | === modified file 'include/server/mir/shell/session_coordinator_wrapper.h' |
872 | --- include/server/mir/shell/session_coordinator_wrapper.h 2014-05-23 12:59:00 +0000 |
873 | +++ include/server/mir/shell/session_coordinator_wrapper.h 2014-06-16 15:01:17 +0000 |
874 | @@ -48,6 +48,20 @@ |
875 | |
876 | void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override; |
877 | |
878 | + std::shared_ptr<frontend::PromptSession> start_prompt_session_for( |
879 | + std::shared_ptr<frontend::Session> const& session, |
880 | + scene::PromptSessionCreationParameters const& params) override; |
881 | + |
882 | + void add_prompt_provider_process_for( |
883 | + std::shared_ptr<frontend::PromptSession> const& prompt_session, |
884 | + pid_t process_id) override; |
885 | + |
886 | + void add_prompt_provider_for( |
887 | + std::shared_ptr<frontend::PromptSession> const& prompt_session, |
888 | + std::shared_ptr<frontend::Session> const& session) override; |
889 | + |
890 | + void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& prompt_session) override; |
891 | + |
892 | protected: |
893 | std::shared_ptr<scene::SessionCoordinator> const wrapped; |
894 | }; |
895 | |
896 | === modified file 'include/shared/mir_toolkit/client_types.h' |
897 | --- include/shared/mir_toolkit/client_types.h 2014-06-02 17:07:02 +0000 |
898 | +++ include/shared/mir_toolkit/client_types.h 2014-06-16 15:01:17 +0000 |
899 | @@ -46,6 +46,7 @@ |
900 | typedef struct MirConnection MirConnection; |
901 | typedef struct MirSurface MirSurface; |
902 | typedef struct MirScreencast MirScreencast; |
903 | +typedef struct MirPromptSession MirPromptSession; |
904 | |
905 | /** |
906 | * Returned by asynchronous functions. Must not be free'd by |
907 | @@ -105,7 +106,7 @@ |
908 | |
909 | /** |
910 | * Callback called when a request for client file descriptors completes |
911 | - * \param [in] connection The connection associated with the display change |
912 | + * \param [in] prompt_session The prompt session |
913 | * \param [in] count The number of FDs allocated |
914 | * \param [in] fds Array of FDs |
915 | * \param [in,out] context The context provided by client |
916 | @@ -114,7 +115,7 @@ |
917 | */ |
918 | |
919 | typedef void (*mir_client_fd_callback)( |
920 | - MirConnection* connection, size_t count, int const* fds, void* context); |
921 | + MirPromptSession *prompt_session, size_t count, int const* fds, void* context); |
922 | |
923 | /** |
924 | * MirBufferUsage specifies how a surface can and will be used. A "hardware" |
925 | @@ -319,6 +320,31 @@ |
926 | */ |
927 | typedef void (*mir_screencast_callback)(MirScreencast *screencast, void *client_context); |
928 | |
929 | +/** |
930 | + * Callback member of MirPromptSession for handling of prompt sessions. |
931 | + * \param [in] prompt_provider The prompt session associated with the callback |
932 | + * \param [in,out] context The context provided by the client |
933 | + */ |
934 | +typedef void (*mir_prompt_session_callback)(MirPromptSession* prompt_provider, void* context); |
935 | + |
936 | +/** |
937 | + * Callback member of MirPromptSession for adding prompt providers |
938 | + * \param [in] prompt_provider The prompt session associated with the callback |
939 | + * \param [in] added True if the session was added, false otherwise |
940 | + * \param [in,out] context The context provided by the client |
941 | + */ |
942 | +typedef void (*mir_prompt_session_add_prompt_provider_callback)( |
943 | + MirPromptSession* prompt_provider, MirBool added, void* context); |
944 | + |
945 | +/** |
946 | + * Callback member of MirPromptSession for handling of prompt sessions events. |
947 | + * \param [in] prompt_provider The prompt session associated with the callback |
948 | + * \param [in] state The state of the prompt session |
949 | + * \param [in,out] context The context provided by the client |
950 | + */ |
951 | +typedef void (*mir_prompt_session_state_change_callback)( |
952 | + MirPromptSession* prompt_provider, MirPromptSessionState state, void* context); |
953 | + |
954 | #ifdef __cplusplus |
955 | } |
956 | /**@}*/ |
957 | |
958 | === modified file 'include/shared/mir_toolkit/common.h' |
959 | --- include/shared/mir_toolkit/common.h 2014-06-09 17:16:32 +0000 |
960 | +++ include/shared/mir_toolkit/common.h 2014-06-16 15:01:17 +0000 |
961 | @@ -88,6 +88,12 @@ |
962 | mir_power_mode_off /* Powered down. */ |
963 | } MirPowerMode; |
964 | |
965 | +typedef enum MirPromptSessionState |
966 | +{ |
967 | + mir_prompt_session_state_stopped = 0, |
968 | + mir_prompt_session_state_started |
969 | +} MirPromptSessionState; |
970 | + |
971 | /** |
972 | * The order of components in a format enum matches the |
973 | * order of the components as they would be written in an |
974 | |
975 | === modified file 'include/shared/mir_toolkit/event.h' |
976 | --- include/shared/mir_toolkit/event.h 2014-03-06 06:05:17 +0000 |
977 | +++ include/shared/mir_toolkit/event.h 2014-06-16 15:01:17 +0000 |
978 | @@ -40,7 +40,8 @@ |
979 | mir_event_type_key, |
980 | mir_event_type_motion, |
981 | mir_event_type_surface, |
982 | - mir_event_type_resize |
983 | + mir_event_type_resize, |
984 | + mir_event_type_prompt_session_state_change |
985 | } MirEventType; |
986 | |
987 | typedef enum { |
988 | @@ -204,6 +205,13 @@ |
989 | int height; |
990 | } MirResizeEvent; |
991 | |
992 | +typedef struct |
993 | +{ |
994 | + MirEventType type; |
995 | + |
996 | + MirPromptSessionState new_state; |
997 | +} MirPromptSessionEvent; |
998 | + |
999 | typedef union |
1000 | { |
1001 | MirEventType type; |
1002 | @@ -211,6 +219,7 @@ |
1003 | MirMotionEvent motion; |
1004 | MirSurfaceEvent surface; |
1005 | MirResizeEvent resize; |
1006 | + MirPromptSessionEvent prompt_session; |
1007 | } MirEvent; |
1008 | |
1009 | #ifdef __cplusplus |
1010 | |
1011 | === modified file 'include/test/mir_test/test_protobuf_client.h' |
1012 | --- include/test/mir_test/test_protobuf_client.h 2013-08-28 03:41:48 +0000 |
1013 | +++ include/test/mir_test/test_protobuf_client.h 2014-06-16 15:01:17 +0000 |
1014 | @@ -21,6 +21,7 @@ |
1015 | #define MIR_TEST_TEST_CLIENT_H_ |
1016 | |
1017 | #include "mir_protobuf.pb.h" |
1018 | +#include "wait_condition.h" |
1019 | |
1020 | #include <gmock/gmock.h> |
1021 | |
1022 | @@ -49,6 +50,9 @@ |
1023 | mir::protobuf::Connection connection; |
1024 | mir::protobuf::DisplayConfiguration disp_config; |
1025 | mir::protobuf::DisplayConfiguration disp_config_response; |
1026 | + mir::protobuf::PromptSessionParameters prompt_session_parameters; |
1027 | + mir::protobuf::PromptProvider prompt_provider; |
1028 | + mir::protobuf::Void prompt_session; |
1029 | |
1030 | MOCK_METHOD0(connect_done, void()); |
1031 | MOCK_METHOD0(create_surface_done, void()); |
1032 | @@ -57,6 +61,9 @@ |
1033 | MOCK_METHOD0(disconnect_done, void()); |
1034 | MOCK_METHOD0(drm_auth_magic_done, void()); |
1035 | MOCK_METHOD0(display_configure_done, void()); |
1036 | + MOCK_METHOD0(prompt_session_start_done, void()); |
1037 | + MOCK_METHOD0(prompt_session_add_prompt_provider_done, void()); |
1038 | + MOCK_METHOD0(prompt_session_stop_done, void()); |
1039 | |
1040 | void on_connect_done(); |
1041 | |
1042 | @@ -94,6 +101,12 @@ |
1043 | |
1044 | void wait_for_configure_display_done(); |
1045 | |
1046 | + void wait_for_prompt_session_start_done(); |
1047 | + |
1048 | + void wait_for_prompt_session_add_prompt_provider_done(); |
1049 | + |
1050 | + void wait_for_prompt_session_stop_done(); |
1051 | + |
1052 | const int maxwait; |
1053 | std::atomic<bool> connect_done_called; |
1054 | std::atomic<bool> create_surface_called; |
1055 | @@ -104,6 +117,10 @@ |
1056 | std::atomic<bool> configure_display_done_called; |
1057 | std::atomic<bool> tfd_done_called; |
1058 | |
1059 | + WaitCondition wc_prompt_session_start; |
1060 | + WaitCondition wc_prompt_session_add; |
1061 | + WaitCondition wc_prompt_session_stop; |
1062 | + |
1063 | std::atomic<int> connect_done_count; |
1064 | std::atomic<int> create_surface_done_count; |
1065 | std::atomic<int> disconnect_done_count; |
1066 | |
1067 | === added file 'include/test/mir_test_doubles/mock_prompt_session_listener.h' |
1068 | --- include/test/mir_test_doubles/mock_prompt_session_listener.h 1970-01-01 00:00:00 +0000 |
1069 | +++ include/test/mir_test_doubles/mock_prompt_session_listener.h 2014-06-16 15:01:17 +0000 |
1070 | @@ -0,0 +1,48 @@ |
1071 | +/* |
1072 | + * Copyright © 2014 Canonical Ltd. |
1073 | + * |
1074 | + * This program is free software: you can redistribute it and/or modify it |
1075 | + * under the terms of the GNU General Public License version 3, |
1076 | + * as published by the Free Software Foundation. |
1077 | + * |
1078 | + * This program is distributed in the hope that it will be useful, |
1079 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1080 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1081 | + * GNU General Public License for more details. |
1082 | + * |
1083 | + * You should have received a copy of the GNU General Public License |
1084 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1085 | + * |
1086 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
1087 | + */ |
1088 | + |
1089 | +#ifndef MIR_TEST_DOUBLES_MOCK_PROMPT_SESSION_LISTENER_H_ |
1090 | +#define MIR_TEST_DOUBLES_MOCK_PROMPT_SESSION_LISTENER_H_ |
1091 | + |
1092 | +#include "mir/scene/prompt_session_listener.h" |
1093 | + |
1094 | +#include <gmock/gmock.h> |
1095 | + |
1096 | +namespace mir |
1097 | +{ |
1098 | +namespace test |
1099 | +{ |
1100 | +namespace doubles |
1101 | +{ |
1102 | + |
1103 | +struct MockPromptSessionListener : public scene::PromptSessionListener |
1104 | +{ |
1105 | + virtual ~MockPromptSessionListener() noexcept(true) {} |
1106 | + |
1107 | + MOCK_METHOD1(starting, void(std::shared_ptr<scene::PromptSession> const&)); |
1108 | + MOCK_METHOD1(stopping, void(std::shared_ptr<scene::PromptSession> const&)); |
1109 | + |
1110 | + MOCK_METHOD2(prompt_provider_added, void(scene::PromptSession const&, std::shared_ptr<scene::Session> const&)); |
1111 | + MOCK_METHOD2(prompt_provider_removed, void(scene::PromptSession const&, std::shared_ptr<scene::Session> const&)); |
1112 | +}; |
1113 | + |
1114 | +} |
1115 | +} |
1116 | +} // namespace mir |
1117 | + |
1118 | +#endif // MIR_TEST_DOUBLES_MOCK_PROMPT_SESSION_LISTENER_H_ |
1119 | |
1120 | === modified file 'include/test/mir_test_doubles/mock_scene_session.h' |
1121 | --- include/test/mir_test_doubles/mock_scene_session.h 2014-06-02 17:07:02 +0000 |
1122 | +++ include/test/mir_test_doubles/mock_scene_session.h 2014-06-16 15:01:17 +0000 |
1123 | @@ -52,6 +52,9 @@ |
1124 | MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int)); |
1125 | |
1126 | MOCK_METHOD1(set_lifecycle_state, void(MirLifecycleState state)); |
1127 | + |
1128 | + MOCK_METHOD0(start_prompt_session, void()); |
1129 | + MOCK_METHOD0(stop_prompt_session, void()); |
1130 | }; |
1131 | |
1132 | } |
1133 | |
1134 | === modified file 'include/test/mir_test_doubles/mock_shell.h' |
1135 | --- include/test/mir_test_doubles/mock_shell.h 2014-04-15 05:31:19 +0000 |
1136 | +++ include/test/mir_test_doubles/mock_shell.h 2014-06-16 15:01:17 +0000 |
1137 | @@ -22,6 +22,7 @@ |
1138 | #include "mir/scene/surface_creation_parameters.h" |
1139 | #include "mir/frontend/shell.h" |
1140 | #include "mir/frontend/surface_id.h" |
1141 | +#include "mir/scene/prompt_session_creation_parameters.h" |
1142 | |
1143 | #include <gmock/gmock.h> |
1144 | |
1145 | @@ -43,6 +44,17 @@ |
1146 | |
1147 | MOCK_METHOD2(create_surface_for, frontend::SurfaceId(std::shared_ptr<frontend::Session> const&, scene::SurfaceCreationParameters const&)); |
1148 | MOCK_METHOD1(handle_surface_created, void(std::shared_ptr<frontend::Session> const&)); |
1149 | + |
1150 | + MOCK_METHOD2(start_prompt_session_for, std::shared_ptr<frontend::PromptSession>( |
1151 | + std::shared_ptr<frontend::Session> const&, |
1152 | + scene::PromptSessionCreationParameters const&)); |
1153 | + MOCK_METHOD2(add_prompt_provider_process_for, void( |
1154 | + std::shared_ptr<frontend::PromptSession> const&, |
1155 | + pid_t)); |
1156 | + MOCK_METHOD2(add_prompt_provider_for, void( |
1157 | + std::shared_ptr<frontend::PromptSession> const&, |
1158 | + std::shared_ptr<frontend::Session> const&)); |
1159 | + MOCK_METHOD1(stop_prompt_session, void(std::shared_ptr<frontend::PromptSession> const&)); |
1160 | }; |
1161 | |
1162 | } |
1163 | |
1164 | === added file 'include/test/mir_test_doubles/null_client_event_sink.h' |
1165 | --- include/test/mir_test_doubles/null_client_event_sink.h 1970-01-01 00:00:00 +0000 |
1166 | +++ include/test/mir_test_doubles/null_client_event_sink.h 2014-06-16 15:01:17 +0000 |
1167 | @@ -0,0 +1,42 @@ |
1168 | +/* |
1169 | + * Copyright © 2012 Canonical Ltd. |
1170 | + * |
1171 | + * This program is free software: you can redistribute it and/or modify it |
1172 | + * under the terms of the GNU General Public License version 3, |
1173 | + * as published by the Free Software Foundation. |
1174 | + * |
1175 | + * This program is distributed in the hope that it will be useful, |
1176 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1177 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1178 | + * GNU General Public License for more details. |
1179 | + * |
1180 | + * You should have received a copy of the GNU General Public License |
1181 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1182 | + * |
1183 | + * Authored by: Nick Dedekink <nick.dedekind@canonical.com> |
1184 | + */ |
1185 | + |
1186 | +#ifndef MIR_TEST_DOUBLES_NULL_CLIENT_EVENT_SINK_H_ |
1187 | +#define MIR_TEST_DOUBLES_NULL_CLIENT_EVENT_SINK_H_ |
1188 | + |
1189 | +#include "src/client/event_sink.h" |
1190 | + |
1191 | +#include <gmock/gmock.h> |
1192 | + |
1193 | +namespace mir |
1194 | +{ |
1195 | +namespace test |
1196 | +{ |
1197 | +namespace doubles |
1198 | +{ |
1199 | +class NullClientEventSink : public client::EventSink |
1200 | +{ |
1201 | +public: |
1202 | + void handle_event(MirEvent const&) override {} |
1203 | +}; |
1204 | + |
1205 | +} |
1206 | +} |
1207 | +} |
1208 | + |
1209 | +#endif /* MIR_TEST_DOUBLES_NULL_CLIENT_EVENT_SINK_H_ */ |
1210 | |
1211 | === added file 'include/test/mir_test_doubles/null_prompt_session.h' |
1212 | --- include/test/mir_test_doubles/null_prompt_session.h 1970-01-01 00:00:00 +0000 |
1213 | +++ include/test/mir_test_doubles/null_prompt_session.h 2014-06-16 15:01:17 +0000 |
1214 | @@ -0,0 +1,37 @@ |
1215 | +/* |
1216 | + * Copyright © 2013-2014 Canonical Ltd. |
1217 | + * |
1218 | + * This program is free software: you can redistribute it and/or modify it |
1219 | + * under the terms of the GNU General Public License version 3, |
1220 | + * as published by the Free Software Foundation. |
1221 | + * |
1222 | + * This program is distributed in the hope that it will be useful, |
1223 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1224 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1225 | + * GNU General Public License for more details. |
1226 | + * |
1227 | + * You should have received a copy of the GNU General Public License |
1228 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1229 | + * |
1230 | + * Authored by: Nick Dedekind <nick.dedekind@gmail.com> |
1231 | + */ |
1232 | + |
1233 | +#ifndef MIR_TEST_DOUBLES_NULL_PROMPT_SESSION_H_ |
1234 | +#define MIR_TEST_DOUBLES_NULL_PROMPT_SESSION_H_ |
1235 | + |
1236 | +#include "mir/scene/prompt_session.h" |
1237 | + |
1238 | +namespace mir |
1239 | +{ |
1240 | +namespace test |
1241 | +{ |
1242 | +namespace doubles |
1243 | +{ |
1244 | +class NullPromptSession : public scene::PromptSession |
1245 | +{ |
1246 | +}; |
1247 | +} |
1248 | +} |
1249 | +} |
1250 | + |
1251 | +#endif /* MIR_TEST_DOUBLES_NULL_PROMPT_SESSION_H_ */ |
1252 | |
1253 | === added file 'include/test/mir_test_doubles/null_prompt_session_manager.h' |
1254 | --- include/test/mir_test_doubles/null_prompt_session_manager.h 1970-01-01 00:00:00 +0000 |
1255 | +++ include/test/mir_test_doubles/null_prompt_session_manager.h 2014-06-16 15:01:17 +0000 |
1256 | @@ -0,0 +1,82 @@ |
1257 | +/* |
1258 | + * Copyright © 2014 Canonical Ltd. |
1259 | + * |
1260 | + * This program is free software: you can redistribute it and/or modify it |
1261 | + * under the terms of the GNU General Public License version 3, |
1262 | + * as published by the Free Software Foundation. |
1263 | + * |
1264 | + * This program is distributed in the hope that it will be useful, |
1265 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1266 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1267 | + * GNU General Public License for more details. |
1268 | + * |
1269 | + * You should have received a copy of the GNU General Public License |
1270 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1271 | + * |
1272 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
1273 | + */ |
1274 | + |
1275 | +#ifndef MIR_SCENE_NULL_PROMPT_SESSION_MANAGER_H_ |
1276 | +#define MIR_SCENE_NULL_PROMPT_SESSION_MANAGER_H_ |
1277 | + |
1278 | +#include "mir/scene/prompt_session_manager.h" |
1279 | + |
1280 | +namespace mir |
1281 | +{ |
1282 | +namespace test |
1283 | +{ |
1284 | +namespace doubles |
1285 | +{ |
1286 | + |
1287 | +class NullPromptSessionManager: public scene::PromptSessionManager |
1288 | +{ |
1289 | +public: |
1290 | + std::shared_ptr<scene::PromptSession> start_prompt_session_for(std::shared_ptr<scene::Session> const&, |
1291 | + scene::PromptSessionCreationParameters const&) const |
1292 | + { |
1293 | + return std::shared_ptr<scene::PromptSession>(); |
1294 | + } |
1295 | + |
1296 | + void stop_prompt_session(std::shared_ptr<scene::PromptSession> const&) const |
1297 | + { |
1298 | + } |
1299 | + |
1300 | + void add_prompt_provider(std::shared_ptr<scene::PromptSession> const&, |
1301 | + std::shared_ptr<scene::Session> const&) const |
1302 | + { |
1303 | + } |
1304 | + |
1305 | + void add_prompt_provider_by_pid(std::shared_ptr<scene::PromptSession> const&, |
1306 | + pid_t) const |
1307 | + { |
1308 | + } |
1309 | + |
1310 | + void add_expected_session(std::shared_ptr<scene::Session> const&) const |
1311 | + { |
1312 | + } |
1313 | + |
1314 | + void remove_session(std::shared_ptr<scene::Session> const&) const |
1315 | + { |
1316 | + } |
1317 | + |
1318 | + std::shared_ptr<scene::Session> application_for(std::shared_ptr<scene::PromptSession> const&) const |
1319 | + { |
1320 | + return std::shared_ptr<scene::Session>(); |
1321 | + } |
1322 | + |
1323 | + std::shared_ptr<scene::Session> helper_for(std::shared_ptr<scene::PromptSession> const&) const |
1324 | + { |
1325 | + return std::shared_ptr<scene::Session>(); |
1326 | + } |
1327 | + |
1328 | + void for_each_provider_in(std::shared_ptr<scene::PromptSession> const&, |
1329 | + std::function<void(std::shared_ptr<scene::Session> const&)> const&) const |
1330 | + { |
1331 | + } |
1332 | +}; |
1333 | + |
1334 | +} |
1335 | +} |
1336 | +} |
1337 | + |
1338 | +#endif // MIR_SCENE_NULL_PROMPT_SESSION_MANAGER_H_ |
1339 | |
1340 | === modified file 'include/test/mir_test_doubles/stub_scene_session.h' |
1341 | --- include/test/mir_test_doubles/stub_scene_session.h 2014-06-02 17:07:02 +0000 |
1342 | +++ include/test/mir_test_doubles/stub_scene_session.h 2014-06-16 15:01:17 +0000 |
1343 | @@ -30,6 +30,8 @@ |
1344 | |
1345 | struct StubSceneSession : public scene::Session |
1346 | { |
1347 | + StubSceneSession(pid_t pid = -1) : pid(pid) {} |
1348 | + |
1349 | frontend::SurfaceId create_surface(scene::SurfaceCreationParameters const& /* params */) override |
1350 | { |
1351 | return frontend::SurfaceId{0}; |
1352 | @@ -45,9 +47,10 @@ |
1353 | { |
1354 | return std::string(); |
1355 | } |
1356 | + |
1357 | pid_t process_id() const override |
1358 | { |
1359 | - return -1; |
1360 | + return pid; |
1361 | } |
1362 | |
1363 | void force_requests_to_complete() override |
1364 | @@ -76,6 +79,16 @@ |
1365 | void set_lifecycle_state(MirLifecycleState /*state*/) |
1366 | { |
1367 | } |
1368 | + |
1369 | + void start_prompt_session() override |
1370 | + { |
1371 | + } |
1372 | + |
1373 | + void stop_prompt_session() override |
1374 | + { |
1375 | + } |
1376 | + |
1377 | + pid_t const pid; |
1378 | }; |
1379 | |
1380 | } |
1381 | |
1382 | === modified file 'include/test/mir_test_doubles/stub_shell.h' |
1383 | --- include/test/mir_test_doubles/stub_shell.h 2014-04-15 05:31:19 +0000 |
1384 | +++ include/test/mir_test_doubles/stub_shell.h 2014-06-16 15:01:17 +0000 |
1385 | @@ -49,6 +49,25 @@ |
1386 | void handle_surface_created(std::shared_ptr<frontend::Session> const& /* session */) override |
1387 | { |
1388 | } |
1389 | + std::shared_ptr<frontend::PromptSession> start_prompt_session_for(std::shared_ptr<frontend::Session> const& /* session */, |
1390 | + scene::PromptSessionCreationParameters const& /* params */) |
1391 | + { |
1392 | + return std::shared_ptr<frontend::PromptSession>(); |
1393 | + } |
1394 | + void add_prompt_provider_process_for( |
1395 | + std::shared_ptr<frontend::PromptSession> const& /* prompt_session */, |
1396 | + pid_t /* process_id */) |
1397 | + { |
1398 | + } |
1399 | + void add_prompt_provider_for( |
1400 | + std::shared_ptr<frontend::PromptSession> const& /* prompt_session */, |
1401 | + std::shared_ptr<frontend::Session> const& /* session */) |
1402 | + { |
1403 | + } |
1404 | + void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& /* prompt_session */) |
1405 | + { |
1406 | + } |
1407 | + |
1408 | std::shared_ptr<StubSession> const stub_session; |
1409 | }; |
1410 | |
1411 | |
1412 | === modified file 'src/client/CMakeLists.txt' |
1413 | --- src/client/CMakeLists.txt 2014-06-02 17:07:02 +0000 |
1414 | +++ src/client/CMakeLists.txt 2014-06-16 15:01:17 +0000 |
1415 | @@ -48,6 +48,9 @@ |
1416 | mir_screencast.cpp |
1417 | mir_screencast_api.cpp |
1418 | mir_cursor_api.cpp |
1419 | + mir_prompt_session.cpp |
1420 | + mir_prompt_session_api.cpp |
1421 | + mir_event_distributor.cpp |
1422 | ) |
1423 | |
1424 | add_library( |
1425 | @@ -82,7 +85,7 @@ |
1426 | mirclientlttngstatic |
1427 | |
1428 | ${MIR_COMMON_PLATFORM_LIBRARIES} |
1429 | - |
1430 | + |
1431 | 3rd_party |
1432 | ) |
1433 | |
1434 | |
1435 | === modified file 'src/client/connection_configuration.h' |
1436 | --- src/client/connection_configuration.h 2014-03-06 06:05:17 +0000 |
1437 | +++ src/client/connection_configuration.h 2014-06-16 15:01:17 +0000 |
1438 | @@ -47,6 +47,8 @@ |
1439 | class ClientPlatformFactory; |
1440 | class DisplayConfiguration; |
1441 | class LifecycleControl; |
1442 | +class EventSink; |
1443 | +class EventHandlerRegister; |
1444 | |
1445 | class ConnectionConfiguration |
1446 | { |
1447 | @@ -60,6 +62,8 @@ |
1448 | virtual std::shared_ptr<input::receiver::InputPlatform> the_input_platform() = 0; |
1449 | virtual std::shared_ptr<DisplayConfiguration> the_display_configuration() = 0; |
1450 | virtual std::shared_ptr<LifecycleControl> the_lifecycle_control() = 0; |
1451 | + virtual std::shared_ptr<EventSink> the_event_sink() = 0; |
1452 | + virtual std::shared_ptr<EventHandlerRegister> the_event_handler_register() = 0; |
1453 | |
1454 | protected: |
1455 | ConnectionConfiguration() = default; |
1456 | |
1457 | === modified file 'src/client/default_connection_configuration.cpp' |
1458 | --- src/client/default_connection_configuration.cpp 2014-03-26 05:48:59 +0000 |
1459 | +++ src/client/default_connection_configuration.cpp 2014-06-16 15:01:17 +0000 |
1460 | @@ -32,6 +32,7 @@ |
1461 | #include "lifecycle_control.h" |
1462 | #include "mir/shared_library.h" |
1463 | #include "client_platform_factory.h" |
1464 | +#include "mir_event_distributor.h" |
1465 | |
1466 | namespace mcl = mir::client; |
1467 | |
1468 | @@ -81,7 +82,7 @@ |
1469 | [this] |
1470 | { |
1471 | return mcl::rpc::make_rpc_channel( |
1472 | - the_socket_file(), the_surface_map(), the_display_configuration(), the_rpc_report(), the_lifecycle_control()); |
1473 | + the_socket_file(), the_surface_map(), the_display_configuration(), the_rpc_report(), the_lifecycle_control(), the_event_sink()); |
1474 | }); |
1475 | } |
1476 | |
1477 | @@ -182,3 +183,21 @@ |
1478 | return std::make_shared<mcl::LifecycleControl>(); |
1479 | }); |
1480 | } |
1481 | + |
1482 | +std::shared_ptr<mcl::EventSink> mcl::DefaultConnectionConfiguration::the_event_sink() |
1483 | +{ |
1484 | + return event_distributor( |
1485 | + [] |
1486 | + { |
1487 | + return std::make_shared<MirEventDistributor>(); |
1488 | + }); |
1489 | +} |
1490 | + |
1491 | +std::shared_ptr<mcl::EventHandlerRegister> mcl::DefaultConnectionConfiguration::the_event_handler_register() |
1492 | +{ |
1493 | + return event_distributor( |
1494 | + [] |
1495 | + { |
1496 | + return std::make_shared<MirEventDistributor>(); |
1497 | + }); |
1498 | +} |
1499 | |
1500 | === modified file 'src/client/default_connection_configuration.h' |
1501 | --- src/client/default_connection_configuration.h 2014-03-06 06:05:17 +0000 |
1502 | +++ src/client/default_connection_configuration.h 2014-06-16 15:01:17 +0000 |
1503 | @@ -36,6 +36,7 @@ |
1504 | } |
1505 | namespace client |
1506 | { |
1507 | +class EventDistributor; |
1508 | |
1509 | namespace rpc |
1510 | { |
1511 | @@ -54,6 +55,8 @@ |
1512 | std::shared_ptr<input::receiver::InputPlatform> the_input_platform(); |
1513 | std::shared_ptr<DisplayConfiguration> the_display_configuration(); |
1514 | std::shared_ptr<LifecycleControl> the_lifecycle_control(); |
1515 | + std::shared_ptr<EventSink> the_event_sink(); |
1516 | + std::shared_ptr<EventHandlerRegister> the_event_handler_register(); |
1517 | |
1518 | virtual std::string the_socket_file(); |
1519 | virtual std::shared_ptr<rpc::RpcReport> the_rpc_report(); |
1520 | @@ -67,6 +70,7 @@ |
1521 | CachedPtr<ConnectionSurfaceMap> surface_map; |
1522 | CachedPtr<DisplayConfiguration> display_configuration; |
1523 | CachedPtr<LifecycleControl> lifecycle_control; |
1524 | + CachedPtr<EventDistributor> event_distributor; |
1525 | |
1526 | CachedPtr<rpc::RpcReport> rpc_report; |
1527 | CachedPtr<input::receiver::InputReceiverReport> input_receiver_report; |
1528 | |
1529 | === added file 'src/client/event_distributor.h' |
1530 | --- src/client/event_distributor.h 1970-01-01 00:00:00 +0000 |
1531 | +++ src/client/event_distributor.h 2014-06-16 15:01:17 +0000 |
1532 | @@ -0,0 +1,37 @@ |
1533 | +/* |
1534 | + * Copyright © 2014 Canonical Ltd. |
1535 | + * |
1536 | + * This program is free software: you can redistribute it and/or modify it |
1537 | + * under the terms of the GNU Lesser General Public License version 3, |
1538 | + * as published by the Free Software Foundation. |
1539 | + * |
1540 | + * This program is distributed in the hope that it will be useful, |
1541 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1542 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1543 | + * GNU Lesser General Public License for more details. |
1544 | + * |
1545 | + * You should have received a copy of the GNU Lesser General Public License |
1546 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1547 | + * |
1548 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1549 | + */ |
1550 | + |
1551 | +#ifndef MIR_CLIENT_EVENT_DISTRIBUTOR_H_ |
1552 | +#define MIR_CLIENT_EVENT_DISTRIBUTOR_H_ |
1553 | + |
1554 | +#include "event_sink.h" |
1555 | +#include "event_handler_register.h" |
1556 | + |
1557 | +namespace mir |
1558 | +{ |
1559 | +namespace client |
1560 | +{ |
1561 | + |
1562 | +class EventDistributor : public EventHandlerRegister, public EventSink |
1563 | +{ |
1564 | +}; |
1565 | + |
1566 | +} // namespace client |
1567 | +} // namespace mir |
1568 | + |
1569 | +#endif // MIR_CLIENT_EVENT_DISTRIBUTOR_H_ |
1570 | |
1571 | === added file 'src/client/event_handler_register.h' |
1572 | --- src/client/event_handler_register.h 1970-01-01 00:00:00 +0000 |
1573 | +++ src/client/event_handler_register.h 2014-06-16 15:01:17 +0000 |
1574 | @@ -0,0 +1,47 @@ |
1575 | +/* |
1576 | + * Copyright © 2014 Canonical Ltd. |
1577 | + * |
1578 | + * This program is free software: you can redistribute it and/or modify it |
1579 | + * under the terms of the GNU Lesser General Public License version 3, |
1580 | + * as published by the Free Software Foundation. |
1581 | + * |
1582 | + * This program is distributed in the hope that it will be useful, |
1583 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1584 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1585 | + * GNU Lesser General Public License for more details. |
1586 | + * |
1587 | + * You should have received a copy of the GNU Lesser General Public License |
1588 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1589 | + * |
1590 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1591 | + */ |
1592 | + |
1593 | +#ifndef MIR_CLIENT_EVENT_HANDLER_REGISTER_H_ |
1594 | +#define MIR_CLIENT_EVENT_HANDLER_REGISTER_H_ |
1595 | + |
1596 | +#include "mir_toolkit/event.h" |
1597 | + |
1598 | +#include <functional> |
1599 | + |
1600 | +namespace mir |
1601 | +{ |
1602 | +namespace client |
1603 | +{ |
1604 | + |
1605 | +class EventHandlerRegister |
1606 | +{ |
1607 | +public: |
1608 | + virtual ~EventHandlerRegister() = default; |
1609 | + |
1610 | + virtual int register_event_handler(std::function<void(MirEvent const&)> const&) = 0; |
1611 | + virtual void unregister_event_handler(int id) = 0; |
1612 | + |
1613 | +protected: |
1614 | + EventHandlerRegister() = default; |
1615 | + EventHandlerRegister(EventHandlerRegister const&) = delete; |
1616 | + EventHandlerRegister& operator=(EventHandlerRegister const&) = delete; |
1617 | +}; |
1618 | +} // namespace client |
1619 | +} // namespace mir |
1620 | + |
1621 | +#endif // MIR_CLIENT_EVENT_HANDLER_REGISTER_H_ |
1622 | |
1623 | === added file 'src/client/event_sink.h' |
1624 | --- src/client/event_sink.h 1970-01-01 00:00:00 +0000 |
1625 | +++ src/client/event_sink.h 2014-06-16 15:01:17 +0000 |
1626 | @@ -0,0 +1,44 @@ |
1627 | +/* |
1628 | + * Copyright © 2014 Canonical Ltd. |
1629 | + * |
1630 | + * This program is free software: you can redistribute it and/or modify it |
1631 | + * under the terms of the GNU Lesser General Public License version 3, |
1632 | + * as published by the Free Software Foundation. |
1633 | + * |
1634 | + * This program is distributed in the hope that it will be useful, |
1635 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1636 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1637 | + * GNU Lesser General Public License for more details. |
1638 | + * |
1639 | + * You should have received a copy of the GNU Lesser General Public License |
1640 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1641 | + * |
1642 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1643 | + */ |
1644 | + |
1645 | +#ifndef MIR_CLIENT_EVENT_SINK_H_ |
1646 | +#define MIR_CLIENT_EVENT_SINK_H_ |
1647 | + |
1648 | +#include "mir_toolkit/event.h" |
1649 | + |
1650 | +namespace mir |
1651 | +{ |
1652 | +namespace client |
1653 | +{ |
1654 | + |
1655 | +class EventSink |
1656 | +{ |
1657 | +public: |
1658 | + virtual ~EventSink() = default; |
1659 | + |
1660 | + virtual void handle_event(MirEvent const& e) = 0; |
1661 | + |
1662 | +protected: |
1663 | + EventSink() = default; |
1664 | + EventSink(EventSink const&) = delete; |
1665 | + EventSink& operator=(EventSink const&) = delete; |
1666 | +}; |
1667 | +} // namespace client |
1668 | +} // namespace mir |
1669 | + |
1670 | +#endif // MIR_CLIENT_EVENT_SINK_H_ |
1671 | |
1672 | === modified file 'src/client/mir_connection.cpp' |
1673 | --- src/client/mir_connection.cpp 2014-06-11 16:24:02 +0000 |
1674 | +++ src/client/mir_connection.cpp 2014-06-16 15:01:17 +0000 |
1675 | @@ -18,6 +18,7 @@ |
1676 | |
1677 | #include "mir_connection.h" |
1678 | #include "mir_surface.h" |
1679 | +#include "mir_prompt_session.h" |
1680 | #include "client_platform.h" |
1681 | #include "client_platform_factory.h" |
1682 | #include "rpc/mir_basic_rpc_channel.h" |
1683 | @@ -82,7 +83,8 @@ |
1684 | input_platform(conf.the_input_platform()), |
1685 | display_configuration(conf.the_display_configuration()), |
1686 | lifecycle_control(conf.the_lifecycle_control()), |
1687 | - surface_map(conf.the_surface_map()) |
1688 | + surface_map(conf.the_surface_map()), |
1689 | + event_handler_register(conf.the_event_handler_register()) |
1690 | { |
1691 | connect_result.set_error("connect not called"); |
1692 | { |
1693 | @@ -194,6 +196,11 @@ |
1694 | return new_wait_handle; |
1695 | } |
1696 | |
1697 | +MirPromptSession* MirConnection::create_prompt_session() |
1698 | +{ |
1699 | + return new MirPromptSession(display_server(), event_handler_register); |
1700 | +} |
1701 | + |
1702 | namespace |
1703 | { |
1704 | void default_lifecycle_event_handler(MirLifecycleState transition) |
1705 | @@ -307,40 +314,6 @@ |
1706 | return &drm_auth_magic_wait_handle; |
1707 | } |
1708 | |
1709 | -MirWaitHandle* MirConnection::new_fds_for_trusted_clients( |
1710 | - unsigned int no_of_fds, |
1711 | - mir_client_fd_callback callback, |
1712 | - void * context) |
1713 | -{ |
1714 | - mir::protobuf::SocketFDRequest request; |
1715 | - request.set_number(no_of_fds); |
1716 | - |
1717 | - server.new_fds_for_trusted_clients( |
1718 | - nullptr, |
1719 | - &request, |
1720 | - &socket_fd_response, |
1721 | - google::protobuf::NewCallback(this, &MirConnection::done_fds_for_trusted_clients, |
1722 | - callback, context)); |
1723 | - |
1724 | - return &fds_for_trusted_clients_wait_handle; |
1725 | -} |
1726 | - |
1727 | -void MirConnection::done_fds_for_trusted_clients( |
1728 | - mir_client_fd_callback callback, |
1729 | - void* context) |
1730 | -{ |
1731 | - auto const size = socket_fd_response.fd_size(); |
1732 | - |
1733 | - std::vector<int> fds; |
1734 | - fds.reserve(size); |
1735 | - |
1736 | - for (auto i = 0; i != size; ++i) |
1737 | - fds.push_back(socket_fd_response.fd(i)); |
1738 | - |
1739 | - callback(this, size, fds.data(), context); |
1740 | - fds_for_trusted_clients_wait_handle.result_received(); |
1741 | -} |
1742 | - |
1743 | bool MirConnection::is_valid(MirConnection *connection) |
1744 | { |
1745 | { |
1746 | @@ -526,6 +499,6 @@ |
1747 | } |
1748 | |
1749 | mir::protobuf::DisplayServer& MirConnection::display_server() |
1750 | -{ |
1751 | +{ |
1752 | return server; |
1753 | } |
1754 | |
1755 | === modified file 'src/client/mir_connection.h' |
1756 | --- src/client/mir_connection.h 2014-06-02 17:07:02 +0000 |
1757 | +++ src/client/mir_connection.h 2014-06-16 15:01:17 +0000 |
1758 | @@ -45,6 +45,7 @@ |
1759 | class ConnectionSurfaceMap; |
1760 | class DisplayConfiguration; |
1761 | class LifecycleControl; |
1762 | +class EventHandlerRegister; |
1763 | |
1764 | namespace rpc |
1765 | { |
1766 | @@ -86,6 +87,8 @@ |
1767 | mir_surface_callback callback, |
1768 | void *context); |
1769 | |
1770 | + MirPromptSession* create_prompt_session(); |
1771 | + |
1772 | char const * get_error_message(); |
1773 | |
1774 | MirWaitHandle* connect( |
1775 | @@ -123,11 +126,6 @@ |
1776 | |
1777 | bool set_extra_platform_data(std::vector<int> const& extra_platform_data); |
1778 | |
1779 | - MirWaitHandle* new_fds_for_trusted_clients( |
1780 | - unsigned int no_of_fds, |
1781 | - mir_client_fd_callback callback, |
1782 | - void * context); |
1783 | - |
1784 | std::shared_ptr<google::protobuf::RpcChannel> rpc_channel() const |
1785 | { |
1786 | return channel; |
1787 | @@ -147,7 +145,6 @@ |
1788 | mir::protobuf::ConnectParameters connect_parameters; |
1789 | mir::protobuf::DRMAuthMagicStatus drm_auth_magic_status; |
1790 | mir::protobuf::DisplayConfiguration display_configuration_response; |
1791 | - mir::protobuf::SocketFD socket_fd_response; |
1792 | |
1793 | std::shared_ptr<mir::client::ClientPlatformFactory> const client_platform_factory; |
1794 | std::shared_ptr<mir::client::ClientPlatform> platform; |
1795 | @@ -161,7 +158,6 @@ |
1796 | MirWaitHandle disconnect_wait_handle; |
1797 | MirWaitHandle drm_auth_magic_wait_handle; |
1798 | MirWaitHandle configure_display_wait_handle; |
1799 | - MirWaitHandle fds_for_trusted_clients_wait_handle; |
1800 | |
1801 | std::mutex release_wait_handle_guard; |
1802 | std::vector<MirWaitHandle*> release_wait_handles; |
1803 | @@ -172,6 +168,8 @@ |
1804 | |
1805 | std::shared_ptr<mir::client::ConnectionSurfaceMap> const surface_map; |
1806 | |
1807 | + std::shared_ptr<mir::client::EventHandlerRegister> const event_handler_register; |
1808 | + |
1809 | std::vector<int> extra_platform_data; |
1810 | |
1811 | struct SurfaceRelease; |
1812 | @@ -181,7 +179,6 @@ |
1813 | void connected(mir_connected_callback callback, void * context); |
1814 | void released(SurfaceRelease ); |
1815 | void done_drm_auth_magic(mir_drm_auth_magic_callback callback, void* context); |
1816 | - void done_fds_for_trusted_clients(mir_client_fd_callback callback, void* context); |
1817 | bool validate_user_display_config(MirDisplayConfiguration* config); |
1818 | }; |
1819 | |
1820 | |
1821 | === modified file 'src/client/mir_connection_api.cpp' |
1822 | --- src/client/mir_connection_api.cpp 2014-06-02 17:07:02 +0000 |
1823 | +++ src/client/mir_connection_api.cpp 2014-06-16 15:01:17 +0000 |
1824 | @@ -272,24 +272,6 @@ |
1825 | } |
1826 | } |
1827 | |
1828 | -MirWaitHandle* mir_connection_new_fds_for_trusted_clients( |
1829 | - MirConnection* connection, |
1830 | - unsigned int no_of_fds, |
1831 | - mir_client_fd_callback callback, |
1832 | - void * context) |
1833 | -{ |
1834 | - try |
1835 | - { |
1836 | - return connection ? |
1837 | - connection->new_fds_for_trusted_clients(no_of_fds, callback, context) : |
1838 | - nullptr; |
1839 | - } |
1840 | - catch (std::exception const&) |
1841 | - { |
1842 | - return nullptr; |
1843 | - } |
1844 | -} |
1845 | - |
1846 | MirEGLNativeDisplayType mir_connection_get_egl_native_display( |
1847 | MirConnection* connection) |
1848 | { |
1849 | |
1850 | === added file 'src/client/mir_event_distributor.cpp' |
1851 | --- src/client/mir_event_distributor.cpp 1970-01-01 00:00:00 +0000 |
1852 | +++ src/client/mir_event_distributor.cpp 2014-06-16 15:01:17 +0000 |
1853 | @@ -0,0 +1,56 @@ |
1854 | +/* |
1855 | + * Copyright © 2014 Canonical Ltd. |
1856 | + * |
1857 | + * This program is free software: you can redistribute it and/or modify it |
1858 | + * under the terms of the GNU Lesser General Public License version 3, |
1859 | + * as published by the Free Software Foundation. |
1860 | + * |
1861 | + * This program is distributed in the hope that it will be useful, |
1862 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1863 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1864 | + * GNU Lesser General Public License for more details. |
1865 | + * |
1866 | + * You should have received a copy of the GNU Lesser General Public License |
1867 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1868 | + * |
1869 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1870 | + */ |
1871 | + |
1872 | +#include "mir_event_distributor.h" |
1873 | + |
1874 | +MirEventDistributor::MirEventDistributor() : |
1875 | + next_fn_id{0} |
1876 | +{ |
1877 | +} |
1878 | + |
1879 | +int MirEventDistributor::register_event_handler(std::function<void(MirEvent const&)> const& fn) |
1880 | +{ |
1881 | + std::unique_lock<decltype(mutex)> lock(mutex); |
1882 | + |
1883 | + int id = ++next_fn_id; |
1884 | + event_handlers[id] = fn; |
1885 | + return id; |
1886 | +} |
1887 | + |
1888 | +void MirEventDistributor::unregister_event_handler(int id) |
1889 | +{ |
1890 | + std::unique_lock<decltype(mutex)> lock(mutex); |
1891 | + |
1892 | + event_handlers.erase(id); |
1893 | +} |
1894 | + |
1895 | +void MirEventDistributor::handle_event(MirEvent const& event) |
1896 | +{ |
1897 | + std::unique_lock<decltype(mutex)> lock(mutex); |
1898 | + |
1899 | + auto const event_handlers_copy(event_handlers); |
1900 | + |
1901 | + for (auto const& handler : event_handlers_copy) |
1902 | + { |
1903 | + // Ensure handler wasn't unregistered since making copy |
1904 | + if (event_handlers.find(handler.first) != event_handlers.end()) |
1905 | + { |
1906 | + handler.second(event); |
1907 | + } |
1908 | + } |
1909 | +} |
1910 | |
1911 | === added file 'src/client/mir_event_distributor.h' |
1912 | --- src/client/mir_event_distributor.h 1970-01-01 00:00:00 +0000 |
1913 | +++ src/client/mir_event_distributor.h 2014-06-16 15:01:17 +0000 |
1914 | @@ -0,0 +1,43 @@ |
1915 | +/* |
1916 | + * Copyright © 2014 Canonical Ltd. |
1917 | + * |
1918 | + * This program is free software: you can redistribute it and/or modify it |
1919 | + * under the terms of the GNU Lesser General Public License version 3, |
1920 | + * as published by the Free Software Foundation. |
1921 | + * |
1922 | + * This program is distributed in the hope that it will be useful, |
1923 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1924 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1925 | + * GNU Lesser General Public License for more details. |
1926 | + * |
1927 | + * You should have received a copy of the GNU Lesser General Public License |
1928 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1929 | + * |
1930 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1931 | + */ |
1932 | + |
1933 | +#ifndef MIR_EVENT_DISTRIBUTOR_H |
1934 | + |
1935 | +#include "event_distributor.h" |
1936 | + |
1937 | +#include <mutex> |
1938 | +#include <map> |
1939 | + |
1940 | +class MirEventDistributor : public mir::client::EventDistributor |
1941 | +{ |
1942 | +public: |
1943 | + MirEventDistributor(); |
1944 | + ~MirEventDistributor() = default; |
1945 | + |
1946 | + int register_event_handler(std::function<void(MirEvent const&)> const&) override; |
1947 | + void unregister_event_handler(int id) override; |
1948 | + |
1949 | + void handle_event(MirEvent const& event) override; |
1950 | + |
1951 | +private: |
1952 | + mutable std::recursive_mutex mutex; |
1953 | + std::map<int, std::function<void(MirEvent const&)>> event_handlers; |
1954 | + int next_fn_id; |
1955 | +}; |
1956 | + |
1957 | +#endif /* MIR_EVENT_DISTRIBUTOR_H */ |
1958 | |
1959 | === added file 'src/client/mir_prompt_session.cpp' |
1960 | --- src/client/mir_prompt_session.cpp 1970-01-01 00:00:00 +0000 |
1961 | +++ src/client/mir_prompt_session.cpp 2014-06-16 15:01:17 +0000 |
1962 | @@ -0,0 +1,203 @@ |
1963 | +/* |
1964 | + * Copyright © 2014 Canonical Ltd. |
1965 | + * |
1966 | + * This program is free software: you can redistribute it and/or modify it |
1967 | + * under the terms of the GNU Lesser General Public License version 3, |
1968 | + * as published by the Free Software Foundation. |
1969 | + * |
1970 | + * This program is distributed in the hope that it will be useful, |
1971 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1972 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1973 | + * GNU Lesser General Public License for more details. |
1974 | + * |
1975 | + * You should have received a copy of the GNU Lesser General Public License |
1976 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1977 | + * |
1978 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
1979 | + */ |
1980 | + |
1981 | +#include "mir_prompt_session.h" |
1982 | +#include "event_handler_register.h" |
1983 | + |
1984 | +namespace mp = mir::protobuf; |
1985 | +namespace mcl = mir::client; |
1986 | + |
1987 | +MirPromptSession::MirPromptSession( |
1988 | + mp::DisplayServer& server, |
1989 | + std::shared_ptr<mcl::EventHandlerRegister> const& event_handler_register) : |
1990 | + server(server), |
1991 | + event_handler_register(event_handler_register), |
1992 | + event_handler_register_id{event_handler_register->register_event_handler( |
1993 | + [this](MirEvent const& event) |
1994 | + { |
1995 | + if (event.type == mir_event_type_prompt_session_state_change) |
1996 | + set_state(event.prompt_session.new_state); |
1997 | + })}, |
1998 | + state(mir_prompt_session_state_stopped), |
1999 | + handle_prompt_session_state_change{[](MirPromptSessionState){}} |
2000 | +{ |
2001 | +} |
2002 | + |
2003 | +MirPromptSession::~MirPromptSession() |
2004 | +{ |
2005 | + set_state(mir_prompt_session_state_stopped); |
2006 | +} |
2007 | + |
2008 | +void MirPromptSession::set_state(MirPromptSessionState new_state) |
2009 | +{ |
2010 | + std::lock_guard<decltype(event_handler_mutex)> lock(event_handler_mutex); |
2011 | + |
2012 | + if (new_state != state) |
2013 | + { |
2014 | + handle_prompt_session_state_change(new_state); |
2015 | + |
2016 | + if (new_state == mir_prompt_session_state_stopped) |
2017 | + { |
2018 | + event_handler_register->unregister_event_handler(event_handler_register_id); |
2019 | + } |
2020 | + |
2021 | + state = new_state; |
2022 | + } |
2023 | +} |
2024 | + |
2025 | +MirWaitHandle* MirPromptSession::start(pid_t application_pid, mir_prompt_session_callback callback, void* context) |
2026 | +{ |
2027 | + { |
2028 | + std::lock_guard<decltype(mutex)> lock(mutex); |
2029 | + parameters.set_application_pid(application_pid); |
2030 | + } |
2031 | + |
2032 | + start_wait_handle.expect_result(); |
2033 | + server.start_prompt_session( |
2034 | + 0, |
2035 | + ¶meters, |
2036 | + &session, |
2037 | + google::protobuf::NewCallback(this, &MirPromptSession::done_start, |
2038 | + callback, context)); |
2039 | + |
2040 | + return &start_wait_handle; |
2041 | +} |
2042 | + |
2043 | +MirWaitHandle* MirPromptSession::stop(mir_prompt_session_callback callback, void* context) |
2044 | +{ |
2045 | + stop_wait_handle.expect_result(); |
2046 | + |
2047 | + server.stop_prompt_session( |
2048 | + 0, |
2049 | + &protobuf_void, |
2050 | + &protobuf_void, |
2051 | + google::protobuf::NewCallback(this, &MirPromptSession::done_stop, |
2052 | + callback, context)); |
2053 | + |
2054 | + return &stop_wait_handle; |
2055 | +} |
2056 | + |
2057 | +MirWaitHandle* MirPromptSession::add_prompt_provider(pid_t provider_pid, |
2058 | + mir_prompt_session_add_prompt_provider_callback callback, |
2059 | + void* context) |
2060 | +{ |
2061 | + { |
2062 | + std::lock_guard<decltype(mutex)> lock(mutex); |
2063 | + prompt_provider.set_pid(provider_pid); |
2064 | + } |
2065 | + |
2066 | + add_result_wait_handle.expect_result(); |
2067 | + server.add_prompt_provider( |
2068 | + 0, |
2069 | + &prompt_provider, |
2070 | + &add_result, |
2071 | + google::protobuf::NewCallback(this, &MirPromptSession::done_add_prompt_provider, |
2072 | + callback, context)); |
2073 | + |
2074 | + return &add_result_wait_handle; |
2075 | +} |
2076 | + |
2077 | +void MirPromptSession::register_prompt_session_state_change_callback( |
2078 | + mir_prompt_session_state_change_callback callback, |
2079 | + void* context) |
2080 | +{ |
2081 | + std::lock_guard<decltype(event_handler_mutex)> lock(event_handler_mutex); |
2082 | + |
2083 | + handle_prompt_session_state_change = |
2084 | + [this, callback, context](MirPromptSessionState new_state) |
2085 | + { |
2086 | + callback(this, new_state, context); |
2087 | + }; |
2088 | +} |
2089 | + |
2090 | +void MirPromptSession::done_start(mir_prompt_session_callback callback, void* context) |
2091 | +{ |
2092 | + { |
2093 | + std::lock_guard<decltype(session_mutex)> lock(session_mutex); |
2094 | + |
2095 | + state = session.has_error() ? mir_prompt_session_state_stopped : mir_prompt_session_state_started; |
2096 | + } |
2097 | + |
2098 | + callback(this, context); |
2099 | + start_wait_handle.result_received(); |
2100 | +} |
2101 | + |
2102 | +void MirPromptSession::done_stop(mir_prompt_session_callback callback, void* context) |
2103 | +{ |
2104 | + set_state(mir_prompt_session_state_stopped); |
2105 | + |
2106 | + callback(this, context); |
2107 | + stop_wait_handle.result_received(); |
2108 | +} |
2109 | + |
2110 | +void MirPromptSession::done_add_prompt_provider(mir_prompt_session_add_prompt_provider_callback callback, void* context) |
2111 | +{ |
2112 | + MirBool added = mir_true; |
2113 | + if (add_result.has_error()) |
2114 | + { |
2115 | + added = mir_false; |
2116 | + } |
2117 | + callback(this, added, context); |
2118 | + add_result_wait_handle.result_received(); |
2119 | +} |
2120 | + |
2121 | +char const* MirPromptSession::get_error_message() |
2122 | +{ |
2123 | + std::lock_guard<decltype(session_mutex)> lock(session_mutex); |
2124 | + |
2125 | + if (!session.has_error()) |
2126 | + session.set_error(std::string{}); |
2127 | + |
2128 | + return session.error().c_str(); |
2129 | +} |
2130 | + |
2131 | +MirWaitHandle* MirPromptSession::new_fds_for_prompt_providers( |
2132 | + unsigned int no_of_fds, |
2133 | + mir_client_fd_callback callback, |
2134 | + void * context) |
2135 | +{ |
2136 | + mir::protobuf::SocketFDRequest request; |
2137 | + request.set_number(no_of_fds); |
2138 | + |
2139 | + fds_for_prompt_providers_wait_handle.expect_result(); |
2140 | + |
2141 | + server.new_fds_for_prompt_providers( |
2142 | + nullptr, |
2143 | + &request, |
2144 | + &socket_fd_response, |
2145 | + google::protobuf::NewCallback(this, &MirPromptSession::done_fds_for_prompt_providers, |
2146 | + callback, context)); |
2147 | + |
2148 | + return &fds_for_prompt_providers_wait_handle; |
2149 | +} |
2150 | + |
2151 | +void MirPromptSession::done_fds_for_prompt_providers( |
2152 | + mir_client_fd_callback callback, |
2153 | + void* context) |
2154 | +{ |
2155 | + auto const size = socket_fd_response.fd_size(); |
2156 | + |
2157 | + std::vector<int> fds; |
2158 | + fds.reserve(size); |
2159 | + |
2160 | + for (auto i = 0; i != size; ++i) |
2161 | + fds.push_back(socket_fd_response.fd(i)); |
2162 | + |
2163 | + callback(this, size, fds.data(), context); |
2164 | + fds_for_prompt_providers_wait_handle.result_received(); |
2165 | +} |
2166 | |
2167 | === added file 'src/client/mir_prompt_session.h' |
2168 | --- src/client/mir_prompt_session.h 1970-01-01 00:00:00 +0000 |
2169 | +++ src/client/mir_prompt_session.h 2014-06-16 15:01:17 +0000 |
2170 | @@ -0,0 +1,94 @@ |
2171 | +/* |
2172 | + * Copyright © 2014 Canonical Ltd. |
2173 | + * |
2174 | + * This program is free software: you can redistribute it and/or modify it |
2175 | + * under the terms of the GNU Lesser General Public License version 3, |
2176 | + * as published by the Free Software Foundation. |
2177 | + * |
2178 | + * This program is distributed in the hope that it will be useful, |
2179 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2180 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2181 | + * GNU Lesser General Public License for more details. |
2182 | + * |
2183 | + * You should have received a copy of the GNU Lesser General Public License |
2184 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2185 | + * |
2186 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
2187 | + */ |
2188 | + |
2189 | +#ifndef MIR_CLIENT_MIR_PROMPT_SESSION_H_ |
2190 | +#define MIR_CLIENT_MIR_PROMPT_SESSION_H_ |
2191 | + |
2192 | +#include "mir_toolkit/mir_client_library.h" |
2193 | + |
2194 | +#include "mir_protobuf.pb.h" |
2195 | +#include "mir_wait_handle.h" |
2196 | + |
2197 | +#include <mutex> |
2198 | +#include <memory> |
2199 | +#include <atomic> |
2200 | + |
2201 | +namespace mir |
2202 | +{ |
2203 | +/// The client-side library implementation namespace |
2204 | +namespace client |
2205 | +{ |
2206 | +class EventHandlerRegister; |
2207 | +} |
2208 | +} |
2209 | + |
2210 | +struct MirPromptSession |
2211 | +{ |
2212 | +public: |
2213 | + MirPromptSession(mir::protobuf::DisplayServer& server, |
2214 | + std::shared_ptr<mir::client::EventHandlerRegister> const& event_handler_register); |
2215 | + |
2216 | + ~MirPromptSession(); |
2217 | + |
2218 | + MirWaitHandle* start(pid_t application_pid, mir_prompt_session_callback callback, void* context); |
2219 | + MirWaitHandle* stop(mir_prompt_session_callback callback, void* context); |
2220 | + MirWaitHandle* add_prompt_provider(pid_t provider_pid, mir_prompt_session_add_prompt_provider_callback callback, void* context); |
2221 | + |
2222 | + MirWaitHandle* new_fds_for_prompt_providers( |
2223 | + unsigned int no_of_fds, |
2224 | + mir_client_fd_callback callback, |
2225 | + void * context); |
2226 | + |
2227 | + void register_prompt_session_state_change_callback(mir_prompt_session_state_change_callback callback, void* context); |
2228 | + |
2229 | + char const* get_error_message(); |
2230 | + |
2231 | +private: |
2232 | + std::mutex mutable mutex; // Protects parameters, wait_handles & results |
2233 | + mir::protobuf::DisplayServer& server; |
2234 | + mir::protobuf::PromptProvider prompt_provider; |
2235 | + mir::protobuf::PromptSessionParameters parameters; |
2236 | + mir::protobuf::Void add_result; |
2237 | + mir::protobuf::Void protobuf_void; |
2238 | + mir::protobuf::SocketFD socket_fd_response; |
2239 | + std::shared_ptr<mir::client::EventHandlerRegister> const event_handler_register; |
2240 | + int const event_handler_register_id; |
2241 | + |
2242 | + MirWaitHandle start_wait_handle; |
2243 | + MirWaitHandle stop_wait_handle; |
2244 | + MirWaitHandle add_result_wait_handle; |
2245 | + MirWaitHandle fds_for_prompt_providers_wait_handle; |
2246 | + std::atomic<MirPromptSessionState> state; |
2247 | + |
2248 | + std::mutex mutable session_mutex; // Protects session |
2249 | + mir::protobuf::Void session; |
2250 | + |
2251 | + std::mutex mutable event_handler_mutex; // Need another mutex for callback access to members |
2252 | + std::function<void(MirPromptSessionState)> handle_prompt_session_state_change; |
2253 | + |
2254 | + void set_state(MirPromptSessionState new_state); |
2255 | + void done_start(mir_prompt_session_callback callback, void* context); |
2256 | + void done_stop(mir_prompt_session_callback callback, void* context); |
2257 | + void done_add_prompt_provider(mir_prompt_session_add_prompt_provider_callback callback, void* context); |
2258 | + void done_fds_for_prompt_providers(mir_client_fd_callback callback, void* context); |
2259 | + MirPromptSession(MirPromptSession const&) = delete; |
2260 | + MirPromptSession& operator=(MirPromptSession const&) = delete; |
2261 | +}; |
2262 | + |
2263 | +#endif /* MIR_CLIENT_MIR_PROMPT_SESSION_H_ */ |
2264 | + |
2265 | |
2266 | === added file 'src/client/mir_prompt_session_api.cpp' |
2267 | --- src/client/mir_prompt_session_api.cpp 1970-01-01 00:00:00 +0000 |
2268 | +++ src/client/mir_prompt_session_api.cpp 2014-06-16 15:01:17 +0000 |
2269 | @@ -0,0 +1,118 @@ |
2270 | +/* |
2271 | + * Copyright © 2014 Canonical Ltd. |
2272 | + * |
2273 | + * This program is free software: you can redistribute it and/or modify it |
2274 | + * under the terms of the GNU Lesser General Public License version 3, |
2275 | + * as published by the Free Software Foundation. |
2276 | + * |
2277 | + * This program is distributed in the hope that it will be useful, |
2278 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2279 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2280 | + * GNU Lesser General Public License for more details. |
2281 | + * |
2282 | + * You should have received a copy of the GNU Lesser General Public License |
2283 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2284 | + * |
2285 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
2286 | + */ |
2287 | + |
2288 | + |
2289 | +#include "mir_toolkit/mir_prompt_session.h" |
2290 | +#include "mir_prompt_session.h" |
2291 | +#include "mir_connection.h" |
2292 | + |
2293 | +#include <stdexcept> |
2294 | +#include <boost/throw_exception.hpp> |
2295 | + |
2296 | +namespace |
2297 | +{ |
2298 | +void null_callback(MirPromptSession*, void*) {} |
2299 | + |
2300 | +void add_prompt_provider_callback( |
2301 | + MirPromptSession*, |
2302 | + MirBool added, |
2303 | + void* context) |
2304 | +{ |
2305 | + if (context) |
2306 | + *(MirBool*)context = added; |
2307 | +} |
2308 | + |
2309 | +} |
2310 | + |
2311 | +MirPromptSession *mir_connection_create_prompt_session_sync( |
2312 | + MirConnection* connection, |
2313 | + pid_t application_pid, |
2314 | + mir_prompt_session_state_change_callback state_change_callback, |
2315 | + void* context) |
2316 | +{ |
2317 | + try |
2318 | + { |
2319 | + auto prompt_session = connection->create_prompt_session(); |
2320 | + if (state_change_callback) |
2321 | + prompt_session->register_prompt_session_state_change_callback(state_change_callback, context); |
2322 | + |
2323 | + mir_wait_for(prompt_session->start(application_pid, |
2324 | + null_callback, |
2325 | + nullptr)); |
2326 | + return prompt_session; |
2327 | + } |
2328 | + catch (std::exception const&) |
2329 | + { |
2330 | + // TODO callback with an error |
2331 | + return nullptr; |
2332 | + } |
2333 | +} |
2334 | + |
2335 | +MirWaitHandle *mir_prompt_session_add_prompt_provider( |
2336 | + MirPromptSession *prompt_session, |
2337 | + pid_t provider_pid, |
2338 | + mir_prompt_session_add_prompt_provider_callback callback, |
2339 | + void* context) |
2340 | +{ |
2341 | + try |
2342 | + { |
2343 | + return prompt_session->add_prompt_provider(provider_pid, callback, context); |
2344 | + } |
2345 | + catch (std::exception const&) |
2346 | + { |
2347 | + // TODO callback with an error |
2348 | + return nullptr; |
2349 | + } |
2350 | +} |
2351 | + |
2352 | +MirBool mir_prompt_session_add_prompt_provider_sync( |
2353 | + MirPromptSession *prompt_session, |
2354 | + pid_t provider_pid) |
2355 | +{ |
2356 | + MirBool result; |
2357 | + mir_wait_for(mir_prompt_session_add_prompt_provider(prompt_session, |
2358 | + provider_pid, |
2359 | + add_prompt_provider_callback, |
2360 | + &result)); |
2361 | + return result; |
2362 | +} |
2363 | + |
2364 | +MirWaitHandle* mir_prompt_session_new_fds_for_prompt_providers( |
2365 | + MirPromptSession *prompt_session, |
2366 | + unsigned int no_of_fds, |
2367 | + mir_client_fd_callback callback, |
2368 | + void * context) |
2369 | +{ |
2370 | + try |
2371 | + { |
2372 | + return prompt_session ? |
2373 | + prompt_session->new_fds_for_prompt_providers(no_of_fds, callback, context) : |
2374 | + nullptr; |
2375 | + } |
2376 | + catch (std::exception const&) |
2377 | + { |
2378 | + return nullptr; |
2379 | + } |
2380 | +} |
2381 | + |
2382 | +void mir_prompt_session_release_sync( |
2383 | + MirPromptSession *prompt_session) |
2384 | +{ |
2385 | + mir_wait_for(prompt_session->stop(&null_callback, nullptr)); |
2386 | + delete prompt_session; |
2387 | +} |
2388 | |
2389 | === modified file 'src/client/rpc/make_rpc_channel.h' |
2390 | --- src/client/rpc/make_rpc_channel.h 2014-03-06 06:05:17 +0000 |
2391 | +++ src/client/rpc/make_rpc_channel.h 2014-06-16 15:01:17 +0000 |
2392 | @@ -29,6 +29,7 @@ |
2393 | class SurfaceMap; |
2394 | class DisplayConfiguration; |
2395 | class LifecycleControl; |
2396 | +class EventSink; |
2397 | |
2398 | namespace rpc |
2399 | { |
2400 | @@ -39,7 +40,8 @@ |
2401 | std::shared_ptr<SurfaceMap> const& map, |
2402 | std::shared_ptr<DisplayConfiguration> const& disp_conf, |
2403 | std::shared_ptr<RpcReport> const& rpc_report, |
2404 | - std::shared_ptr<LifecycleControl> const& lifecycle_control); |
2405 | + std::shared_ptr<LifecycleControl> const& lifecycle_control, |
2406 | + std::shared_ptr<EventSink> const& event_distributor); |
2407 | } |
2408 | } |
2409 | } |
2410 | |
2411 | === modified file 'src/client/rpc/make_socket_rpc_channel.cpp' |
2412 | --- src/client/rpc/make_socket_rpc_channel.cpp 2014-03-06 06:05:17 +0000 |
2413 | +++ src/client/rpc/make_socket_rpc_channel.cpp 2014-06-16 15:01:17 +0000 |
2414 | @@ -44,13 +44,14 @@ |
2415 | std::shared_ptr<mcl::SurfaceMap> const& map, |
2416 | std::shared_ptr<mcl::DisplayConfiguration> const& disp_conf, |
2417 | std::shared_ptr<RpcReport> const& rpc_report, |
2418 | - std::shared_ptr<mcl::LifecycleControl> const& lifecycle_control) |
2419 | + std::shared_ptr<mcl::LifecycleControl> const& lifecycle_control, |
2420 | + std::shared_ptr<mcl::EventSink> const& event_sink) |
2421 | { |
2422 | if (fd_prefix.is_start_of(name)) |
2423 | { |
2424 | auto const fd = atoi(name.c_str()+fd_prefix.size); |
2425 | - return std::make_shared<MirSocketRpcChannel>(fd, map, disp_conf, rpc_report, lifecycle_control); |
2426 | + return std::make_shared<MirSocketRpcChannel>(fd, map, disp_conf, rpc_report, lifecycle_control, event_sink); |
2427 | } |
2428 | |
2429 | - return std::make_shared<MirSocketRpcChannel>(name, map, disp_conf, rpc_report, lifecycle_control); |
2430 | + return std::make_shared<MirSocketRpcChannel>(name, map, disp_conf, rpc_report, lifecycle_control, event_sink); |
2431 | } |
2432 | |
2433 | === modified file 'src/client/rpc/mir_socket_rpc_channel.cpp' |
2434 | --- src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-09 17:16:32 +0000 |
2435 | +++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-16 15:01:17 +0000 |
2436 | @@ -24,6 +24,7 @@ |
2437 | #include "../mir_surface.h" |
2438 | #include "../display_configuration.h" |
2439 | #include "../lifecycle_control.h" |
2440 | +#include "../event_sink.h" |
2441 | #include "mir/variable_length_array.h" |
2442 | |
2443 | #include "mir_protobuf.pb.h" // For Buffer frig |
2444 | @@ -50,7 +51,8 @@ |
2445 | std::shared_ptr<mcl::SurfaceMap> const& surface_map, |
2446 | std::shared_ptr<DisplayConfiguration> const& disp_config, |
2447 | std::shared_ptr<RpcReport> const& rpc_report, |
2448 | - std::shared_ptr<LifecycleControl> const& lifecycle_control) : |
2449 | + std::shared_ptr<LifecycleControl> const& lifecycle_control, |
2450 | + std::shared_ptr<EventSink> const& event_sink) : |
2451 | rpc_report(rpc_report), |
2452 | pending_calls(rpc_report), |
2453 | work(io_service), |
2454 | @@ -58,6 +60,7 @@ |
2455 | surface_map(surface_map), |
2456 | display_configuration(disp_config), |
2457 | lifecycle_control(lifecycle_control), |
2458 | + event_sink(event_sink), |
2459 | disconnected(false) |
2460 | { |
2461 | socket.connect(endpoint); |
2462 | @@ -69,7 +72,8 @@ |
2463 | std::shared_ptr<mcl::SurfaceMap> const& surface_map, |
2464 | std::shared_ptr<DisplayConfiguration> const& disp_config, |
2465 | std::shared_ptr<RpcReport> const& rpc_report, |
2466 | - std::shared_ptr<LifecycleControl> const& lifecycle_control) : |
2467 | + std::shared_ptr<LifecycleControl> const& lifecycle_control, |
2468 | + std::shared_ptr<EventSink> const& event_sink) : |
2469 | rpc_report(rpc_report), |
2470 | pending_calls(rpc_report), |
2471 | work(io_service), |
2472 | @@ -77,6 +81,7 @@ |
2473 | surface_map(surface_map), |
2474 | display_configuration(disp_config), |
2475 | lifecycle_control(lifecycle_control), |
2476 | + event_sink(event_sink), |
2477 | disconnected(false) |
2478 | { |
2479 | socket.assign(boost::asio::local::stream_protocol(), native_socket); |
2480 | @@ -413,11 +418,25 @@ |
2481 | |
2482 | rpc_report->event_parsing_succeeded(e); |
2483 | |
2484 | - surface_map->with_surface_do(e.surface.id, |
2485 | - [&e](MirSurface* surface) |
2486 | - { |
2487 | - surface->handle_event(e); |
2488 | - }); |
2489 | + event_sink->handle_event(e); |
2490 | + |
2491 | + // todo - surfaces should register with the event handler register. |
2492 | + if (e.type == mir_event_type_surface) |
2493 | + { |
2494 | + surface_map->with_surface_do(e.surface.id, |
2495 | + [&e](MirSurface* surface) |
2496 | + { |
2497 | + surface->handle_event(e); |
2498 | + }); |
2499 | + } |
2500 | + else if (e.type == mir_event_type_resize) |
2501 | + { |
2502 | + surface_map->with_surface_do(e.resize.surface_id, |
2503 | + [&e](MirSurface* surface) |
2504 | + { |
2505 | + surface->handle_event(e); |
2506 | + }); |
2507 | + } |
2508 | } |
2509 | else |
2510 | { |
2511 | |
2512 | === modified file 'src/client/rpc/mir_socket_rpc_channel.h' |
2513 | --- src/client/rpc/mir_socket_rpc_channel.h 2014-06-02 17:07:02 +0000 |
2514 | +++ src/client/rpc/mir_socket_rpc_channel.h 2014-06-16 15:01:17 +0000 |
2515 | @@ -44,6 +44,7 @@ |
2516 | class DisplayConfiguration; |
2517 | class SurfaceMap; |
2518 | class LifecycleControl; |
2519 | +class EventSink; |
2520 | namespace rpc |
2521 | { |
2522 | |
2523 | @@ -56,13 +57,15 @@ |
2524 | std::shared_ptr<SurfaceMap> const& surface_map, |
2525 | std::shared_ptr<DisplayConfiguration> const& disp_config, |
2526 | std::shared_ptr<RpcReport> const& rpc_report, |
2527 | - std::shared_ptr<LifecycleControl> const& lifecycle_control); |
2528 | + std::shared_ptr<LifecycleControl> const& lifecycle_control, |
2529 | + std::shared_ptr<EventSink> const& event_sink); |
2530 | |
2531 | MirSocketRpcChannel(int native_socket, |
2532 | std::shared_ptr<SurfaceMap> const& surface_map, |
2533 | std::shared_ptr<DisplayConfiguration> const& disp_config, |
2534 | std::shared_ptr<RpcReport> const& rpc_report, |
2535 | - std::shared_ptr<LifecycleControl> const& lifecycle_control); |
2536 | + std::shared_ptr<LifecycleControl> const& lifecycle_control, |
2537 | + std::shared_ptr<EventSink> const& event_sink); |
2538 | ~MirSocketRpcChannel(); |
2539 | |
2540 | private: |
2541 | @@ -102,6 +105,7 @@ |
2542 | std::shared_ptr<SurfaceMap> surface_map; |
2543 | std::shared_ptr<DisplayConfiguration> display_configuration; |
2544 | std::shared_ptr<LifecycleControl> lifecycle_control; |
2545 | + std::shared_ptr<EventSink> event_sink; |
2546 | std::atomic<bool> disconnected; |
2547 | }; |
2548 | |
2549 | |
2550 | === modified file 'src/server/default_server_configuration.cpp' |
2551 | --- src/server/default_server_configuration.cpp 2014-06-02 17:07:02 +0000 |
2552 | +++ src/server/default_server_configuration.cpp 2014-06-16 15:01:17 +0000 |
2553 | @@ -37,6 +37,7 @@ |
2554 | #include "mir/time/high_resolution_clock.h" |
2555 | #include "mir/geometry/rectangles.h" |
2556 | #include "mir/default_configuration.h" |
2557 | +#include "mir/scene/null_prompt_session_listener.h" |
2558 | |
2559 | #include <map> |
2560 | #include <vector> |
2561 | @@ -90,6 +91,16 @@ |
2562 | }); |
2563 | } |
2564 | |
2565 | +std::shared_ptr<ms::PromptSessionListener> |
2566 | +mir::DefaultServerConfiguration::the_prompt_session_listener() |
2567 | +{ |
2568 | + return prompt_session_listener( |
2569 | + [this] |
2570 | + { |
2571 | + return std::make_shared<ms::NullPromptSessionListener>(); |
2572 | + }); |
2573 | +} |
2574 | + |
2575 | std::shared_ptr<mi::CursorListener> |
2576 | mir::DefaultServerConfiguration::the_cursor_listener() |
2577 | { |
2578 | |
2579 | === modified file 'src/server/frontend/protobuf_message_processor.cpp' |
2580 | --- src/server/frontend/protobuf_message_processor.cpp 2014-06-02 17:07:02 +0000 |
2581 | +++ src/server/frontend/protobuf_message_processor.cpp 2014-06-16 15:01:17 +0000 |
2582 | @@ -183,9 +183,21 @@ |
2583 | { |
2584 | invoke(this, display_server.get(), &protobuf::DisplayServer::configure_cursor, invocation); |
2585 | } |
2586 | - else if ("new_fds_for_trusted_clients" == invocation.method_name()) |
2587 | - { |
2588 | - invoke(this, display_server.get(), &protobuf::DisplayServer::new_fds_for_trusted_clients, invocation); |
2589 | + else if ("new_fds_for_prompt_providers" == invocation.method_name()) |
2590 | + { |
2591 | + invoke(this, display_server.get(), &protobuf::DisplayServer::new_fds_for_prompt_providers, invocation); |
2592 | + } |
2593 | + else if ("start_prompt_session" == invocation.method_name()) |
2594 | + { |
2595 | + invoke(this, display_server.get(), &protobuf::DisplayServer::start_prompt_session, invocation); |
2596 | + } |
2597 | + else if ("add_prompt_provider" == invocation.method_name()) |
2598 | + { |
2599 | + invoke(this, display_server.get(), &protobuf::DisplayServer::add_prompt_provider, invocation); |
2600 | + } |
2601 | + else if ("stop_prompt_session" == invocation.method_name()) |
2602 | + { |
2603 | + invoke(this, display_server.get(), &protobuf::DisplayServer::stop_prompt_session, invocation); |
2604 | } |
2605 | else if ("disconnect" == invocation.method_name()) |
2606 | { |
2607 | |
2608 | === modified file 'src/server/frontend/session_mediator.cpp' |
2609 | --- src/server/frontend/session_mediator.cpp 2014-06-03 16:43:38 +0000 |
2610 | +++ src/server/frontend/session_mediator.cpp 2014-06-16 15:01:17 +0000 |
2611 | @@ -41,6 +41,8 @@ |
2612 | #include "mir/frontend/client_constants.h" |
2613 | #include "mir/frontend/event_sink.h" |
2614 | #include "mir/frontend/screencast.h" |
2615 | +#include "mir/frontend/prompt_session.h" |
2616 | +#include "mir/scene/prompt_session_creation_parameters.h" |
2617 | |
2618 | #include "mir/geometry/rectangles.h" |
2619 | #include "client_buffer_tracker.h" |
2620 | @@ -423,9 +425,16 @@ |
2621 | done->Run(); |
2622 | } |
2623 | |
2624 | -std::function<void(std::shared_ptr<mf::Session> const&)> mf::SessionMediator::trusted_connect_handler() const |
2625 | +std::function<void(std::shared_ptr<mf::Session> const&)> mf::SessionMediator::prompt_session_connect_handler() const |
2626 | { |
2627 | - return [](std::shared_ptr<frontend::Session> const&) {}; |
2628 | + return [this](std::shared_ptr<frontend::Session> const& session) |
2629 | + { |
2630 | + auto prompt_session = weak_prompt_session.lock(); |
2631 | + if (prompt_session.get() == nullptr) |
2632 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid prompt session")); |
2633 | + |
2634 | + shell->add_prompt_provider_for(prompt_session, session); |
2635 | + }; |
2636 | } |
2637 | |
2638 | void mf::SessionMediator::configure_cursor( |
2639 | @@ -446,7 +455,7 @@ |
2640 | |
2641 | auto const id = frontend::SurfaceId(cursor_request->surfaceid().value()); |
2642 | auto const surface = session->get_surface(id); |
2643 | - |
2644 | + |
2645 | if (cursor_request->has_name()) |
2646 | { |
2647 | auto const& image = cursor_images->image(cursor_request->name(), mg::default_cursor_size); |
2648 | @@ -460,7 +469,7 @@ |
2649 | done->Run(); |
2650 | } |
2651 | |
2652 | -void mf::SessionMediator::new_fds_for_trusted_clients( |
2653 | +void mf::SessionMediator::new_fds_for_prompt_providers( |
2654 | ::google::protobuf::RpcController* , |
2655 | ::mir::protobuf::SocketFDRequest const* parameters, |
2656 | ::mir::protobuf::SocketFD* response, |
2657 | @@ -473,8 +482,7 @@ |
2658 | if (session.get() == nullptr) |
2659 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
2660 | |
2661 | - // TODO write a handler that connects the new session to our trust session |
2662 | - auto const connect_handler = trusted_connect_handler(); |
2663 | + auto const connect_handler = prompt_session_connect_handler(); |
2664 | |
2665 | auto const fds_requested = parameters->number(); |
2666 | |
2667 | @@ -531,6 +539,83 @@ |
2668 | done->Run(); |
2669 | } |
2670 | |
2671 | +void mf::SessionMediator::start_prompt_session( |
2672 | + ::google::protobuf::RpcController*, |
2673 | + const ::mir::protobuf::PromptSessionParameters* request, |
2674 | + ::mir::protobuf::Void* /*response*/, |
2675 | + ::google::protobuf::Closure* done) |
2676 | +{ |
2677 | + { |
2678 | + std::unique_lock<std::mutex> lock(session_mutex); |
2679 | + auto const session = weak_session.lock(); |
2680 | + |
2681 | + if (!session) |
2682 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
2683 | + |
2684 | + if (weak_prompt_session.lock()) |
2685 | + BOOST_THROW_EXCEPTION(std::runtime_error("Cannot start another prompt session")); |
2686 | + |
2687 | + ms::PromptSessionCreationParameters parameters; |
2688 | + parameters.application_pid = request->application_pid(); |
2689 | + |
2690 | + report->session_start_prompt_session_called(session->name(), parameters.application_pid); |
2691 | + |
2692 | + weak_prompt_session = shell->start_prompt_session_for(session, parameters); |
2693 | + } |
2694 | + done->Run(); |
2695 | +} |
2696 | + |
2697 | +void mf::SessionMediator::add_prompt_provider( |
2698 | + ::google::protobuf::RpcController*, |
2699 | + const ::mir::protobuf::PromptProvider* request, |
2700 | + ::mir::protobuf::Void*, |
2701 | + ::google::protobuf::Closure* done) |
2702 | +{ |
2703 | + { |
2704 | + std::unique_lock<std::mutex> lock(session_mutex); |
2705 | + auto const session = weak_session.lock(); |
2706 | + |
2707 | + if (!session) |
2708 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
2709 | + |
2710 | + auto const prompt_session = weak_prompt_session.lock(); |
2711 | + |
2712 | + if (!prompt_session) |
2713 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid prompt session")); |
2714 | + |
2715 | + report->session_add_prompt_provider_called(session->name(), request->pid()); |
2716 | + shell->add_prompt_provider_process_for(prompt_session, request->pid()); |
2717 | + } |
2718 | + done->Run(); |
2719 | +} |
2720 | + |
2721 | +void mf::SessionMediator::stop_prompt_session( |
2722 | + ::google::protobuf::RpcController*, |
2723 | + const ::mir::protobuf::Void*, |
2724 | + ::mir::protobuf::Void*, |
2725 | + ::google::protobuf::Closure* done) |
2726 | +{ |
2727 | + { |
2728 | + std::unique_lock<std::mutex> lock(session_mutex); |
2729 | + auto const session = weak_session.lock(); |
2730 | + |
2731 | + if (!session) |
2732 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
2733 | + |
2734 | + auto const prompt_session = weak_prompt_session.lock(); |
2735 | + |
2736 | + if (!prompt_session) |
2737 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid prompt session")); |
2738 | + |
2739 | + weak_prompt_session.reset(); |
2740 | + |
2741 | + report->session_stop_prompt_session_called(session->name()); |
2742 | + |
2743 | + shell->stop_prompt_session(prompt_session); |
2744 | + } |
2745 | + done->Run(); |
2746 | +} |
2747 | + |
2748 | void mf::SessionMediator::pack_protobuf_buffer( |
2749 | protobuf::Buffer& protobuf_buffer, |
2750 | graphics::Buffer* graphics_buffer, |
2751 | |
2752 | === modified file 'src/server/frontend/session_mediator.h' |
2753 | --- src/server/frontend/session_mediator.h 2014-06-03 16:43:38 +0000 |
2754 | +++ src/server/frontend/session_mediator.h 2014-06-16 15:01:17 +0000 |
2755 | @@ -54,6 +54,7 @@ |
2756 | class EventSink; |
2757 | class DisplayChanger; |
2758 | class Screencast; |
2759 | +class PromptSession; |
2760 | |
2761 | // SessionMediator relays requests from the client process into the server. |
2762 | class SessionMediator : public detail::DisplayServer |
2763 | @@ -109,9 +110,9 @@ |
2764 | google::protobuf::Closure* done) override; |
2765 | |
2766 | void configure_display(::google::protobuf::RpcController* controller, |
2767 | - const ::mir::protobuf::DisplayConfiguration* request, |
2768 | - ::mir::protobuf::DisplayConfiguration* response, |
2769 | - ::google::protobuf::Closure* done) override; |
2770 | + const ::mir::protobuf::DisplayConfiguration* request, |
2771 | + ::mir::protobuf::DisplayConfiguration* response, |
2772 | + ::google::protobuf::Closure* done) override; |
2773 | |
2774 | void create_screencast(google::protobuf::RpcController*, |
2775 | const mir::protobuf::ScreencastParameters*, |
2776 | @@ -127,19 +128,34 @@ |
2777 | const mir::protobuf::ScreencastId*, |
2778 | mir::protobuf::Buffer*, |
2779 | google::protobuf::Closure* done); |
2780 | - |
2781 | + |
2782 | void configure_cursor(google::protobuf::RpcController*, |
2783 | mir::protobuf::CursorSetting const*, |
2784 | mir::protobuf::Void*, |
2785 | google::protobuf::Closure* done); |
2786 | |
2787 | + void start_prompt_session(::google::protobuf::RpcController* controller, |
2788 | + const ::mir::protobuf::PromptSessionParameters* request, |
2789 | + ::mir::protobuf::Void* response, |
2790 | + ::google::protobuf::Closure* done); |
2791 | + |
2792 | + void add_prompt_provider(::google::protobuf::RpcController* controller, |
2793 | + const ::mir::protobuf::PromptProvider* request, |
2794 | + ::mir::protobuf::Void*, |
2795 | + ::google::protobuf::Closure* done); |
2796 | + |
2797 | + void stop_prompt_session(::google::protobuf::RpcController* controller, |
2798 | + const ::mir::protobuf::Void* request, |
2799 | + ::mir::protobuf::Void* response, |
2800 | + ::google::protobuf::Closure* done); |
2801 | + |
2802 | /* Platform specific requests */ |
2803 | void drm_auth_magic(google::protobuf::RpcController* controller, |
2804 | const mir::protobuf::DRMMagic* request, |
2805 | mir::protobuf::DRMAuthMagicStatus* response, |
2806 | google::protobuf::Closure* done) override; |
2807 | |
2808 | - void new_fds_for_trusted_clients( |
2809 | + void new_fds_for_prompt_providers( |
2810 | ::google::protobuf::RpcController* controller, |
2811 | ::mir::protobuf::SocketFDRequest const* parameters, |
2812 | ::mir::protobuf::SocketFD* response, |
2813 | @@ -152,7 +168,7 @@ |
2814 | |
2815 | void advance_buffer(SurfaceId surf_id, Surface& surface, std::function<void(graphics::Buffer*, bool)> complete); |
2816 | |
2817 | - virtual std::function<void(std::shared_ptr<Session> const&)> trusted_connect_handler() const; |
2818 | + virtual std::function<void(std::shared_ptr<Session> const&)> prompt_session_connect_handler() const; |
2819 | |
2820 | pid_t client_pid_; |
2821 | std::shared_ptr<Shell> const shell; |
2822 | @@ -173,6 +189,7 @@ |
2823 | |
2824 | std::mutex session_mutex; |
2825 | std::weak_ptr<Session> weak_session; |
2826 | + std::weak_ptr<PromptSession> weak_prompt_session; |
2827 | }; |
2828 | |
2829 | } |
2830 | |
2831 | === modified file 'src/server/report/logging/session_mediator_report.cpp' |
2832 | --- src/server/report/logging/session_mediator_report.cpp 2014-05-12 21:11:05 +0000 |
2833 | +++ src/server/report/logging/session_mediator_report.cpp 2014-06-16 15:01:17 +0000 |
2834 | @@ -78,6 +78,21 @@ |
2835 | log->log(ml::Logger::informational, "session_configure_display_called(\"" + app_name + "\")", component); |
2836 | } |
2837 | |
2838 | +void mrl::SessionMediatorReport::session_start_prompt_session_called(std::string const& app_name, pid_t application_process) |
2839 | +{ |
2840 | + log->log(ml::Logger::informational, "session_start_prompt_session_called(\"" + app_name + ", " + std::to_string(application_process) + ")", component); |
2841 | +} |
2842 | + |
2843 | +void mrl::SessionMediatorReport::session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process) |
2844 | +{ |
2845 | + log->log(ml::Logger::informational, "session_add_prompt_provider_called(\"" + app_name + ", " + std::to_string(provider_process) + ")", component); |
2846 | +} |
2847 | + |
2848 | +void mrl::SessionMediatorReport::session_stop_prompt_session_called(std::string const& app_name) |
2849 | +{ |
2850 | + log->log(ml::Logger::informational, "session_stop_prompt_session_called(\"" + app_name + "\")", component); |
2851 | +} |
2852 | + |
2853 | void mrl::SessionMediatorReport::session_error( |
2854 | std::string const& app_name, |
2855 | char const* method, |
2856 | |
2857 | === modified file 'src/server/report/logging/session_mediator_report.h' |
2858 | --- src/server/report/logging/session_mediator_report.h 2014-05-12 21:11:05 +0000 |
2859 | +++ src/server/report/logging/session_mediator_report.h 2014-06-16 15:01:17 +0000 |
2860 | @@ -59,6 +59,12 @@ |
2861 | |
2862 | virtual void session_configure_display_called(std::string const& app_name); |
2863 | |
2864 | + virtual void session_start_prompt_session_called(std::string const& app_name, pid_t application_process); |
2865 | + |
2866 | + virtual void session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process); |
2867 | + |
2868 | + virtual void session_stop_prompt_session_called(std::string const& app_name); |
2869 | + |
2870 | virtual void session_error( |
2871 | std::string const& app_name, |
2872 | char const* method, |
2873 | |
2874 | === modified file 'src/server/report/lttng/session_mediator_report.cpp' |
2875 | --- src/server/report/lttng/session_mediator_report.cpp 2014-05-12 21:11:05 +0000 |
2876 | +++ src/server/report/lttng/session_mediator_report.cpp 2014-06-16 15:01:17 +0000 |
2877 | @@ -39,6 +39,17 @@ |
2878 | MIR_SESSION_MEDIATOR_EVENT_METHOD(session_configure_surface_called) |
2879 | MIR_SESSION_MEDIATOR_EVENT_METHOD(session_configure_surface_cursor_called) |
2880 | MIR_SESSION_MEDIATOR_EVENT_METHOD(session_configure_display_called) |
2881 | +MIR_SESSION_MEDIATOR_EVENT_METHOD(session_stop_prompt_session_called) |
2882 | + |
2883 | +void mir::report::lttng::SessionMediatorReport::session_start_prompt_session_called(std::string const& app_name, pid_t application_process) |
2884 | +{ |
2885 | + mir_tracepoint(mir_server_session_mediator, session_start_prompt_session_called, app_name.c_str(), application_process); |
2886 | +} |
2887 | + |
2888 | +void mir::report::lttng::SessionMediatorReport::session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process) |
2889 | +{ |
2890 | + mir_tracepoint(mir_server_session_mediator, session_add_prompt_provider_called, app_name.c_str(), provider_process); |
2891 | +} |
2892 | |
2893 | void mir::report::lttng::SessionMediatorReport::session_error(std::string const& app_name, char const* method, std::string const& what) |
2894 | { |
2895 | |
2896 | === modified file 'src/server/report/lttng/session_mediator_report.h' |
2897 | --- src/server/report/lttng/session_mediator_report.h 2014-05-12 21:11:05 +0000 |
2898 | +++ src/server/report/lttng/session_mediator_report.h 2014-06-16 15:01:17 +0000 |
2899 | @@ -42,6 +42,9 @@ |
2900 | void session_configure_surface_called(std::string const& app_name) override; |
2901 | void session_configure_surface_cursor_called(std::string const& app_name) override; |
2902 | void session_configure_display_called(std::string const& app_name) override; |
2903 | + void session_start_prompt_session_called(std::string const& app_name, pid_t application_process) override; |
2904 | + void session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process) override; |
2905 | + void session_stop_prompt_session_called(std::string const& app_name) override; |
2906 | |
2907 | void session_error(std::string const& app_name, char const* method, std::string const& what) override; |
2908 | private: |
2909 | |
2910 | === modified file 'src/server/report/lttng/session_mediator_report_tp.h' |
2911 | --- src/server/report/lttng/session_mediator_report_tp.h 2014-05-12 21:11:05 +0000 |
2912 | +++ src/server/report/lttng/session_mediator_report_tp.h 2014-06-16 15:01:17 +0000 |
2913 | @@ -48,6 +48,27 @@ |
2914 | MIR_SESSION_MEDIATOR_EVENT(session_configure_surface_called) |
2915 | MIR_SESSION_MEDIATOR_EVENT(session_configure_surface_cursor_called) |
2916 | MIR_SESSION_MEDIATOR_EVENT(session_configure_display_called) |
2917 | +MIR_SESSION_MEDIATOR_EVENT(session_stop_prompt_session_called) |
2918 | + |
2919 | +TRACEPOINT_EVENT( |
2920 | + mir_server_session_mediator, |
2921 | + session_start_prompt_session_called, |
2922 | + TP_ARGS(char const*, application, pid_t, application_process), |
2923 | + TP_FIELDS( |
2924 | + ctf_string(application, application) |
2925 | + ctf_integer(pid_t, application_process, application_process) |
2926 | + ) |
2927 | + ) |
2928 | + |
2929 | +TRACEPOINT_EVENT( |
2930 | + mir_server_session_mediator, |
2931 | + session_add_prompt_provider_called, |
2932 | + TP_ARGS(char const*, application, pid_t, provider_process), |
2933 | + TP_FIELDS( |
2934 | + ctf_string(application, application) |
2935 | + ctf_integer(pid_t, provider_process, provider_process) |
2936 | + ) |
2937 | + ) |
2938 | |
2939 | TRACEPOINT_EVENT( |
2940 | mir_server_session_mediator, |
2941 | |
2942 | === modified file 'src/server/report/null/session_mediator_report.cpp' |
2943 | --- src/server/report/null/session_mediator_report.cpp 2014-05-12 21:11:05 +0000 |
2944 | +++ src/server/report/null/session_mediator_report.cpp 2014-06-16 15:01:17 +0000 |
2945 | @@ -54,6 +54,18 @@ |
2946 | { |
2947 | } |
2948 | |
2949 | +void mir::report::null::SessionMediatorReport::session_start_prompt_session_called(std::string const&, pid_t) |
2950 | +{ |
2951 | +} |
2952 | + |
2953 | +void mir::report::null::SessionMediatorReport::session_add_prompt_provider_called(std::string const&, pid_t) |
2954 | +{ |
2955 | +} |
2956 | + |
2957 | +void mir::report::null::SessionMediatorReport::session_stop_prompt_session_called(std::string const&) |
2958 | +{ |
2959 | +} |
2960 | + |
2961 | void mir::report::null::SessionMediatorReport::session_error( |
2962 | std::string const&, |
2963 | char const* , |
2964 | |
2965 | === modified file 'src/server/report/null/session_mediator_report.h' |
2966 | --- src/server/report/null/session_mediator_report.h 2014-05-12 21:11:05 +0000 |
2967 | +++ src/server/report/null/session_mediator_report.h 2014-06-16 15:01:17 +0000 |
2968 | @@ -53,6 +53,12 @@ |
2969 | |
2970 | void session_configure_display_called(std::string const& app_name) override; |
2971 | |
2972 | + void session_start_prompt_session_called(std::string const& app_name, pid_t application_process) override; |
2973 | + |
2974 | + void session_add_prompt_provider_called(std::string const& app_name, pid_t provider_process) override; |
2975 | + |
2976 | + void session_stop_prompt_session_called(std::string const& app_name) override; |
2977 | + |
2978 | void session_error( |
2979 | std::string const& app_name, |
2980 | char const* method, |
2981 | |
2982 | === modified file 'src/server/scene/CMakeLists.txt' |
2983 | --- src/server/scene/CMakeLists.txt 2014-06-02 17:07:02 +0000 |
2984 | +++ src/server/scene/CMakeLists.txt 2014-06-16 15:01:17 +0000 |
2985 | @@ -20,4 +20,6 @@ |
2986 | threaded_snapshot_strategy.cpp |
2987 | legacy_scene_change_notification.cpp |
2988 | legacy_surface_change_notification.cpp |
2989 | + prompt_session_container.cpp |
2990 | + prompt_session_manager_impl.cpp |
2991 | ) |
2992 | |
2993 | === modified file 'src/server/scene/application_session.cpp' |
2994 | --- src/server/scene/application_session.cpp 2014-06-02 17:07:02 +0000 |
2995 | +++ src/server/scene/application_session.cpp 2014-06-16 15:01:17 +0000 |
2996 | @@ -23,6 +23,7 @@ |
2997 | #include "snapshot_strategy.h" |
2998 | #include "mir/scene/session_listener.h" |
2999 | #include "mir/frontend/event_sink.h" |
3000 | +#include "default_session_container.h" |
3001 | |
3002 | #include <boost/throw_exception.hpp> |
3003 | |
3004 | @@ -30,6 +31,7 @@ |
3005 | #include <memory> |
3006 | #include <cassert> |
3007 | #include <algorithm> |
3008 | +#include <cstring> |
3009 | |
3010 | namespace mf = mir::frontend; |
3011 | namespace ms = mir::scene; |
3012 | @@ -181,3 +183,22 @@ |
3013 | { |
3014 | event_sink->handle_lifecycle_event(state); |
3015 | } |
3016 | + |
3017 | +void ms::ApplicationSession::start_prompt_session() |
3018 | +{ |
3019 | + // All sessions which are part of the prompt session get this event. |
3020 | + MirEvent start_event; |
3021 | + memset(&start_event, 0, sizeof start_event); |
3022 | + start_event.type = mir_event_type_prompt_session_state_change; |
3023 | + start_event.prompt_session.new_state = mir_prompt_session_state_started; |
3024 | + event_sink->handle_event(start_event); |
3025 | +} |
3026 | + |
3027 | +void ms::ApplicationSession::stop_prompt_session() |
3028 | +{ |
3029 | + MirEvent stop_event; |
3030 | + memset(&stop_event, 0, sizeof stop_event); |
3031 | + stop_event.type = mir_event_type_prompt_session_state_change; |
3032 | + stop_event.prompt_session.new_state = mir_prompt_session_state_stopped; |
3033 | + event_sink->handle_event(stop_event); |
3034 | +} |
3035 | |
3036 | === modified file 'src/server/scene/application_session.h' |
3037 | --- src/server/scene/application_session.h 2014-06-02 17:07:02 +0000 |
3038 | +++ src/server/scene/application_session.h 2014-06-16 15:01:17 +0000 |
3039 | @@ -71,6 +71,9 @@ |
3040 | |
3041 | void set_lifecycle_state(MirLifecycleState state); |
3042 | |
3043 | + void start_prompt_session() override; |
3044 | + void stop_prompt_session() override; |
3045 | + |
3046 | protected: |
3047 | ApplicationSession(ApplicationSession const&) = delete; |
3048 | ApplicationSession& operator=(ApplicationSession const&) = delete; |
3049 | |
3050 | === modified file 'src/server/scene/default_configuration.cpp' |
3051 | --- src/server/scene/default_configuration.cpp 2014-06-03 16:43:38 +0000 |
3052 | +++ src/server/scene/default_configuration.cpp 2014-06-16 15:01:17 +0000 |
3053 | @@ -35,6 +35,7 @@ |
3054 | #include "surface_controller.h" |
3055 | #include "surface_stack.h" |
3056 | #include "threaded_snapshot_strategy.h" |
3057 | +#include "prompt_session_manager_impl.h" |
3058 | |
3059 | namespace mc = mir::compositor; |
3060 | namespace mf = mir::frontend; |
3061 | @@ -179,7 +180,8 @@ |
3062 | the_shell_focus_setter(), |
3063 | the_snapshot_strategy(), |
3064 | the_session_event_sink(), |
3065 | - the_session_listener())); |
3066 | + the_session_listener(), |
3067 | + the_prompt_session_manager())); |
3068 | }); |
3069 | } |
3070 | |
3071 | @@ -223,3 +225,15 @@ |
3072 | the_pixel_buffer()); |
3073 | }); |
3074 | } |
3075 | + |
3076 | +std::shared_ptr<ms::PromptSessionManager> |
3077 | +mir::DefaultServerConfiguration::the_prompt_session_manager() |
3078 | +{ |
3079 | + return prompt_session_manager( |
3080 | + [this]() |
3081 | + { |
3082 | + return std::make_shared<ms::PromptSessionManagerImpl>( |
3083 | + the_session_container(), |
3084 | + the_prompt_session_listener()); |
3085 | + }); |
3086 | +} |
3087 | |
3088 | === added file 'src/server/scene/prompt_session_container.cpp' |
3089 | --- src/server/scene/prompt_session_container.cpp 1970-01-01 00:00:00 +0000 |
3090 | +++ src/server/scene/prompt_session_container.cpp 2014-06-16 15:01:17 +0000 |
3091 | @@ -0,0 +1,189 @@ |
3092 | +/* |
3093 | + * Copyright © 2014 Canonical Ltd. |
3094 | + * |
3095 | + * This program is free software: you can redistribute it and/or modify it |
3096 | + * under the terms of the GNU General Public License version 3, |
3097 | + * as published by the Free Software Foundation. |
3098 | + * |
3099 | + * This program is distributed in the hope that it will be useful, |
3100 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3101 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3102 | + * GNU General Public License for more details. |
3103 | + * |
3104 | + * You should have received a copy of the GNU General Public License |
3105 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3106 | + * |
3107 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
3108 | + */ |
3109 | + |
3110 | +#include "prompt_session_container.h" |
3111 | +#include "mir/scene/session.h" |
3112 | + |
3113 | +#include <boost/throw_exception.hpp> |
3114 | +#include <atomic> |
3115 | + |
3116 | +namespace ms = mir::scene; |
3117 | +namespace mf = mir::frontend; |
3118 | + |
3119 | +namespace |
3120 | +{ |
3121 | +std::atomic<unsigned> insertion_order{0}; |
3122 | +} |
3123 | + |
3124 | +ms::PromptSessionContainer::PromptSessionContainer() |
3125 | + : prompt_session_index(participant_map) |
3126 | + , participant_index(get<1>(participant_map)) |
3127 | + , waiting_process_prompt_session_index(waiting_process_map) |
3128 | + , waiting_process_index(get<1>(waiting_process_map)) |
3129 | +{ |
3130 | +} |
3131 | + |
3132 | +void ms::PromptSessionContainer::insert_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) |
3133 | +{ |
3134 | + std::unique_lock<std::mutex> lk(mutex); |
3135 | + prompt_sessions[prompt_session.get()] = prompt_session; |
3136 | +} |
3137 | + |
3138 | +void ms::PromptSessionContainer::remove_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) |
3139 | +{ |
3140 | + std::unique_lock<std::mutex> lk(mutex); |
3141 | + |
3142 | + { |
3143 | + participant_by_prompt_session::iterator it, end; |
3144 | + boost::tie(it, end) = prompt_session_index.equal_range(prompt_session.get()); |
3145 | + prompt_session_index.erase(it, end); |
3146 | + } |
3147 | + |
3148 | + { |
3149 | + process_by_prompt_session::iterator it, end; |
3150 | + boost::tie(it, end) = waiting_process_prompt_session_index.equal_range(prompt_session.get()); |
3151 | + waiting_process_prompt_session_index.erase(it, end); |
3152 | + } |
3153 | + |
3154 | + prompt_sessions.erase(prompt_session.get()); |
3155 | +} |
3156 | + |
3157 | +bool ms::PromptSessionContainer::insert_participant(PromptSession* prompt_session, std::weak_ptr<Session> const& session, ParticipantType participant_type) |
3158 | +{ |
3159 | + std::unique_lock<std::mutex> lk(mutex); |
3160 | + |
3161 | + // the prompt session must have first been added by insert_prompt_session. |
3162 | + if (prompt_sessions.find(prompt_session) == prompt_sessions.end()) |
3163 | + BOOST_THROW_EXCEPTION(std::runtime_error("Prompt Session does not exist")); |
3164 | + |
3165 | + if (auto locked_session = session.lock()) |
3166 | + { |
3167 | + participant_by_prompt_session::iterator it; |
3168 | + bool valid = false; |
3169 | + |
3170 | + Participant participant{prompt_session, locked_session, participant_type, insertion_order++}; |
3171 | + boost::tie(it,valid) = participant_map.insert(participant); |
3172 | + |
3173 | + if (!valid) |
3174 | + return false; |
3175 | + |
3176 | + process_by_prompt_session::iterator process_it,end; |
3177 | + boost::tie(process_it,end) = waiting_process_prompt_session_index.equal_range(boost::make_tuple(prompt_session, locked_session->process_id())); |
3178 | + if (process_it != end) |
3179 | + waiting_process_prompt_session_index.erase(process_it); |
3180 | + return true; |
3181 | + } |
3182 | + return false; |
3183 | +} |
3184 | + |
3185 | +bool ms::PromptSessionContainer::remove_participant(PromptSession* prompt_session, std::weak_ptr<Session> const& session, ParticipantType participant_type) |
3186 | +{ |
3187 | + std::unique_lock<std::mutex> lk(mutex); |
3188 | + |
3189 | + participant_by_session::iterator it = participant_index.find(boost::make_tuple(session, participant_type, prompt_session)); |
3190 | + if (it == participant_index.end()) |
3191 | + return false; |
3192 | + |
3193 | + participant_index.erase(it); |
3194 | + return true; |
3195 | +} |
3196 | + |
3197 | +void ms::PromptSessionContainer::for_each_participant_in_prompt_session( |
3198 | + PromptSession* prompt_session, |
3199 | + std::function<void(std::weak_ptr<Session> const&, ms::PromptSessionContainer::ParticipantType participant_type)> f) const |
3200 | +{ |
3201 | + std::unique_lock<std::mutex> lk(mutex); |
3202 | + |
3203 | + participant_by_prompt_session::iterator it,end; |
3204 | + boost::tie(it,end) = prompt_session_index.equal_range(prompt_session); |
3205 | + |
3206 | + for (; it != end; ++it) |
3207 | + { |
3208 | + Participant const& participant = *it; |
3209 | + f(participant.session, participant.participant_type); |
3210 | + } |
3211 | +} |
3212 | + |
3213 | +void ms::PromptSessionContainer::for_each_prompt_session_with_participant( |
3214 | + std::weak_ptr<Session> const& participant, |
3215 | + ParticipantType participant_type, |
3216 | + std::function<void(std::shared_ptr<PromptSession> const&)> f) const |
3217 | +{ |
3218 | + std::unique_lock<std::mutex> lk(mutex); |
3219 | + |
3220 | + participant_by_session::iterator it,end; |
3221 | + boost::tie(it,end) = participant_index.equal_range(boost::make_tuple(participant, participant_type)); |
3222 | + |
3223 | + for (; it != end; ++it) |
3224 | + { |
3225 | + Participant const& participant = *it; |
3226 | + |
3227 | + auto tsit = prompt_sessions.find(participant.prompt_session); |
3228 | + if (tsit != prompt_sessions.end()) |
3229 | + f(tsit->second); |
3230 | + } |
3231 | +} |
3232 | + |
3233 | +void ms::PromptSessionContainer::for_each_prompt_session_with_participant( |
3234 | + std::weak_ptr<Session> const& participant, |
3235 | + std::function<void(std::shared_ptr<PromptSession> const&, ParticipantType)> f) const |
3236 | +{ |
3237 | + std::unique_lock<std::mutex> lk(mutex); |
3238 | + participant_by_session::iterator it,end; |
3239 | + boost::tie(it,end) = participant_index.equal_range(participant); |
3240 | + |
3241 | + for (; it != end; ++it) |
3242 | + { |
3243 | + Participant const& participant = *it; |
3244 | + |
3245 | + auto tsit = prompt_sessions.find(participant.prompt_session); |
3246 | + if (tsit != prompt_sessions.end()) |
3247 | + f(tsit->second, participant.participant_type); |
3248 | + } |
3249 | +} |
3250 | + |
3251 | +void ms::PromptSessionContainer::insert_waiting_process( |
3252 | + PromptSession* prompt_session, |
3253 | + pid_t process_id) |
3254 | +{ |
3255 | + std::unique_lock<std::mutex> lk(mutex); |
3256 | + |
3257 | + // the prompt session must have first been added by insert_prompt_session. |
3258 | + if (prompt_sessions.find(prompt_session) == prompt_sessions.end()) |
3259 | + BOOST_THROW_EXCEPTION(std::runtime_error("Prompt Session does not exist")); |
3260 | + |
3261 | + waiting_process_map.insert(WaitingProcess{prompt_session, process_id}); |
3262 | +} |
3263 | + |
3264 | +void ms::PromptSessionContainer::for_each_prompt_session_expecting_process( |
3265 | + pid_t process_id, |
3266 | + std::function<void(std::shared_ptr<PromptSession> const&)> f) const |
3267 | +{ |
3268 | + std::unique_lock<std::mutex> lk(mutex); |
3269 | + |
3270 | + prompt_session_by_process::iterator it,end; |
3271 | + boost::tie(it,end) = waiting_process_index.equal_range(process_id); |
3272 | + |
3273 | + for (; it != end; ++it) |
3274 | + { |
3275 | + WaitingProcess const& waiting_process = *it; |
3276 | + auto tsit = prompt_sessions.find(waiting_process.prompt_session); |
3277 | + if (tsit != prompt_sessions.end()) |
3278 | + f(tsit->second); |
3279 | + } |
3280 | +} |
3281 | |
3282 | === added file 'src/server/scene/prompt_session_container.h' |
3283 | --- src/server/scene/prompt_session_container.h 1970-01-01 00:00:00 +0000 |
3284 | +++ src/server/scene/prompt_session_container.h 2014-06-16 15:01:17 +0000 |
3285 | @@ -0,0 +1,158 @@ |
3286 | +/* |
3287 | + * Copyright © 2014 Canonical Ltd. |
3288 | + * |
3289 | + * This program is free software: you can redistribute it and/or modify it |
3290 | + * under the terms of the GNU General Public License version 3, |
3291 | + * as published by the Free Software Foundation. |
3292 | + * |
3293 | + * This program is distributed in the hope that it will be useful, |
3294 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3295 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3296 | + * GNU General Public License for more details. |
3297 | + * |
3298 | + * You should have received a copy of the GNU General Public License |
3299 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3300 | + * |
3301 | + * Authored By: Nick Dedekind <nick.dedekind@canonical.com> |
3302 | + */ |
3303 | + |
3304 | +#ifndef MIR_SCENE_PROMPT_SESSION_CONTAINER_H_ |
3305 | +#define MIR_SCENE_PROMPT_SESSION_CONTAINER_H_ |
3306 | + |
3307 | +#include <sys/types.h> |
3308 | +#include <mutex> |
3309 | +#include <unordered_map> |
3310 | + |
3311 | +#include <boost/multi_index_container.hpp> |
3312 | +#include <boost/multi_index/member.hpp> |
3313 | +#include <boost/multi_index/ordered_index.hpp> |
3314 | +#include <boost/multi_index/composite_key.hpp> |
3315 | +#include <boost/multi_index/mem_fun.hpp> |
3316 | + |
3317 | +namespace mir |
3318 | +{ |
3319 | +using boost::multi_index_container; |
3320 | +using namespace boost::multi_index; |
3321 | + |
3322 | +namespace scene |
3323 | +{ |
3324 | +class Session; |
3325 | +class PromptSession; |
3326 | + |
3327 | +class PromptSessionContainer |
3328 | +{ |
3329 | +public: |
3330 | + PromptSessionContainer(); |
3331 | + virtual ~PromptSessionContainer() = default; |
3332 | + |
3333 | + enum class ParticipantType |
3334 | + { |
3335 | + helper, |
3336 | + application, |
3337 | + prompt_provider, |
3338 | + }; |
3339 | + |
3340 | + void insert_prompt_session(std::shared_ptr<PromptSession> const& prompt_session); |
3341 | + void remove_prompt_session(std::shared_ptr<PromptSession> const& prompt_session); |
3342 | + |
3343 | + bool insert_participant(PromptSession* prompt_session, std::weak_ptr<Session> const& session, ParticipantType participant_type); |
3344 | + bool remove_participant(PromptSession* prompt_session, std::weak_ptr<Session> const& session, ParticipantType participant_type); |
3345 | + |
3346 | + void for_each_participant_in_prompt_session(PromptSession* prompt_session, std::function<void(std::weak_ptr<Session> const&, ParticipantType)> f) const; |
3347 | + void for_each_prompt_session_with_participant(std::weak_ptr<Session> const& participant, ParticipantType participant_type, std::function<void(std::shared_ptr<PromptSession> const&)> f) const; |
3348 | + void for_each_prompt_session_with_participant(std::weak_ptr<Session> const& participant, std::function<void(std::shared_ptr<PromptSession> const&, ParticipantType)> f) const; |
3349 | + |
3350 | + void insert_waiting_process(PromptSession* prompt_session, pid_t process_id); |
3351 | + void for_each_prompt_session_expecting_process(pid_t process_id, std::function<void(std::shared_ptr<PromptSession> const&)> f) const; |
3352 | + |
3353 | +private: |
3354 | + std::mutex mutable mutex; |
3355 | + |
3356 | + std::unordered_map<PromptSession*, std::shared_ptr<PromptSession>> prompt_sessions; |
3357 | + |
3358 | + struct Participant |
3359 | + { |
3360 | + PromptSession* prompt_session; |
3361 | + std::weak_ptr<Session> session; |
3362 | + ParticipantType participant_type; |
3363 | + uint insert_order; |
3364 | + }; |
3365 | + |
3366 | + /** |
3367 | + * A multi map for associating PromptSessions <-> Sessions. |
3368 | + * indexed by insertion order for determining the Sessions participating in a PromptSession |
3369 | + * and indexed for determining the Prompt Sessions in which a Session is participating. |
3370 | + * A Session can be associated a number of times with a single PromptSession, providing it has a different type |
3371 | + * eg A Session can be both a helper and a provider for a PromptSession. |
3372 | + */ |
3373 | + typedef multi_index_container< |
3374 | + Participant, |
3375 | + indexed_by< |
3376 | + ordered_non_unique< |
3377 | + composite_key< |
3378 | + Participant, |
3379 | + member<Participant, PromptSession*, &Participant::prompt_session>, |
3380 | + member<Participant, uint, &Participant::insert_order> |
3381 | + > |
3382 | + >, |
3383 | + ordered_unique< |
3384 | + composite_key< |
3385 | + Participant, |
3386 | + member<Participant, std::weak_ptr<Session>, &Participant::session>, |
3387 | + member<Participant, ParticipantType, &Participant::participant_type>, |
3388 | + member<Participant, PromptSession*, &Participant::prompt_session> |
3389 | + >, |
3390 | + composite_key_compare< |
3391 | + std::owner_less<std::weak_ptr<Session>>, |
3392 | + std::less<ParticipantType>, |
3393 | + std::less<PromptSession*>> |
3394 | + > |
3395 | + > |
3396 | + > PromptSessionParticipants; |
3397 | + |
3398 | + typedef nth_index<PromptSessionParticipants,0>::type participant_by_prompt_session; |
3399 | + typedef nth_index<PromptSessionParticipants,1>::type participant_by_session; |
3400 | + |
3401 | + PromptSessionParticipants participant_map; |
3402 | + participant_by_prompt_session& prompt_session_index; |
3403 | + participant_by_session& participant_index; |
3404 | + |
3405 | + struct WaitingProcess |
3406 | + { |
3407 | + PromptSession* prompt_session; |
3408 | + pid_t process_id; |
3409 | + }; |
3410 | + |
3411 | + /** |
3412 | + * A multimap for associating PromptSessions <-> process ids |
3413 | + * indexed for determining which process ids a Prompt Session is waiting for |
3414 | + * and the prompt sessions which are waiting for a speicific process. |
3415 | + */ |
3416 | + typedef multi_index_container< |
3417 | + WaitingProcess, |
3418 | + indexed_by< |
3419 | + ordered_non_unique< |
3420 | + composite_key< |
3421 | + WaitingProcess, |
3422 | + member<WaitingProcess, PromptSession*, &WaitingProcess::prompt_session>, |
3423 | + member<WaitingProcess, pid_t, &WaitingProcess::process_id> |
3424 | + > |
3425 | + >, |
3426 | + ordered_non_unique< |
3427 | + member<WaitingProcess, pid_t, &WaitingProcess::process_id> |
3428 | + > |
3429 | + > |
3430 | + > WaitingPromptSessionsProcesses; |
3431 | + |
3432 | + typedef nth_index<WaitingPromptSessionsProcesses,0>::type process_by_prompt_session; |
3433 | + typedef nth_index<WaitingPromptSessionsProcesses,1>::type prompt_session_by_process; |
3434 | + |
3435 | + WaitingPromptSessionsProcesses waiting_process_map; |
3436 | + process_by_prompt_session& waiting_process_prompt_session_index; |
3437 | + prompt_session_by_process& waiting_process_index; |
3438 | +}; |
3439 | + |
3440 | +} |
3441 | +} |
3442 | + |
3443 | +#endif // MIR_SCENE_PROMPT_SESSION_CONTAINER_H_ |
3444 | |
3445 | === added file 'src/server/scene/prompt_session_manager_impl.cpp' |
3446 | --- src/server/scene/prompt_session_manager_impl.cpp 1970-01-01 00:00:00 +0000 |
3447 | +++ src/server/scene/prompt_session_manager_impl.cpp 2014-06-16 15:01:17 +0000 |
3448 | @@ -0,0 +1,232 @@ |
3449 | +/* |
3450 | + * Copyright © 2014 Canonical Ltd. |
3451 | + * |
3452 | + * This program is free software: you can redistribute it and/or modify it |
3453 | + * under the terms of the GNU General Public License version 3, |
3454 | + * as published by the Free Software Foundation. |
3455 | + * |
3456 | + * This program is distributed in the hope that it will be useful, |
3457 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3458 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3459 | + * GNU General Public License for more details. |
3460 | + * |
3461 | + * You should have received a copy of the GNU General Public License |
3462 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3463 | + * |
3464 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
3465 | + */ |
3466 | + |
3467 | +#include "prompt_session_manager_impl.h" |
3468 | + |
3469 | +#include "mir/scene/prompt_session_creation_parameters.h" |
3470 | +#include "mir/scene/prompt_session_listener.h" |
3471 | +#include "mir/scene/session.h" |
3472 | +#include "mir/scene/prompt_session.h" |
3473 | +#include "session_container.h" |
3474 | +#include "prompt_session_container.h" |
3475 | + |
3476 | +namespace ms = mir::scene; |
3477 | + |
3478 | +ms::PromptSessionManagerImpl::PromptSessionManagerImpl( |
3479 | + std::shared_ptr<SessionContainer> const& app_container, |
3480 | + std::shared_ptr<PromptSessionListener> const& prompt_session_listener) : |
3481 | + prompt_session_container(std::make_shared<PromptSessionContainer>()), |
3482 | + prompt_session_listener(prompt_session_listener), |
3483 | + app_container(app_container) |
3484 | +{ |
3485 | +} |
3486 | + |
3487 | +void ms::PromptSessionManagerImpl::stop_prompt_session_locked( |
3488 | + std::lock_guard<std::mutex> const&, |
3489 | + std::shared_ptr<PromptSession> const& prompt_session) const |
3490 | +{ |
3491 | + std::vector<std::shared_ptr<Session>> participants; |
3492 | + |
3493 | + prompt_session_container->for_each_participant_in_prompt_session(prompt_session.get(), |
3494 | + [&](std::weak_ptr<Session> const& session, PromptSessionContainer::ParticipantType type) |
3495 | + { |
3496 | + if (type == PromptSessionContainer::ParticipantType::helper) |
3497 | + { |
3498 | + if (auto locked_session = session.lock()) |
3499 | + locked_session->stop_prompt_session(); |
3500 | + } |
3501 | + else if (type == PromptSessionContainer::ParticipantType::prompt_provider) |
3502 | + { |
3503 | + if (auto locked_session = session.lock()) |
3504 | + participants.push_back(locked_session); |
3505 | + } |
3506 | + }); |
3507 | + |
3508 | + for (auto const& participant : participants) |
3509 | + { |
3510 | + if (prompt_session_container->remove_participant(prompt_session.get(), participant, PromptSessionContainer::ParticipantType::prompt_provider)) |
3511 | + prompt_session_listener->prompt_provider_removed(*prompt_session, participant); |
3512 | + } |
3513 | + |
3514 | + prompt_session_container->remove_prompt_session(prompt_session); |
3515 | + |
3516 | + prompt_session_listener->stopping(prompt_session); |
3517 | +} |
3518 | + |
3519 | +void ms::PromptSessionManagerImpl::remove_session(std::shared_ptr<Session> const& session) const |
3520 | +{ |
3521 | + std::lock_guard<std::mutex> lock(prompt_sessions_mutex); |
3522 | + |
3523 | + std::vector<std::pair<std::shared_ptr<PromptSession>, PromptSessionContainer::ParticipantType>> prompt_sessions; |
3524 | + |
3525 | + prompt_session_container->for_each_prompt_session_with_participant(session, |
3526 | + [&](std::shared_ptr<PromptSession> const& prompt_session, PromptSessionContainer::ParticipantType participant_type) |
3527 | + { |
3528 | + prompt_sessions.push_back(std::make_pair(prompt_session, participant_type)); |
3529 | + }); |
3530 | + |
3531 | + for(auto const& prompt_session : prompt_sessions) |
3532 | + { |
3533 | + if (prompt_session.second == PromptSessionContainer::ParticipantType::helper) |
3534 | + { |
3535 | + stop_prompt_session_locked(lock, prompt_session.first); |
3536 | + } |
3537 | + else |
3538 | + { |
3539 | + if (prompt_session_container->remove_participant(prompt_session.first.get(), session, prompt_session.second)) |
3540 | + { |
3541 | + if (prompt_session.second == PromptSessionContainer::ParticipantType::prompt_provider) |
3542 | + prompt_session_listener->prompt_provider_removed(*prompt_session.first, session); |
3543 | + } |
3544 | + } |
3545 | + } |
3546 | +} |
3547 | + |
3548 | +void ms::PromptSessionManagerImpl::stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) const |
3549 | +{ |
3550 | + std::lock_guard<std::mutex> lock(prompt_sessions_mutex); |
3551 | + |
3552 | + stop_prompt_session_locked(lock, prompt_session); |
3553 | +} |
3554 | + |
3555 | +void ms::PromptSessionManagerImpl::add_prompt_provider_by_pid_locked(std::lock_guard<std::mutex> const&, |
3556 | + std::shared_ptr<PromptSession> const& prompt_session, |
3557 | + pid_t process_id) const |
3558 | +{ |
3559 | + prompt_session_container->insert_waiting_process(prompt_session.get(), process_id); |
3560 | + |
3561 | + app_container->for_each( |
3562 | + [&](std::shared_ptr<Session> const& session) |
3563 | + { |
3564 | + if (session->process_id() == process_id) |
3565 | + { |
3566 | + if (prompt_session_container->insert_participant(prompt_session.get(), session, PromptSessionContainer::ParticipantType::prompt_provider)) |
3567 | + prompt_session_listener->prompt_provider_added(*prompt_session, session); |
3568 | + } |
3569 | + }); |
3570 | +} |
3571 | + |
3572 | +void ms::PromptSessionManagerImpl::add_prompt_provider_by_pid( |
3573 | + std::shared_ptr<PromptSession> const& prompt_session, |
3574 | + pid_t process_id) const |
3575 | +{ |
3576 | + std::lock_guard<std::mutex> lock(prompt_sessions_mutex); |
3577 | + |
3578 | + add_prompt_provider_by_pid_locked(lock, prompt_session, process_id); |
3579 | +} |
3580 | + |
3581 | +std::shared_ptr<ms::PromptSession> ms::PromptSessionManagerImpl::start_prompt_session_for( |
3582 | + std::shared_ptr<Session> const& session, |
3583 | + PromptSessionCreationParameters const& params) const |
3584 | +{ |
3585 | + auto prompt_session = std::make_shared<PromptSession>(); |
3586 | + |
3587 | + std::lock_guard<std::mutex> lock(prompt_sessions_mutex); |
3588 | + |
3589 | + prompt_session_container->insert_prompt_session(prompt_session); |
3590 | + if (!prompt_session_container->insert_participant(prompt_session.get(), session, PromptSessionContainer::ParticipantType::helper)) |
3591 | + BOOST_THROW_EXCEPTION(std::runtime_error("Could not set prompt session helper")); |
3592 | + |
3593 | + session->start_prompt_session(); |
3594 | + prompt_session_listener->starting(prompt_session); |
3595 | + |
3596 | + app_container->for_each( |
3597 | + [&](std::shared_ptr<Session> const& session) |
3598 | + { |
3599 | + if (session->process_id() == params.application_pid) |
3600 | + { |
3601 | + prompt_session_container->insert_participant(prompt_session.get(), session, PromptSessionContainer::ParticipantType::application); |
3602 | + } |
3603 | + }); |
3604 | + |
3605 | + return prompt_session; |
3606 | +} |
3607 | + |
3608 | +void ms::PromptSessionManagerImpl::add_expected_session(std::shared_ptr<Session> const& session) const |
3609 | +{ |
3610 | + std::unique_lock<std::mutex> lock(prompt_sessions_mutex); |
3611 | + |
3612 | + std::vector<std::shared_ptr<PromptSession>> prompt_sessions; |
3613 | + |
3614 | + prompt_session_container->for_each_prompt_session_expecting_process(session->process_id(), |
3615 | + [&](std::shared_ptr<PromptSession> const& prompt_session) |
3616 | + { |
3617 | + prompt_sessions.push_back(prompt_session); |
3618 | + }); |
3619 | + |
3620 | + for(auto const& prompt_session : prompt_sessions) |
3621 | + { |
3622 | + if (prompt_session_container->insert_participant(prompt_session.get(), session, PromptSessionContainer::ParticipantType::prompt_provider)) |
3623 | + prompt_session_listener->prompt_provider_added(*prompt_session, session); |
3624 | + } |
3625 | +} |
3626 | + |
3627 | +void ms::PromptSessionManagerImpl::add_prompt_provider( |
3628 | + std::shared_ptr<PromptSession> const& prompt_session, |
3629 | + std::shared_ptr<Session> const& prompt_provider) const |
3630 | +{ |
3631 | + std::unique_lock<std::mutex> lock(prompt_sessions_mutex); |
3632 | + |
3633 | + if (prompt_session_container->insert_participant(prompt_session.get(), prompt_provider, PromptSessionContainer::ParticipantType::prompt_provider)) |
3634 | + prompt_session_listener->prompt_provider_added(*prompt_session, prompt_provider); |
3635 | +} |
3636 | + |
3637 | +std::shared_ptr<ms::Session> ms::PromptSessionManagerImpl::application_for( |
3638 | + std::shared_ptr<PromptSession> const& prompt_session) const |
3639 | +{ |
3640 | + std::shared_ptr<Session> application_session; |
3641 | + std::unique_lock<std::mutex> lock(prompt_sessions_mutex); |
3642 | + |
3643 | + prompt_session_container->for_each_participant_in_prompt_session(prompt_session.get(), |
3644 | + [&](std::weak_ptr<Session> const& session, PromptSessionContainer::ParticipantType type) |
3645 | + { |
3646 | + if (type == PromptSessionContainer::ParticipantType::application) |
3647 | + application_session = session.lock(); |
3648 | + }); |
3649 | + return application_session; |
3650 | +} |
3651 | + |
3652 | +std::shared_ptr<ms::Session> ms::PromptSessionManagerImpl::helper_for( |
3653 | + std::shared_ptr<PromptSession> const& prompt_session) const |
3654 | +{ |
3655 | + std::shared_ptr<Session> helper_session; |
3656 | + std::unique_lock<std::mutex> lock(prompt_sessions_mutex); |
3657 | + |
3658 | + prompt_session_container->for_each_participant_in_prompt_session(prompt_session.get(), |
3659 | + [&](std::weak_ptr<Session> const& session, PromptSessionContainer::ParticipantType type) |
3660 | + { |
3661 | + if (type == PromptSessionContainer::ParticipantType::helper) |
3662 | + helper_session = session.lock(); |
3663 | + }); |
3664 | + return helper_session; |
3665 | +} |
3666 | + |
3667 | +void ms::PromptSessionManagerImpl::for_each_provider_in( |
3668 | + std::shared_ptr<PromptSession> const& prompt_session, |
3669 | + std::function<void(std::shared_ptr<Session> const& prompt_provider)> const& f) const |
3670 | +{ |
3671 | + std::unique_lock<std::mutex> lock(prompt_sessions_mutex); |
3672 | + |
3673 | + prompt_session_container->for_each_participant_in_prompt_session(prompt_session.get(), |
3674 | + [&](std::weak_ptr<Session> const& session, PromptSessionContainer::ParticipantType type) |
3675 | + { |
3676 | + if (type == PromptSessionContainer::ParticipantType::prompt_provider) |
3677 | + if (auto locked_session = session.lock()) |
3678 | + f(locked_session); |
3679 | + }); |
3680 | +} |
3681 | |
3682 | === added file 'src/server/scene/prompt_session_manager_impl.h' |
3683 | --- src/server/scene/prompt_session_manager_impl.h 1970-01-01 00:00:00 +0000 |
3684 | +++ src/server/scene/prompt_session_manager_impl.h 2014-06-16 15:01:17 +0000 |
3685 | @@ -0,0 +1,96 @@ |
3686 | +/* |
3687 | + * Copyright © 2014 Canonical Ltd. |
3688 | + * |
3689 | + * This program is free software: you can redistribute it and/or modify it |
3690 | + * under the terms of the GNU General Public License version 3, |
3691 | + * as published by the Free Software Foundation. |
3692 | + * |
3693 | + * This program is distributed in the hope that it will be useful, |
3694 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3695 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3696 | + * GNU General Public License for more details. |
3697 | + * |
3698 | + * You should have received a copy of the GNU General Public License |
3699 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3700 | + * |
3701 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
3702 | + */ |
3703 | + |
3704 | +#ifndef MIR_SCENE_PROMPT_SESSION_MANAGERIMPL_H_ |
3705 | +#define MIR_SCENE_PROMPT_SESSION_MANAGERIMPL_H_ |
3706 | + |
3707 | +#include "mir/scene/prompt_session_manager.h" |
3708 | +#include "mir_toolkit/common.h" |
3709 | + |
3710 | +#include <mutex> |
3711 | +#include <memory> |
3712 | + |
3713 | +namespace mir |
3714 | +{ |
3715 | +namespace scene |
3716 | +{ |
3717 | +class Session; |
3718 | +class SessionContainer; |
3719 | +class PromptSession; |
3720 | +class PromptSessionContainer; |
3721 | +class PromptSessionCreationParameters; |
3722 | +class PromptSessionListener; |
3723 | + |
3724 | +class PromptSessionManagerImpl : public scene::PromptSessionManager |
3725 | +{ |
3726 | +public: |
3727 | + explicit PromptSessionManagerImpl( |
3728 | + std::shared_ptr<SessionContainer> const& app_container, |
3729 | + std::shared_ptr<PromptSessionListener> const& prompt_session_listener); |
3730 | + |
3731 | + std::shared_ptr<PromptSession> start_prompt_session_for( |
3732 | + std::shared_ptr<Session> const& session, |
3733 | + PromptSessionCreationParameters const& params) const override; |
3734 | + |
3735 | + void stop_prompt_session( |
3736 | + std::shared_ptr<PromptSession> const& prompt_session) const override; |
3737 | + |
3738 | + void add_prompt_provider( |
3739 | + std::shared_ptr<PromptSession> const& prompt_session, |
3740 | + std::shared_ptr<Session> const& prompt_provider) const override; |
3741 | + |
3742 | + void add_prompt_provider_by_pid( |
3743 | + std::shared_ptr<PromptSession> const& prompt_session, |
3744 | + pid_t process_id) const override; |
3745 | + |
3746 | + void add_expected_session( |
3747 | + std::shared_ptr<Session> const& new_session) const override; |
3748 | + |
3749 | + void remove_session( |
3750 | + std::shared_ptr<Session> const& session) const override; |
3751 | + |
3752 | + std::shared_ptr<Session> application_for( |
3753 | + std::shared_ptr<PromptSession> const& prompt_session) const override; |
3754 | + |
3755 | + std::shared_ptr<Session> helper_for( |
3756 | + std::shared_ptr<PromptSession> const& prompt_session) const override; |
3757 | + |
3758 | + void for_each_provider_in( |
3759 | + std::shared_ptr<PromptSession> const& prompt_session, |
3760 | + std::function<void(std::shared_ptr<Session> const& prompt_provider)> const& f) const override; |
3761 | + |
3762 | +private: |
3763 | + std::shared_ptr<PromptSessionContainer> const prompt_session_container; |
3764 | + std::shared_ptr<PromptSessionListener> const prompt_session_listener; |
3765 | + std::shared_ptr<SessionContainer> const app_container; |
3766 | + |
3767 | + std::mutex mutable prompt_sessions_mutex; |
3768 | + |
3769 | + void add_prompt_provider_by_pid_locked( |
3770 | + std::lock_guard<std::mutex> const&, |
3771 | + std::shared_ptr<PromptSession> const& prompt_session, |
3772 | + pid_t process_id) const; |
3773 | + |
3774 | + void stop_prompt_session_locked( |
3775 | + std::lock_guard<std::mutex> const&, |
3776 | + std::shared_ptr<PromptSession> const& prompt_session) const; |
3777 | +}; |
3778 | +} |
3779 | +} |
3780 | + |
3781 | +#endif // MIR_SCENE_PROMPT_SESSION_MANAGERIMPL_H_ |
3782 | |
3783 | === modified file 'src/server/scene/session_manager.cpp' |
3784 | --- src/server/scene/session_manager.cpp 2014-04-15 05:31:19 +0000 |
3785 | +++ src/server/scene/session_manager.cpp 2014-06-16 15:01:17 +0000 |
3786 | @@ -23,6 +23,8 @@ |
3787 | #include "mir/shell/focus_setter.h" |
3788 | #include "mir/scene/session.h" |
3789 | #include "mir/scene/session_listener.h" |
3790 | +#include "mir/scene/prompt_session.h" |
3791 | +#include "mir/scene/prompt_session_manager.h" |
3792 | #include "session_event_sink.h" |
3793 | |
3794 | #include <memory> |
3795 | @@ -38,13 +40,15 @@ |
3796 | std::shared_ptr<msh::FocusSetter> const& focus_setter, |
3797 | std::shared_ptr<SnapshotStrategy> const& snapshot_strategy, |
3798 | std::shared_ptr<SessionEventSink> const& session_event_sink, |
3799 | - std::shared_ptr<SessionListener> const& session_listener) : |
3800 | + std::shared_ptr<SessionListener> const& session_listener, |
3801 | + std::shared_ptr<PromptSessionManager> const& prompt_session_manager) : |
3802 | surface_coordinator(surface_factory), |
3803 | app_container(container), |
3804 | focus_setter(focus_setter), |
3805 | snapshot_strategy(snapshot_strategy), |
3806 | session_event_sink(session_event_sink), |
3807 | - session_listener(session_listener) |
3808 | + session_listener(session_listener), |
3809 | + prompt_session_manager(prompt_session_manager) |
3810 | { |
3811 | assert(surface_factory); |
3812 | assert(container); |
3813 | @@ -52,7 +56,7 @@ |
3814 | assert(session_listener); |
3815 | } |
3816 | |
3817 | -ms::SessionManager::~SessionManager() |
3818 | +ms::SessionManager::~SessionManager() noexcept |
3819 | { |
3820 | /* |
3821 | * Close all open sessions. We need to do this manually here |
3822 | @@ -85,6 +89,8 @@ |
3823 | |
3824 | session_listener->starting(new_session); |
3825 | |
3826 | + prompt_session_manager->add_expected_session(new_session); |
3827 | + |
3828 | set_focus_to(new_session); |
3829 | |
3830 | return new_session; |
3831 | @@ -122,6 +128,9 @@ |
3832 | scene_session->force_requests_to_complete(); |
3833 | |
3834 | session_event_sink->handle_session_stopping(scene_session); |
3835 | + |
3836 | + prompt_session_manager->remove_session(scene_session); |
3837 | + |
3838 | session_listener->stopping(scene_session); |
3839 | |
3840 | app_container->remove_session(scene_session); |
3841 | @@ -169,3 +178,38 @@ |
3842 | { |
3843 | set_focus_to(std::dynamic_pointer_cast<Session>(session)); |
3844 | } |
3845 | + |
3846 | +std::shared_ptr<mf::PromptSession> ms::SessionManager::start_prompt_session_for(std::shared_ptr<mf::Session> const& session, |
3847 | + PromptSessionCreationParameters const& params) |
3848 | +{ |
3849 | + auto shell_session = std::dynamic_pointer_cast<Session>(session); |
3850 | + |
3851 | + return prompt_session_manager->start_prompt_session_for( |
3852 | + shell_session, params); |
3853 | + |
3854 | +} |
3855 | + |
3856 | +void ms::SessionManager::add_prompt_provider_process_for( |
3857 | + std::shared_ptr<mf::PromptSession> const& prompt_session, |
3858 | + pid_t process_id) |
3859 | +{ |
3860 | + auto scene_prompt_session = std::dynamic_pointer_cast<PromptSession>(prompt_session); |
3861 | + |
3862 | + prompt_session_manager->add_prompt_provider_by_pid(scene_prompt_session, process_id); |
3863 | +} |
3864 | + |
3865 | +void ms::SessionManager::add_prompt_provider_for( |
3866 | + std::shared_ptr<mf::PromptSession> const& prompt_session, |
3867 | + std::shared_ptr<frontend::Session> const& session) |
3868 | +{ |
3869 | + auto scene_prompt_session = std::dynamic_pointer_cast<PromptSession>(prompt_session); |
3870 | + auto scene_session = std::dynamic_pointer_cast<Session>(session); |
3871 | + |
3872 | + prompt_session_manager->add_prompt_provider(scene_prompt_session, scene_session); |
3873 | +} |
3874 | + |
3875 | +void ms::SessionManager::stop_prompt_session(std::shared_ptr<mf::PromptSession> const& prompt_session) |
3876 | +{ |
3877 | + auto scene_prompt_session = std::dynamic_pointer_cast<PromptSession>(prompt_session); |
3878 | + prompt_session_manager->stop_prompt_session(scene_prompt_session); |
3879 | +} |
3880 | |
3881 | === modified file 'src/server/scene/session_manager.h' |
3882 | --- src/server/scene/session_manager.h 2014-05-23 11:18:09 +0000 |
3883 | +++ src/server/scene/session_manager.h 2014-06-16 15:01:17 +0000 |
3884 | @@ -40,6 +40,8 @@ |
3885 | class SessionListener; |
3886 | class SnapshotStrategy; |
3887 | class SurfaceCoordinator; |
3888 | +class PromptSessionManager; |
3889 | + |
3890 | |
3891 | class SessionManager : public SessionCoordinator |
3892 | { |
3893 | @@ -49,8 +51,9 @@ |
3894 | std::shared_ptr<shell::FocusSetter> const& focus_setter, |
3895 | std::shared_ptr<SnapshotStrategy> const& snapshot_strategy, |
3896 | std::shared_ptr<SessionEventSink> const& session_event_sink, |
3897 | - std::shared_ptr<SessionListener> const& session_listener); |
3898 | - virtual ~SessionManager(); |
3899 | + std::shared_ptr<SessionListener> const& session_listener, |
3900 | + std::shared_ptr<PromptSessionManager> const& prompt_session_manager); |
3901 | + virtual ~SessionManager() noexcept; |
3902 | |
3903 | virtual std::shared_ptr<frontend::Session> open_session( |
3904 | pid_t client_pid, |
3905 | @@ -69,6 +72,14 @@ |
3906 | |
3907 | void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override; |
3908 | |
3909 | + std::shared_ptr<frontend::PromptSession> start_prompt_session_for(std::shared_ptr<frontend::Session> const& session, |
3910 | + PromptSessionCreationParameters const& params) override; |
3911 | + void add_prompt_provider_process_for(std::shared_ptr<frontend::PromptSession> const& prompt_session, |
3912 | + pid_t process_id) override; |
3913 | + void add_prompt_provider_for(std::shared_ptr<frontend::PromptSession> const& prompt_session, |
3914 | + std::shared_ptr<frontend::Session> const& session) override; |
3915 | + void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& prompt_session) override; |
3916 | + |
3917 | protected: |
3918 | SessionManager(const SessionManager&) = delete; |
3919 | SessionManager& operator=(const SessionManager&) = delete; |
3920 | @@ -80,6 +91,7 @@ |
3921 | std::shared_ptr<SnapshotStrategy> const snapshot_strategy; |
3922 | std::shared_ptr<SessionEventSink> const session_event_sink; |
3923 | std::shared_ptr<SessionListener> const session_listener; |
3924 | + std::shared_ptr<PromptSessionManager> const prompt_session_manager; |
3925 | |
3926 | std::mutex mutex; |
3927 | std::weak_ptr<Session> focus_application; |
3928 | |
3929 | === modified file 'src/server/shell/session_coordinator_wrapper.cpp' |
3930 | --- src/server/shell/session_coordinator_wrapper.cpp 2014-05-23 12:59:00 +0000 |
3931 | +++ src/server/shell/session_coordinator_wrapper.cpp 2014-06-16 15:01:17 +0000 |
3932 | @@ -32,7 +32,7 @@ |
3933 | std::shared_ptr<mf::Session> msh::SessionCoordinatorWrapper::open_session( |
3934 | pid_t client_pid, |
3935 | std::string const& name, |
3936 | - std::shared_ptr<frontend::EventSink> const& sink) |
3937 | + std::shared_ptr<mf::EventSink> const& sink) |
3938 | { |
3939 | return wrapped->open_session(client_pid, name, sink); |
3940 | } |
3941 | @@ -67,7 +67,33 @@ |
3942 | } |
3943 | |
3944 | void msh::SessionCoordinatorWrapper::handle_surface_created( |
3945 | - std::shared_ptr<frontend::Session> const& session) |
3946 | + std::shared_ptr<mf::Session> const& session) |
3947 | { |
3948 | wrapped->handle_surface_created(session); |
3949 | } |
3950 | + |
3951 | +std::shared_ptr<mf::PromptSession> msh::SessionCoordinatorWrapper::start_prompt_session_for( |
3952 | + std::shared_ptr<mf::Session> const& session, |
3953 | + scene::PromptSessionCreationParameters const& params) |
3954 | +{ |
3955 | + return wrapped->start_prompt_session_for(session, params); |
3956 | +} |
3957 | + |
3958 | +void msh::SessionCoordinatorWrapper::add_prompt_provider_process_for( |
3959 | + std::shared_ptr<mf::PromptSession> const& prompt_session, |
3960 | + pid_t process_id) |
3961 | +{ |
3962 | + wrapped->add_prompt_provider_process_for(prompt_session, process_id); |
3963 | +} |
3964 | + |
3965 | +void msh::SessionCoordinatorWrapper::add_prompt_provider_for( |
3966 | + std::shared_ptr<mf::PromptSession> const& prompt_session, |
3967 | + std::shared_ptr<mf::Session> const& session) |
3968 | +{ |
3969 | + wrapped->add_prompt_provider_for(prompt_session, session); |
3970 | +} |
3971 | + |
3972 | +void msh::SessionCoordinatorWrapper::stop_prompt_session(std::shared_ptr<mf::PromptSession> const& prompt_session) |
3973 | +{ |
3974 | + wrapped->stop_prompt_session(prompt_session); |
3975 | +} |
3976 | |
3977 | === modified file 'src/shared/protobuf/mir_protobuf.proto' |
3978 | --- src/shared/protobuf/mir_protobuf.proto 2014-06-02 17:07:02 +0000 |
3979 | +++ src/shared/protobuf/mir_protobuf.proto 2014-06-16 15:01:17 +0000 |
3980 | @@ -100,7 +100,7 @@ |
3981 | optional int32 pixel_format = 4; |
3982 | optional int32 buffer_usage = 5; |
3983 | optional Buffer buffer = 6; |
3984 | - |
3985 | + |
3986 | repeated sint32 fd = 7; |
3987 | optional int32 fds_on_side_channel = 8; |
3988 | |
3989 | @@ -185,7 +185,6 @@ |
3990 | required int32 number = 1; |
3991 | } |
3992 | |
3993 | - |
3994 | message SocketFD { |
3995 | repeated sint32 fd = 1; |
3996 | optional int32 fds_on_side_channel = 2; |
3997 | @@ -193,6 +192,14 @@ |
3998 | optional string error = 127; |
3999 | } |
4000 | |
4001 | +message PromptProvider { |
4002 | + required int32 pid = 1; |
4003 | +} |
4004 | + |
4005 | +message PromptSessionParameters { |
4006 | + required int32 application_pid = 1; |
4007 | +} |
4008 | + |
4009 | service DisplayServer { |
4010 | // Platform independent requests |
4011 | rpc connect(ConnectParameters) returns (Connection); |
4012 | @@ -212,7 +219,11 @@ |
4013 | rpc create_screencast(ScreencastParameters) returns (Screencast); |
4014 | rpc screencast_buffer(ScreencastId) returns (Buffer); |
4015 | rpc release_screencast(ScreencastId) returns (Void); |
4016 | - |
4017 | + |
4018 | rpc configure_cursor(CursorSetting) returns (Void); |
4019 | - rpc new_fds_for_trusted_clients(SocketFDRequest) returns (SocketFD); |
4020 | + rpc new_fds_for_prompt_providers(SocketFDRequest) returns (SocketFD); |
4021 | + |
4022 | + rpc start_prompt_session(PromptSessionParameters) returns (Void); |
4023 | + rpc add_prompt_provider(PromptProvider) returns (Void); |
4024 | + rpc stop_prompt_session(Void) returns (Void); |
4025 | } |
4026 | |
4027 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
4028 | --- tests/acceptance-tests/CMakeLists.txt 2014-06-10 13:45:51 +0000 |
4029 | +++ tests/acceptance-tests/CMakeLists.txt 2014-06-16 15:01:17 +0000 |
4030 | @@ -30,11 +30,11 @@ |
4031 | test_surfaces_with_output_id.cpp |
4032 | test_server_disconnect.cpp |
4033 | test_client_library_drm.cpp |
4034 | + test_prompt_session_client_api.cpp |
4035 | test_protobuf.cpp |
4036 | test_client_screencast.cpp |
4037 | test_client_surface_swap_buffers.cpp |
4038 | test_client_cursor_api.cpp |
4039 | - test_trust_session_helper.cpp |
4040 | test_large_messages.cpp |
4041 | ${GENERATED_PROTOBUF_SRCS} |
4042 | ${GENERATED_PROTOBUF_HDRS} |
4043 | |
4044 | === modified file 'tests/acceptance-tests/test_nested_mir.cpp' |
4045 | --- tests/acceptance-tests/test_nested_mir.cpp 2014-05-12 21:11:05 +0000 |
4046 | +++ tests/acceptance-tests/test_nested_mir.cpp 2014-06-16 15:01:17 +0000 |
4047 | @@ -56,6 +56,9 @@ |
4048 | MOCK_METHOD1(session_next_buffer_called, void (std::string const&)); |
4049 | MOCK_METHOD1(session_release_surface_called, void (std::string const&)); |
4050 | MOCK_METHOD1(session_disconnect_called, void (std::string const&)); |
4051 | + MOCK_METHOD2(session_start_prompt_session_called, void (std::string const&, pid_t)); |
4052 | + MOCK_METHOD2(session_add_prompt_provider_called, void (std::string const&, pid_t)); |
4053 | + MOCK_METHOD1(session_stop_prompt_session_called, void (std::string const&)); |
4054 | |
4055 | void session_drm_auth_magic_called(const std::string&) override {}; |
4056 | void session_configure_surface_called(std::string const&) override {}; |
4057 | |
4058 | === added file 'tests/acceptance-tests/test_prompt_session_client_api.cpp' |
4059 | --- tests/acceptance-tests/test_prompt_session_client_api.cpp 1970-01-01 00:00:00 +0000 |
4060 | +++ tests/acceptance-tests/test_prompt_session_client_api.cpp 2014-06-16 15:01:17 +0000 |
4061 | @@ -0,0 +1,421 @@ |
4062 | +/* |
4063 | + * Copyright © 2014 Canonical Ltd. |
4064 | + * |
4065 | + * This program is free software: you can redistribute it and/or modify |
4066 | + * it under the terms of the GNU General Public License version 3 as |
4067 | + * published by the Free Software Foundation. |
4068 | + * |
4069 | + * This program is distributed in the hope that it will be useful, |
4070 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4071 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4072 | + * GNU General Public License for more details. |
4073 | + * |
4074 | + * You should have received a copy of the GNU General Public License |
4075 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4076 | + * |
4077 | + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> |
4078 | + */ |
4079 | + |
4080 | +#include "mir_toolkit/mir_prompt_session.h" |
4081 | +#include "mir/scene/prompt_session_listener.h" |
4082 | +#include "mir/scene/prompt_session.h" |
4083 | +#include "mir/scene/prompt_session_manager.h" |
4084 | +#include "mir/scene/session.h" |
4085 | +#include "mir/frontend/shell.h" |
4086 | + |
4087 | +#include "mir_test_framework/stubbed_server_configuration.h" |
4088 | +#include "mir_test_framework/basic_client_server_fixture.h" |
4089 | +#include "mir_test/popen.h" |
4090 | + |
4091 | +#include <gtest/gtest.h> |
4092 | +#include <gmock/gmock.h> |
4093 | + |
4094 | +#include <condition_variable> |
4095 | +#include <mutex> |
4096 | + |
4097 | +namespace mtf = mir_test_framework; |
4098 | +namespace ms = mir::scene; |
4099 | +namespace mf = mir::frontend; |
4100 | + |
4101 | +using namespace testing; |
4102 | + |
4103 | +namespace |
4104 | +{ |
4105 | +struct MockPromptSessionListener : ms::PromptSessionListener |
4106 | +{ |
4107 | + MockPromptSessionListener(std::shared_ptr<ms::PromptSessionListener> const& wrapped) : |
4108 | + wrapped(wrapped) |
4109 | + { |
4110 | + ON_CALL(*this, starting(_)).WillByDefault(Invoke(wrapped.get(), &ms::PromptSessionListener::starting)); |
4111 | + ON_CALL(*this, stopping(_)).WillByDefault(Invoke(wrapped.get(), &ms::PromptSessionListener::stopping)); |
4112 | + ON_CALL(*this, prompt_provider_added(_, _)).WillByDefault(Invoke(wrapped.get(), &ms::PromptSessionListener::prompt_provider_added)); |
4113 | + ON_CALL(*this, prompt_provider_removed(_, _)).WillByDefault(Invoke(wrapped.get(), &ms::PromptSessionListener::prompt_provider_removed)); |
4114 | + } |
4115 | + |
4116 | + MOCK_METHOD1(starting, void(std::shared_ptr<ms::PromptSession> const& prompt_session)); |
4117 | + MOCK_METHOD1(stopping, void(std::shared_ptr<ms::PromptSession> const& prompt_session)); |
4118 | + |
4119 | + MOCK_METHOD2(prompt_provider_added, void(ms::PromptSession const& prompt_session, std::shared_ptr<ms::Session> const& prompt_provider)); |
4120 | + MOCK_METHOD2(prompt_provider_removed, void(ms::PromptSession const& prompt_session, std::shared_ptr<ms::Session> const& prompt_provider)); |
4121 | + |
4122 | + std::shared_ptr<ms::PromptSessionListener> const wrapped; |
4123 | +}; |
4124 | + |
4125 | +struct PromptSessionListenerConfiguration : mtf::StubbedServerConfiguration |
4126 | +{ |
4127 | + std::shared_ptr<ms::PromptSessionListener> the_prompt_session_listener() |
4128 | + { |
4129 | + return prompt_session_listener([this]() |
4130 | + ->std::shared_ptr<ms::PromptSessionListener> |
4131 | + { |
4132 | + return the_mock_prompt_session_listener(); |
4133 | + }); |
4134 | + } |
4135 | + |
4136 | + std::shared_ptr<MockPromptSessionListener> the_mock_prompt_session_listener() |
4137 | + { |
4138 | + return mock_prompt_session_listener([this] |
4139 | + { |
4140 | + return std::make_shared<NiceMock<MockPromptSessionListener>>( |
4141 | + mtf::StubbedServerConfiguration::the_prompt_session_listener()); |
4142 | + }); |
4143 | + } |
4144 | + |
4145 | + mir::CachedPtr<MockPromptSessionListener> mock_prompt_session_listener; |
4146 | +}; |
4147 | + |
4148 | +using BasicClientServerFixture = mtf::BasicClientServerFixture<PromptSessionListenerConfiguration>; |
4149 | + |
4150 | +struct PromptSessionClientAPI : BasicClientServerFixture |
4151 | +{ |
4152 | + static constexpr mir_prompt_session_state_change_callback null_state_change_callback = nullptr; |
4153 | + |
4154 | + static constexpr pid_t application_session_pid = __LINE__; |
4155 | + std::shared_ptr<mf::Session> application_session; |
4156 | + |
4157 | + static constexpr pid_t existing_prompt_provider_pid = __LINE__; |
4158 | + std::shared_ptr<mf::Session> existing_prompt_provider_session; |
4159 | + |
4160 | + static constexpr pid_t another_prompt_provider_pid = __LINE__; |
4161 | + std::shared_ptr<mf::Session> another_existing_prompt_provider; |
4162 | + |
4163 | + std::shared_ptr<ms::PromptSession> server_prompt_session; |
4164 | + |
4165 | + void SetUp() override |
4166 | + { |
4167 | + BasicClientServerFixture::SetUp(); |
4168 | + application_session = server_config().the_frontend_shell()->open_session(application_session_pid, __PRETTY_FUNCTION__, std::shared_ptr<mf::EventSink>()); |
4169 | + existing_prompt_provider_session = server_config().the_frontend_shell()->open_session(existing_prompt_provider_pid, __PRETTY_FUNCTION__, std::shared_ptr<mf::EventSink>()); |
4170 | + another_existing_prompt_provider = server_config().the_frontend_shell()->open_session(another_prompt_provider_pid, __PRETTY_FUNCTION__, std::shared_ptr<mf::EventSink>()); |
4171 | + } |
4172 | + |
4173 | + void capture_server_prompt_session() |
4174 | + { |
4175 | + EXPECT_CALL(*the_mock_prompt_session_listener(), starting(_)). |
4176 | + WillOnce(DoAll( |
4177 | + Invoke(the_mock_prompt_session_listener()->wrapped.get(), &ms::PromptSessionListener::starting), |
4178 | + SaveArg<0>(&server_prompt_session))); |
4179 | + } |
4180 | + |
4181 | + void TearDown() override |
4182 | + { |
4183 | + // TODO It really shouldn't be necessary to close these sessions. |
4184 | + // TODO But the MediatingDisplayChanger id destroyed without deregistering |
4185 | + // TODO callbacks from the BroadcastingSessionEventSink which gets called in |
4186 | + // TODO SessionManager::~SessionManager() in code that the comments claim |
4187 | + // TODO works around broken ownership. |
4188 | + server_config().the_frontend_shell()->close_session(another_existing_prompt_provider); |
4189 | + server_config().the_frontend_shell()->close_session(existing_prompt_provider_session); |
4190 | + server_config().the_frontend_shell()->close_session(application_session); |
4191 | + |
4192 | + BasicClientServerFixture::TearDown(); |
4193 | + } |
4194 | + |
4195 | + MockPromptSessionListener* the_mock_prompt_session_listener() |
4196 | + { |
4197 | + return server_configuration.the_mock_prompt_session_listener().get(); |
4198 | + } |
4199 | + |
4200 | + MOCK_METHOD2(prompt_session_state_change, void(MirPromptSession* prompt_provider, MirPromptSessionState state)); |
4201 | + |
4202 | + static std::size_t const arbritary_fd_request_count = 3; |
4203 | + std::mutex mutex; |
4204 | + std::size_t actual_fd_count = 0; |
4205 | + int actual_fds[arbritary_fd_request_count] = {}; |
4206 | + std::condition_variable cv; |
4207 | + bool called_back = false; |
4208 | + |
4209 | + bool wait_for_callback(std::chrono::milliseconds timeout) |
4210 | + { |
4211 | + std::unique_lock<decltype(mutex)> lock(mutex); |
4212 | + return cv.wait_for(lock, timeout, [this]{ return called_back; }); |
4213 | + } |
4214 | + |
4215 | + char const* fd_connect_string(int fd) |
4216 | + { |
4217 | + static char client_connect_string[32] = {0}; |
4218 | + |
4219 | + sprintf(client_connect_string, "fd://%d", fd); |
4220 | + return client_connect_string; |
4221 | + } |
4222 | + |
4223 | + MOCK_METHOD1(process_line, void(std::string const&)); |
4224 | + |
4225 | + std::vector<std::shared_ptr<mf::Session>> list_providers_for(std::shared_ptr<ms::PromptSession> const& prompt_session) |
4226 | + { |
4227 | + std::vector<std::shared_ptr<mf::Session>> results; |
4228 | + auto providers_fn = [&results](std::weak_ptr<ms::Session> const& session) |
4229 | + { |
4230 | + results.push_back(session.lock()); |
4231 | + }; |
4232 | + |
4233 | + server_configuration.the_prompt_session_manager()->for_each_provider_in(prompt_session, providers_fn); |
4234 | + |
4235 | + return results; |
4236 | + } |
4237 | +}; |
4238 | + |
4239 | +extern "C" void prompt_session_state_change_callback(MirPromptSession* prompt_provider, MirPromptSessionState state, void* context) |
4240 | +{ |
4241 | + PromptSessionClientAPI* self = static_cast<PromptSessionClientAPI*>(context); |
4242 | + self->prompt_session_state_change(prompt_provider, state); |
4243 | +} |
4244 | + |
4245 | +void client_fd_callback(MirPromptSession*, size_t count, int const* fds, void* context) |
4246 | +{ |
4247 | + auto const self = static_cast<PromptSessionClientAPI*>(context); |
4248 | + |
4249 | + std::unique_lock<decltype(self->mutex)> lock(self->mutex); |
4250 | + self->actual_fd_count = count; |
4251 | + |
4252 | + std::copy(fds, fds+count, self->actual_fds); |
4253 | + self->called_back = true; |
4254 | + self->cv.notify_one(); |
4255 | +} |
4256 | + |
4257 | +struct DummyPromptProvider |
4258 | +{ |
4259 | + DummyPromptProvider(char const* connect_string, char const* app_name) : |
4260 | + connection{mir_connect_sync(connect_string, app_name)} |
4261 | + { |
4262 | + EXPECT_THAT(connection, NotNull()); |
4263 | + } |
4264 | + |
4265 | + ~DummyPromptProvider() noexcept |
4266 | + { |
4267 | + mir_connection_release(connection); |
4268 | + } |
4269 | + |
4270 | + MirConnection* const connection; |
4271 | +}; |
4272 | + |
4273 | +MATCHER_P(SessionWithPid, pid, "") |
4274 | +{ |
4275 | + return arg->process_id() == pid; |
4276 | +} |
4277 | + |
4278 | +MATCHER_P(SessionWithName, name, "") |
4279 | +{ |
4280 | + return arg->name() == name; |
4281 | +} |
4282 | +} |
4283 | + |
4284 | +TEST_F(PromptSessionClientAPI, can_start_and_stop_a_prompt_session) |
4285 | +{ |
4286 | + { |
4287 | + InSequence server_seq; |
4288 | + EXPECT_CALL(*the_mock_prompt_session_listener(), starting(_)); |
4289 | + EXPECT_CALL(*the_mock_prompt_session_listener(), stopping(_)); |
4290 | + } |
4291 | + |
4292 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4293 | + connection, application_session_pid, null_state_change_callback, this); |
4294 | + ASSERT_THAT(prompt_session, Ne(nullptr)); |
4295 | + |
4296 | + mir_prompt_session_release_sync(prompt_session); |
4297 | +} |
4298 | + |
4299 | +TEST_F(PromptSessionClientAPI, notifies_start_and_stop) |
4300 | +{ |
4301 | + InSequence seq; |
4302 | + EXPECT_CALL(*this, prompt_session_state_change(_, mir_prompt_session_state_started)); |
4303 | + EXPECT_CALL(*this, prompt_session_state_change(_, mir_prompt_session_state_stopped)); |
4304 | + |
4305 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4306 | + connection, application_session_pid, prompt_session_state_change_callback, this); |
4307 | + |
4308 | + mir_prompt_session_release_sync(prompt_session); |
4309 | +} |
4310 | + |
4311 | +TEST_F(PromptSessionClientAPI, can_add_preexisting_prompt_provider) |
4312 | +{ |
4313 | + { |
4314 | + auto const prompt_provider = std::dynamic_pointer_cast<ms::Session>(existing_prompt_provider_session); |
4315 | + InSequence server_seq; |
4316 | + EXPECT_CALL(*the_mock_prompt_session_listener(), prompt_provider_added(_, Eq(prompt_provider))); |
4317 | + EXPECT_CALL(*the_mock_prompt_session_listener(), prompt_provider_removed(_, Eq(prompt_provider))); |
4318 | + } |
4319 | + |
4320 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4321 | + connection, application_session_pid, null_state_change_callback, this); |
4322 | + |
4323 | + EXPECT_TRUE(mir_prompt_session_add_prompt_provider_sync(prompt_session, existing_prompt_provider_pid)); |
4324 | + |
4325 | + mir_prompt_session_release_sync(prompt_session); |
4326 | +} |
4327 | + |
4328 | +TEST_F(PromptSessionClientAPI, can_get_fds_for_prompt_providers) |
4329 | +{ |
4330 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4331 | + connection, application_session_pid, null_state_change_callback, this); |
4332 | + |
4333 | + mir_prompt_session_new_fds_for_prompt_providers(prompt_session, arbritary_fd_request_count, &client_fd_callback, this); |
4334 | + EXPECT_TRUE(wait_for_callback(std::chrono::milliseconds(500))); |
4335 | + |
4336 | + EXPECT_THAT(actual_fd_count, Eq(arbritary_fd_request_count)); |
4337 | + |
4338 | + mir_prompt_session_release_sync(prompt_session); |
4339 | +} |
4340 | + |
4341 | +TEST_F(PromptSessionClientAPI, when_prompt_provider_connects_over_fd_prompt_provider_added_with_right_pid) |
4342 | +{ |
4343 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4344 | + connection, application_session_pid, null_state_change_callback, this); |
4345 | + |
4346 | + mir_prompt_session_new_fds_for_prompt_providers(prompt_session, 1, &client_fd_callback, this); |
4347 | + ASSERT_TRUE(wait_for_callback(std::chrono::milliseconds(500))); |
4348 | + |
4349 | + auto const expected_pid = getpid(); |
4350 | + |
4351 | + EXPECT_CALL(*the_mock_prompt_session_listener(), prompt_provider_added(_, SessionWithPid(expected_pid))); |
4352 | + |
4353 | + DummyPromptProvider{fd_connect_string(actual_fds[0]), __PRETTY_FUNCTION__}; |
4354 | + |
4355 | + mir_prompt_session_release_sync(prompt_session); |
4356 | +} |
4357 | + |
4358 | +// TODO we need a nice way to run this (and similar tests that require a separate client process) in CI |
4359 | +// Disabled as we can't be sure the mir_demo_client_basic is about |
4360 | +TEST_F(PromptSessionClientAPI, DISABLED_client_pid_is_associated_with_session) |
4361 | +{ |
4362 | + auto const server_pid = getpid(); |
4363 | + |
4364 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4365 | + connection, application_session_pid, null_state_change_callback, this); |
4366 | + |
4367 | + mir_prompt_session_new_fds_for_prompt_providers(prompt_session, 1, &client_fd_callback, this); |
4368 | + wait_for_callback(std::chrono::milliseconds(500)); |
4369 | + |
4370 | + EXPECT_CALL(*the_mock_prompt_session_listener(), prompt_provider_added(_, Not(SessionWithPid(server_pid)))); |
4371 | + |
4372 | + InSequence seq; |
4373 | + EXPECT_CALL(*this, process_line(StrEq("Starting"))); |
4374 | + EXPECT_CALL(*this, process_line(StrEq("Connected"))); |
4375 | + EXPECT_CALL(*this, process_line(StrEq("Surface created"))); |
4376 | + EXPECT_CALL(*this, process_line(StrEq("Surface released"))); |
4377 | + EXPECT_CALL(*this, process_line(StrEq("Connection released"))); |
4378 | + |
4379 | + mir::test::Popen output(std::string("bin/mir_demo_client_basic -m ") + fd_connect_string(actual_fds[0])); |
4380 | + |
4381 | + std::string line; |
4382 | + while (output.get_line(line)) process_line(line); |
4383 | + |
4384 | + mir_prompt_session_release_sync(prompt_session); |
4385 | +} |
4386 | + |
4387 | +TEST_F(PromptSessionClientAPI, notifies_when_server_closes_prompt_session) |
4388 | +{ |
4389 | + EXPECT_CALL(*this, prompt_session_state_change(_, mir_prompt_session_state_started)); |
4390 | + |
4391 | + capture_server_prompt_session(); |
4392 | + |
4393 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4394 | + connection, application_session_pid, prompt_session_state_change_callback, this); |
4395 | + |
4396 | + EXPECT_CALL(*this, prompt_session_state_change(_, mir_prompt_session_state_stopped)); |
4397 | + |
4398 | + server_configuration.the_prompt_session_manager()->stop_prompt_session(server_prompt_session); |
4399 | + |
4400 | + // Verify we have got the "stopped" notification before we go on and release the session |
4401 | + Mock::VerifyAndClearExpectations(the_mock_prompt_session_listener()); |
4402 | + |
4403 | + mir_prompt_session_release_sync(prompt_session); |
4404 | +} |
4405 | + |
4406 | +TEST_F(PromptSessionClientAPI, after_server_closes_prompt_session_api_isnt_broken) |
4407 | +{ |
4408 | + capture_server_prompt_session(); |
4409 | + |
4410 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4411 | + connection, application_session_pid, null_state_change_callback, this); |
4412 | + |
4413 | + server_configuration.the_prompt_session_manager()->stop_prompt_session(server_prompt_session); |
4414 | + |
4415 | + EXPECT_FALSE(mir_prompt_session_add_prompt_provider_sync(prompt_session, existing_prompt_provider_pid)); |
4416 | + |
4417 | + mir_prompt_session_release_sync(prompt_session); |
4418 | +} |
4419 | + |
4420 | +TEST_F(PromptSessionClientAPI, server_retrieves_application_session) |
4421 | +{ |
4422 | + capture_server_prompt_session(); |
4423 | + |
4424 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4425 | + connection, application_session_pid, null_state_change_callback, this); |
4426 | + |
4427 | + EXPECT_THAT(server_configuration.the_prompt_session_manager()->application_for(server_prompt_session), Eq(application_session)); |
4428 | + |
4429 | + mir_prompt_session_release_sync(prompt_session); |
4430 | +} |
4431 | + |
4432 | +TEST_F(PromptSessionClientAPI, server_retrieves_helper_session) |
4433 | +{ |
4434 | + capture_server_prompt_session(); |
4435 | + |
4436 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4437 | + connection, application_session_pid, null_state_change_callback, this); |
4438 | + |
4439 | + // can get the helper session. but it will be the current pid. |
4440 | + EXPECT_THAT(server_configuration.the_prompt_session_manager()->helper_for(server_prompt_session), SessionWithPid(getpid())); |
4441 | + |
4442 | + mir_prompt_session_release_sync(prompt_session); |
4443 | +} |
4444 | + |
4445 | +TEST_F(PromptSessionClientAPI, server_retrieves_existing_provider_sessions) |
4446 | +{ |
4447 | + capture_server_prompt_session(); |
4448 | + |
4449 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4450 | + connection, application_session_pid, null_state_change_callback, this); |
4451 | + |
4452 | + mir_prompt_session_add_prompt_provider_sync(prompt_session, existing_prompt_provider_pid); |
4453 | + mir_prompt_session_add_prompt_provider_sync(prompt_session, another_prompt_provider_pid); |
4454 | + |
4455 | + EXPECT_THAT(list_providers_for(server_prompt_session), ElementsAre(existing_prompt_provider_session, another_existing_prompt_provider)); |
4456 | + |
4457 | + mir_prompt_session_release_sync(prompt_session); |
4458 | +} |
4459 | + |
4460 | +TEST_F(PromptSessionClientAPI, server_retrieves_child_provider_sessions) |
4461 | +{ |
4462 | + static int const no_of_prompt_providers = 2; |
4463 | + char const* const child_provider_name[no_of_prompt_providers] = |
4464 | + { |
4465 | + "child_provider0", |
4466 | + "child_provider1" |
4467 | + }; |
4468 | + |
4469 | + capture_server_prompt_session(); |
4470 | + |
4471 | + MirPromptSession* prompt_session = mir_connection_create_prompt_session_sync( |
4472 | + connection, application_session_pid, null_state_change_callback, this); |
4473 | + |
4474 | + mir_wait_for(mir_prompt_session_new_fds_for_prompt_providers(prompt_session, no_of_prompt_providers, &client_fd_callback, this)); |
4475 | + |
4476 | + DummyPromptProvider child_provider1{fd_connect_string(actual_fds[0]), child_provider_name[0]}; |
4477 | + DummyPromptProvider child_provider2{fd_connect_string(actual_fds[1]), child_provider_name[1]}; |
4478 | + |
4479 | + EXPECT_THAT(list_providers_for(server_prompt_session), ElementsAre(SessionWithName(child_provider_name[0]), SessionWithName(child_provider_name[1]))); |
4480 | + |
4481 | + mir_prompt_session_release_sync(prompt_session); |
4482 | +} |
4483 | |
4484 | === removed file 'tests/acceptance-tests/test_trust_session_helper.cpp' |
4485 | --- tests/acceptance-tests/test_trust_session_helper.cpp 2014-06-03 16:43:38 +0000 |
4486 | +++ tests/acceptance-tests/test_trust_session_helper.cpp 1970-01-01 00:00:00 +0000 |
4487 | @@ -1,218 +0,0 @@ |
4488 | -/* |
4489 | - * Copyright © 2014 Canonical Ltd. |
4490 | - * |
4491 | - * This program is free software: you can redistribute it and/or modify it |
4492 | - * under the terms of the GNU General Public License version 3, |
4493 | - * as published by the Free Software Foundation. |
4494 | - * |
4495 | - * This program is distributed in the hope that it will be useful, |
4496 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4497 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4498 | - * GNU General Public License for more details. |
4499 | - * |
4500 | - * You should have received a copy of the GNU General Public License |
4501 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4502 | - * |
4503 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
4504 | - */ |
4505 | - |
4506 | -#include "mir_toolkit/mir_client_library.h" |
4507 | - |
4508 | -#include "src/server/frontend/session_mediator.h" |
4509 | - |
4510 | -#include "mir/frontend/connection_context.h" |
4511 | -#include "mir/scene/session.h" |
4512 | -#include "mir/graphics/graphic_buffer_allocator.h" |
4513 | - |
4514 | -#include "mir_test_framework/stubbed_server_configuration.h" |
4515 | -#include "mir_test_framework/basic_client_server_fixture.h" |
4516 | -#include "mir_test_doubles/fake_ipc_factory.h" |
4517 | -#include "mir_test/popen.h" |
4518 | - |
4519 | -#include <gtest/gtest.h> |
4520 | -#include <gmock/gmock.h> |
4521 | - |
4522 | -#include <algorithm> |
4523 | -#include <condition_variable> |
4524 | -#include <mutex> |
4525 | - |
4526 | -using namespace testing; |
4527 | - |
4528 | -namespace |
4529 | -{ |
4530 | -struct TrustedHelperSessionMediator : mir::frontend::SessionMediator |
4531 | -{ |
4532 | - using mir::frontend::SessionMediator::SessionMediator; |
4533 | - |
4534 | - std::function<void(std::shared_ptr<mir::frontend::Session> const&)> trusted_connect_handler() const override |
4535 | - { |
4536 | - return [this](std::shared_ptr<mir::frontend::Session> const& session) |
4537 | - { |
4538 | - auto const ss = std::dynamic_pointer_cast<mir::scene::Session>(session); |
4539 | - client_pid = ss->process_id(); |
4540 | - }; |
4541 | - } |
4542 | - |
4543 | - pid_t mutable client_pid = 0; |
4544 | -}; |
4545 | - |
4546 | -std::shared_ptr<TrustedHelperSessionMediator> trusted_helper_mediator; |
4547 | - |
4548 | -struct FakeIpcFactory : mir::test::doubles::FakeIpcFactory |
4549 | -{ |
4550 | - using mir::test::doubles::FakeIpcFactory::FakeIpcFactory; |
4551 | - |
4552 | - std::shared_ptr<mir::frontend::detail::DisplayServer> make_helper_mediator( |
4553 | - std::shared_ptr<mir::frontend::Shell> const& shell, |
4554 | - std::shared_ptr<mir::graphics::Platform> const& graphics_platform, |
4555 | - std::shared_ptr<mir::frontend::DisplayChanger> const& changer, |
4556 | - std::shared_ptr<mir::graphics::GraphicBufferAllocator> const& buffer_allocator, |
4557 | - std::shared_ptr<mir::frontend::SessionMediatorReport> const& sm_report, |
4558 | - std::shared_ptr<mir::frontend::EventSink> const& sink, |
4559 | - std::shared_ptr<mir::frontend::Screencast> const& effective_screencast, |
4560 | - mir::frontend::ConnectionContext const& connection_context, |
4561 | - std::shared_ptr<mir::graphics::CursorImages> const& cursor_images) |
4562 | - { |
4563 | - trusted_helper_mediator = std::make_shared<TrustedHelperSessionMediator>( |
4564 | - shell, |
4565 | - graphics_platform, |
4566 | - changer, |
4567 | - buffer_allocator->supported_pixel_formats(), |
4568 | - sm_report, |
4569 | - sink, |
4570 | - resource_cache(), |
4571 | - effective_screencast, |
4572 | - connection_context, |
4573 | - cursor_images); |
4574 | - |
4575 | - return trusted_helper_mediator; |
4576 | - } |
4577 | -}; |
4578 | - |
4579 | -struct MyServerConfiguration : mir_test_framework::StubbedServerConfiguration |
4580 | -{ |
4581 | - std::shared_ptr<FakeIpcFactory> mediator_factory; |
4582 | - |
4583 | - auto the_ipc_factory( |
4584 | - std::shared_ptr<mir::frontend::Shell> const& shell, |
4585 | - std::shared_ptr<mir::graphics::GraphicBufferAllocator> const& allocator) |
4586 | - -> std::shared_ptr<mir::frontend::ProtobufIpcFactory> override |
4587 | - { |
4588 | - return ipc_factory( |
4589 | - [&]() |
4590 | - { |
4591 | - mediator_factory = std::make_shared<FakeIpcFactory>( |
4592 | - shell, |
4593 | - the_session_mediator_report(), |
4594 | - the_graphics_platform(), |
4595 | - the_frontend_display_changer(), |
4596 | - allocator, |
4597 | - the_screencast(), |
4598 | - the_session_authorizer(), |
4599 | - the_cursor_images()); |
4600 | - |
4601 | - EXPECT_CALL(*mediator_factory, |
4602 | - make_mediator(_, _, _, _, _, _, _, _, _)).Times(AnyNumber()) |
4603 | - .WillOnce(Invoke(mediator_factory.get(), &FakeIpcFactory::make_helper_mediator)) |
4604 | - .WillRepeatedly(Invoke(mediator_factory.get(), &FakeIpcFactory::make_default_mediator)); |
4605 | - |
4606 | - return mediator_factory; |
4607 | - }); |
4608 | - } |
4609 | -}; |
4610 | - |
4611 | -using MyBasicClientServerFixture = mir_test_framework::BasicClientServerFixture<MyServerConfiguration>; |
4612 | - |
4613 | -struct TrustSessionHelper : MyBasicClientServerFixture |
4614 | -{ |
4615 | - |
4616 | - void TearDown() |
4617 | - { |
4618 | - trusted_helper_mediator.reset(); |
4619 | - MyBasicClientServerFixture::TearDown(); |
4620 | - } |
4621 | - |
4622 | - static std::size_t const arbritary_fd_request_count = 3; |
4623 | - |
4624 | - std::mutex mutex; |
4625 | - std::size_t actual_fd_count = 0; |
4626 | - int actual_fds[arbritary_fd_request_count] = {}; |
4627 | - std::condition_variable cv; |
4628 | - bool called_back = false; |
4629 | - |
4630 | - bool wait_for_callback(std::chrono::milliseconds timeout) |
4631 | - { |
4632 | - std::unique_lock<decltype(mutex)> lock(mutex); |
4633 | - return cv.wait_for(lock, timeout, [this]{ return called_back; }); |
4634 | - } |
4635 | - |
4636 | - char client_connect_string[128] = {0}; |
4637 | - |
4638 | - char const* fd_connect_string(int fd) |
4639 | - { |
4640 | - sprintf(client_connect_string, "fd://%d", fd); |
4641 | - return client_connect_string; |
4642 | - } |
4643 | - |
4644 | - MOCK_METHOD1(process_line, void(std::string const&)); |
4645 | -}; |
4646 | - |
4647 | -void client_fd_callback(MirConnection*, size_t count, int const* fds, void* context) |
4648 | -{ |
4649 | - auto const self = static_cast<TrustSessionHelper*>(context); |
4650 | - |
4651 | - std::unique_lock<decltype(self->mutex)> lock(self->mutex); |
4652 | - self->actual_fd_count = count; |
4653 | - |
4654 | - std::copy(fds, fds+count, self->actual_fds); |
4655 | - self->called_back = true; |
4656 | - self->cv.notify_one(); |
4657 | -} |
4658 | -} |
4659 | - |
4660 | -TEST_F(TrustSessionHelper, can_get_fds_for_trusted_clients) |
4661 | -{ |
4662 | - mir_connection_new_fds_for_trusted_clients(connection, arbritary_fd_request_count, &client_fd_callback, this); |
4663 | - EXPECT_TRUE(wait_for_callback(std::chrono::milliseconds(500))); |
4664 | - |
4665 | - EXPECT_THAT(actual_fd_count, Eq(arbritary_fd_request_count)); |
4666 | -} |
4667 | - |
4668 | -TEST_F(TrustSessionHelper, gets_pid_when_trusted_client_connects_over_fd) |
4669 | -{ |
4670 | - mir_connection_new_fds_for_trusted_clients(connection, 1, &client_fd_callback, this); |
4671 | - wait_for_callback(std::chrono::milliseconds(500)); |
4672 | - |
4673 | - auto const expected_pid = getpid(); |
4674 | - |
4675 | - EXPECT_THAT(trusted_helper_mediator->client_pid, Eq(0)); // Before the client connects we don't have a pid |
4676 | - auto client_connection = mir_connect_sync(fd_connect_string(actual_fds[0]), __PRETTY_FUNCTION__); |
4677 | - EXPECT_THAT(trusted_helper_mediator->client_pid, Eq(expected_pid)); // After the client connects we do have a pid |
4678 | - |
4679 | - mir_connection_release(client_connection); |
4680 | -} |
4681 | - |
4682 | -// TODO we need a nice way to run this (and similar tests that require a separate client process) in CI |
4683 | -// Disabled as we can't be sure the mir_demo_client_basic is about |
4684 | -TEST_F(TrustSessionHelper, DISABLED_client_pid_is_associated_with_session) |
4685 | -{ |
4686 | - auto const server_pid = getpid(); |
4687 | - |
4688 | - mir_connection_new_fds_for_trusted_clients(connection, 1, &client_fd_callback, this); |
4689 | - wait_for_callback(std::chrono::milliseconds(500)); |
4690 | - |
4691 | - InSequence seq; |
4692 | - EXPECT_CALL(*this, process_line(StrEq("Starting"))); |
4693 | - EXPECT_CALL(*this, process_line(StrEq("Connected"))); |
4694 | - EXPECT_CALL(*this, process_line(StrEq("Surface created"))); |
4695 | - EXPECT_CALL(*this, process_line(StrEq("Surface released"))); |
4696 | - EXPECT_CALL(*this, process_line(StrEq("Connection released"))); |
4697 | - |
4698 | - mir::test::Popen output(std::string("bin/mir_demo_client_basic -m ") + fd_connect_string(actual_fds[0])); |
4699 | - |
4700 | - std::string line; |
4701 | - while (output.get_line(line)) process_line(line); |
4702 | - |
4703 | - EXPECT_THAT(trusted_helper_mediator->client_pid, Ne(0)); |
4704 | - EXPECT_THAT(trusted_helper_mediator->client_pid, Ne(server_pid)); |
4705 | -} |
4706 | |
4707 | === modified file 'tests/integration-tests/frontend/test_application_mediator_report.cpp' |
4708 | --- tests/integration-tests/frontend/test_application_mediator_report.cpp 2014-05-12 21:11:05 +0000 |
4709 | +++ tests/integration-tests/frontend/test_application_mediator_report.cpp 2014-06-16 15:01:17 +0000 |
4710 | @@ -50,6 +50,12 @@ |
4711 | |
4712 | EXPECT_CALL(*this, session_disconnect_called(testing::_)). |
4713 | Times(testing::AtLeast(0)); |
4714 | + |
4715 | + EXPECT_CALL(*this, session_start_prompt_session_called(testing::_, testing::_)). |
4716 | + Times(testing::AtLeast(0)); |
4717 | + |
4718 | + EXPECT_CALL(*this, session_stop_prompt_session_called(testing::_)). |
4719 | + Times(testing::AtLeast(0)); |
4720 | } |
4721 | |
4722 | MOCK_METHOD1(session_connect_called, void (std::string const&)); |
4723 | @@ -57,6 +63,9 @@ |
4724 | MOCK_METHOD1(session_next_buffer_called, void (std::string const&)); |
4725 | MOCK_METHOD1(session_release_surface_called, void (std::string const&)); |
4726 | MOCK_METHOD1(session_disconnect_called, void (std::string const&)); |
4727 | + MOCK_METHOD2(session_start_prompt_session_called, void (std::string const&, pid_t)); |
4728 | + MOCK_METHOD2(session_add_prompt_provider_called, void (std::string const&, pid_t)); |
4729 | + MOCK_METHOD1(session_stop_prompt_session_called, void (std::string const&)); |
4730 | |
4731 | void session_drm_auth_magic_called(const std::string&) override {}; |
4732 | void session_configure_surface_called(std::string const&) override {}; |
4733 | @@ -359,3 +368,175 @@ |
4734 | |
4735 | launch_client_process(client_process); |
4736 | } |
4737 | + |
4738 | +TEST_F(ApplicationMediatorReport, prompt_session_start_called) |
4739 | +{ |
4740 | + struct Server : TestingServerConfiguration |
4741 | + { |
4742 | + std::shared_ptr<mf::SessionMediatorReport> |
4743 | + the_application_mediator_report() |
4744 | + { |
4745 | + auto result = std::make_shared<MockApplicationMediatorReport>(); |
4746 | + |
4747 | + EXPECT_CALL(*result, session_start_prompt_session_called(testing::_, testing::_)). |
4748 | + Times(1); |
4749 | + |
4750 | + return result; |
4751 | + } |
4752 | + } server_processing; |
4753 | + |
4754 | + launch_server_process(server_processing); |
4755 | + |
4756 | + struct Client: TestingClientConfiguration |
4757 | + { |
4758 | + void exec() |
4759 | + { |
4760 | + mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms); |
4761 | + |
4762 | + client.connect_parameters.set_application_name(__PRETTY_FUNCTION__); |
4763 | + EXPECT_CALL(client, connect_done()). |
4764 | + Times(testing::AtLeast(0)); |
4765 | + EXPECT_CALL(client, prompt_session_start_done()). |
4766 | + Times(testing::AtLeast(0)); |
4767 | + |
4768 | + client.display_server.connect( |
4769 | + 0, |
4770 | + &client.connect_parameters, |
4771 | + &client.connection, |
4772 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done)); |
4773 | + |
4774 | + client.wait_for_connect_done(); |
4775 | + |
4776 | + client.display_server.start_prompt_session( |
4777 | + 0, |
4778 | + &client.prompt_session_parameters, |
4779 | + &client.prompt_session, |
4780 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::prompt_session_start_done)); |
4781 | + client.wait_for_prompt_session_start_done(); |
4782 | + |
4783 | + } |
4784 | + } client_process; |
4785 | + |
4786 | + launch_client_process(client_process); |
4787 | +} |
4788 | + |
4789 | +TEST_F(ApplicationMediatorReport, prompt_session_add_prompt_provider_called) |
4790 | +{ |
4791 | + struct Server : TestingServerConfiguration |
4792 | + { |
4793 | + std::shared_ptr<mf::SessionMediatorReport> |
4794 | + the_application_mediator_report() |
4795 | + { |
4796 | + auto result = std::make_shared<MockApplicationMediatorReport>(); |
4797 | + |
4798 | + EXPECT_CALL(*result, session_start_prompt_session_called(testing::_, testing::_)). |
4799 | + Times(1); |
4800 | + |
4801 | + return result; |
4802 | + } |
4803 | + } server_processing; |
4804 | + |
4805 | + launch_server_process(server_processing); |
4806 | + |
4807 | + struct Client: TestingClientConfiguration |
4808 | + { |
4809 | + void exec() |
4810 | + { |
4811 | + mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms); |
4812 | + |
4813 | + client.connect_parameters.set_application_name(__PRETTY_FUNCTION__); |
4814 | + EXPECT_CALL(client, connect_done()). |
4815 | + Times(testing::AtLeast(0)); |
4816 | + EXPECT_CALL(client, prompt_session_start_done()). |
4817 | + Times(testing::AtLeast(0)); |
4818 | + EXPECT_CALL(client, prompt_session_add_prompt_provider_done()). |
4819 | + Times(testing::AtLeast(0)); |
4820 | + |
4821 | + client.display_server.connect( |
4822 | + 0, |
4823 | + &client.connect_parameters, |
4824 | + &client.connection, |
4825 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done)); |
4826 | + |
4827 | + client.wait_for_connect_done(); |
4828 | + |
4829 | + client.display_server.start_prompt_session( |
4830 | + 0, |
4831 | + &client.prompt_session_parameters, |
4832 | + &client.prompt_session, |
4833 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::prompt_session_start_done)); |
4834 | + client.wait_for_prompt_session_start_done(); |
4835 | + |
4836 | + client.display_server.add_prompt_provider( |
4837 | + 0, |
4838 | + &client.prompt_provider, |
4839 | + &client.ignored, |
4840 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::prompt_session_add_prompt_provider_done)); |
4841 | + client.wait_for_prompt_session_add_prompt_provider_done(); |
4842 | + |
4843 | + } |
4844 | + } client_process; |
4845 | + |
4846 | + launch_client_process(client_process); |
4847 | +} |
4848 | + |
4849 | +TEST_F(ApplicationMediatorReport, prompt_session_stop_called) |
4850 | +{ |
4851 | + struct Server : TestingServerConfiguration |
4852 | + { |
4853 | + std::shared_ptr<mf::SessionMediatorReport> |
4854 | + the_application_mediator_report() |
4855 | + { |
4856 | + auto result = std::make_shared<MockApplicationMediatorReport>(); |
4857 | + |
4858 | + EXPECT_CALL(*result, session_stop_prompt_session_called(testing::_)). |
4859 | + Times(1); |
4860 | + |
4861 | + return result; |
4862 | + } |
4863 | + } server_processing; |
4864 | + |
4865 | + launch_server_process(server_processing); |
4866 | + |
4867 | + struct Client: TestingClientConfiguration |
4868 | + { |
4869 | + void exec() |
4870 | + { |
4871 | + mt::TestProtobufClient client(mtf::test_socket_file(), rpc_timeout_ms); |
4872 | + |
4873 | + client.connect_parameters.set_application_name(__PRETTY_FUNCTION__); |
4874 | + EXPECT_CALL(client, connect_done()). |
4875 | + Times(testing::AtLeast(0)); |
4876 | + EXPECT_CALL(client, prompt_session_start_done()). |
4877 | + Times(testing::AtLeast(0)); |
4878 | + EXPECT_CALL(client, prompt_session_stop_done()). |
4879 | + Times(testing::AtLeast(0)); |
4880 | + |
4881 | + client.display_server.connect( |
4882 | + 0, |
4883 | + &client.connect_parameters, |
4884 | + &client.connection, |
4885 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::connect_done)); |
4886 | + |
4887 | + client.wait_for_connect_done(); |
4888 | + |
4889 | + client.display_server.start_prompt_session( |
4890 | + 0, |
4891 | + &client.prompt_session_parameters, |
4892 | + &client.prompt_session, |
4893 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::prompt_session_start_done)); |
4894 | + client.wait_for_prompt_session_start_done(); |
4895 | + |
4896 | + client.display_server.stop_prompt_session( |
4897 | + 0, |
4898 | + &client.ignored, |
4899 | + &client.ignored, |
4900 | + google::protobuf::NewCallback(&client, &mt::TestProtobufClient::prompt_session_stop_done)); |
4901 | + client.wait_for_prompt_session_stop_done(); |
4902 | + } |
4903 | + } client_process; |
4904 | + |
4905 | + launch_client_process(client_process); |
4906 | +} |
4907 | + |
4908 | + |
4909 | |
4910 | === modified file 'tests/integration-tests/test_session_manager.cpp' |
4911 | --- tests/integration-tests/test_session_manager.cpp 2014-04-15 05:31:19 +0000 |
4912 | +++ tests/integration-tests/test_session_manager.cpp 2014-06-16 15:01:17 +0000 |
4913 | @@ -32,6 +32,7 @@ |
4914 | #include "mir_test_doubles/null_snapshot_strategy.h" |
4915 | #include "mir_test_doubles/null_event_sink.h" |
4916 | #include "mir_test_doubles/null_session_event_sink.h" |
4917 | +#include "mir_test_doubles/null_prompt_session_manager.h" |
4918 | |
4919 | #include <gmock/gmock.h> |
4920 | #include <gtest/gtest.h> |
4921 | @@ -55,7 +56,8 @@ |
4922 | mt::fake_shared(focus_setter), |
4923 | std::make_shared<mtd::NullSnapshotStrategy>(), |
4924 | std::make_shared<mtd::NullSessionEventSink>(), |
4925 | - mt::fake_shared(session_listener)) |
4926 | + mt::fake_shared(session_listener), |
4927 | + std::make_shared<mtd::NullPromptSessionManager>()) |
4928 | { |
4929 | |
4930 | } |
4931 | |
4932 | === modified file 'tests/mir_test_doubles/test_protobuf_client.cpp' |
4933 | --- tests/mir_test_doubles/test_protobuf_client.cpp 2014-03-06 06:05:17 +0000 |
4934 | +++ tests/mir_test_doubles/test_protobuf_client.cpp 2014-06-16 15:01:17 +0000 |
4935 | @@ -18,6 +18,7 @@ |
4936 | |
4937 | #include "mir_test/test_protobuf_client.h" |
4938 | #include "mir_test_doubles/mock_rpc_report.h" |
4939 | +#include "mir_test_doubles/null_client_event_sink.h" |
4940 | |
4941 | #include "src/client/connection_surface_map.h" |
4942 | #include "src/client/display_configuration.h" |
4943 | @@ -38,7 +39,8 @@ |
4944 | std::make_shared<mir::client::ConnectionSurfaceMap>(), |
4945 | std::make_shared<mir::client::DisplayConfiguration>(), |
4946 | rpc_report, |
4947 | - std::make_shared<mir::client::LifecycleControl>())), |
4948 | + std::make_shared<mir::client::LifecycleControl>(), |
4949 | + std::make_shared<mtd::NullClientEventSink>())), |
4950 | display_server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL), |
4951 | maxwait(timeout_ms), |
4952 | connect_done_called(false), |
4953 | @@ -59,6 +61,9 @@ |
4954 | surface_parameters.set_buffer_usage(0); |
4955 | surface_parameters.set_output_id(mir_display_output_id_invalid); |
4956 | |
4957 | + prompt_provider.set_pid(__LINE__); |
4958 | + prompt_session_parameters.set_application_pid(__LINE__); |
4959 | + |
4960 | ON_CALL(*this, connect_done()) |
4961 | .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_connect_done)); |
4962 | ON_CALL(*this, create_surface_done()) |
4963 | @@ -73,6 +78,12 @@ |
4964 | .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_drm_auth_magic_done)); |
4965 | ON_CALL(*this, display_configure_done()) |
4966 | .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_configure_display_done)); |
4967 | + ON_CALL(*this, prompt_session_start_done()) |
4968 | + .WillByDefault(testing::Invoke(&wc_prompt_session_start, &WaitCondition::wake_up_everyone)); |
4969 | + ON_CALL(*this, prompt_session_add_prompt_provider_done()) |
4970 | + .WillByDefault(testing::Invoke(&wc_prompt_session_add, &WaitCondition::wake_up_everyone)); |
4971 | + ON_CALL(*this, prompt_session_stop_done()) |
4972 | + .WillByDefault(testing::Invoke(&wc_prompt_session_stop, &WaitCondition::wake_up_everyone)); |
4973 | } |
4974 | |
4975 | void mir::test::TestProtobufClient::on_connect_done() |
4976 | @@ -225,3 +236,18 @@ |
4977 | } |
4978 | tfd_done_called.store(false); |
4979 | } |
4980 | + |
4981 | +void mir::test::TestProtobufClient::wait_for_prompt_session_start_done() |
4982 | +{ |
4983 | + wc_prompt_session_start.wait_for_at_most_seconds(maxwait); |
4984 | +} |
4985 | + |
4986 | +void mir::test::TestProtobufClient::wait_for_prompt_session_add_prompt_provider_done() |
4987 | +{ |
4988 | + wc_prompt_session_add.wait_for_at_most_seconds(maxwait); |
4989 | +} |
4990 | + |
4991 | +void mir::test::TestProtobufClient::wait_for_prompt_session_stop_done() |
4992 | +{ |
4993 | + wc_prompt_session_stop.wait_for_at_most_seconds(maxwait); |
4994 | +} |
4995 | |
4996 | === modified file 'tests/unit-tests/client/CMakeLists.txt' |
4997 | --- tests/unit-tests/client/CMakeLists.txt 2014-03-06 06:05:17 +0000 |
4998 | +++ tests/unit-tests/client/CMakeLists.txt 2014-06-16 15:01:17 +0000 |
4999 | @@ -8,6 +8,8 @@ |
5000 | ${CMAKE_CURRENT_SOURCE_DIR}/test_wait_handle.cpp |
FAILED: Continuous integration, rev:1518 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/1722/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 318 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 319 jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/318 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 241/console jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 240 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 240/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/870 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/870/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/1562 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 7600
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/1722/ rebuild
http://