OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "examples/echo/echo.mojom.h" | 7 #include "examples/echo/echo.mojom.h" |
8 #include "mojo/common/binding_set.h" | 8 #include "mojo/common/binding_set.h" |
9 #include "mojo/public/c/system/main.h" | 9 #include "mojo/public/c/system/main.h" |
10 #include "mojo/public/cpp/application/application_connection.h" | 10 #include "mojo/public/cpp/application/application_connection.h" |
11 #include "mojo/public/cpp/application/application_delegate.h" | 11 #include "mojo/public/cpp/application/application_delegate.h" |
12 #include "mojo/public/cpp/application/application_runner.h" | 12 #include "mojo/public/cpp/application/application_runner.h" |
13 #include "mojo/public/cpp/application/interface_factory.h" | |
14 #include "mojo/public/cpp/bindings/strong_binding.h" | 13 #include "mojo/public/cpp/bindings/strong_binding.h" |
15 | 14 |
16 namespace mojo { | 15 namespace mojo { |
17 namespace examples { | 16 namespace examples { |
18 | 17 |
19 // This file demonstrates three ways to implement a simple Mojo server. Because | 18 // This file demonstrates three ways to implement a simple Mojo server. Because |
20 // there's no state that's saved per-pipe, all three servers appear to the | 19 // there's no state that's saved per-pipe, all three servers appear to the |
21 // client to do exactly the same thing. | 20 // client to do exactly the same thing. |
22 // | 21 // |
23 // To choose one of the them, update MojoMain() at the end of this file. | 22 // To choose one of the them, update MojoMain() at the end of this file. |
24 // 1. MultiServer - creates a new object for each connection. Cleans up by using | 23 // 1. MultiServer - creates a new object for each connection. Cleans up by using |
25 // StrongBinding. | 24 // StrongBinding. |
26 // 2. SingletonServer -- all requests are handled by one object. Connections are | 25 // 2. SingletonServer -- all requests are handled by one object. Connections are |
27 // tracked using BindingSet. | 26 // tracked using BindingSet. |
28 // 3. OneAtATimeServer -- each Create call from InterfaceFactory<> closes the | 27 // 3. OneAtATimeServer -- each request "replaces" any previous request. Any old |
29 // old interface pipe and binds the new interface pipe. | 28 // interface pipe is closed and the new interface pipe is bound. |
30 | 29 |
31 // EchoImpl defines our implementation of the Echo interface. | 30 // EchoImpl defines our implementation of the Echo interface. |
32 // It is used by all three server variants. | 31 // It is used by all three server variants. |
33 class EchoImpl : public Echo { | 32 class EchoImpl : public Echo { |
34 public: | 33 public: |
35 void EchoString(const mojo::String& value, | 34 void EchoString(const mojo::String& value, |
36 const Callback<void(mojo::String)>& callback) override { | 35 const Callback<void(mojo::String)>& callback) override { |
37 callback.Run(value); | 36 callback.Run(value); |
38 } | 37 } |
39 }; | 38 }; |
40 | 39 |
41 // StrongBindingEchoImpl inherits from EchoImpl and adds the StrongBinding<> | 40 // StrongBindingEchoImpl inherits from EchoImpl and adds the StrongBinding<> |
42 // class so instances will delete themselves when the message pipe is closed. | 41 // class so instances will delete themselves when the message pipe is closed. |
43 // This simplifies lifetime management. This class is only used by MultiServer. | 42 // This simplifies lifetime management. This class is only used by MultiServer. |
44 class StrongBindingEchoImpl : public EchoImpl { | 43 class StrongBindingEchoImpl : public EchoImpl { |
45 public: | 44 public: |
46 explicit StrongBindingEchoImpl(InterfaceRequest<Echo> handle) | 45 explicit StrongBindingEchoImpl(InterfaceRequest<Echo> handle) |
47 : strong_binding_(this, handle.Pass()) {} | 46 : strong_binding_(this, handle.Pass()) {} |
48 | 47 |
49 private: | 48 private: |
50 mojo::StrongBinding<Echo> strong_binding_; | 49 mojo::StrongBinding<Echo> strong_binding_; |
51 }; | 50 }; |
52 | 51 |
53 // MultiServer creates a new object to handle each message pipe. | 52 // MultiServer creates a new object to handle each message pipe. |
54 class MultiServer : public mojo::ApplicationDelegate, | 53 class MultiServer : public mojo::ApplicationDelegate { |
55 public mojo::InterfaceFactory<Echo> { | |
56 public: | 54 public: |
57 MultiServer() {} | 55 MultiServer() {} |
58 | 56 |
59 // From ApplicationDelegate | 57 // From ApplicationDelegate |
60 bool ConfigureIncomingConnection( | 58 bool ConfigureIncomingConnection( |
61 mojo::ApplicationConnection* connection) override { | 59 mojo::ApplicationConnection* connection) override { |
62 connection->AddService<Echo>(this); | 60 connection->GetServiceProviderImpl().AddService<Echo>( |
| 61 [](const mojo::ConnectionContext& connection_context, |
| 62 mojo::InterfaceRequest<Echo> echo_request) { |
| 63 // This object will be deleted automatically because of the use of |
| 64 // StrongBinding<> for the declaration of |strong_binding_|. |
| 65 new StrongBindingEchoImpl(echo_request.Pass()); |
| 66 }); |
63 return true; | 67 return true; |
64 } | 68 } |
65 | |
66 // From InterfaceFactory<Echo> | |
67 void Create(const mojo::ConnectionContext& connection_context, | |
68 mojo::InterfaceRequest<Echo> request) override { | |
69 // This object will be deleted automatically because of the use of | |
70 // StrongBinding<> for the declaration of |strong_binding_|. | |
71 new StrongBindingEchoImpl(request.Pass()); | |
72 } | |
73 }; | 69 }; |
74 | 70 |
75 // SingletonServer uses the same object to handle all message pipes. Useful | 71 // SingletonServer uses the same object to handle all message pipes. Useful |
76 // for stateless operation. | 72 // for stateless operation. |
77 class SingletonServer : public mojo::ApplicationDelegate, | 73 class SingletonServer : public mojo::ApplicationDelegate { |
78 public mojo::InterfaceFactory<Echo> { | |
79 public: | 74 public: |
80 SingletonServer() {} | 75 SingletonServer() {} |
81 | 76 |
82 // From ApplicationDelegate | 77 // From ApplicationDelegate |
83 bool ConfigureIncomingConnection( | 78 bool ConfigureIncomingConnection( |
84 mojo::ApplicationConnection* connection) override { | 79 mojo::ApplicationConnection* connection) override { |
85 connection->AddService<Echo>(this); | 80 connection->GetServiceProviderImpl().AddService<Echo>( |
| 81 [this](const mojo::ConnectionContext& connection_context, |
| 82 mojo::InterfaceRequest<Echo> echo_request) { |
| 83 // All channels will connect to this singleton object, so just |
| 84 // add the binding to our collection. |
| 85 bindings_.AddBinding(&echo_impl_, echo_request.Pass()); |
| 86 }); |
86 return true; | 87 return true; |
87 } | 88 } |
88 | 89 |
89 // From InterfaceFactory<Echo> | |
90 void Create(const mojo::ConnectionContext& connection_context, | |
91 mojo::InterfaceRequest<Echo> request) override { | |
92 // All channels will connect to this singleton object, so just | |
93 // add the binding to our collection. | |
94 bindings_.AddBinding(&echo_impl_, request.Pass()); | |
95 } | |
96 | |
97 private: | 90 private: |
98 EchoImpl echo_impl_; | 91 EchoImpl echo_impl_; |
99 | 92 |
100 mojo::BindingSet<Echo> bindings_; | 93 mojo::BindingSet<Echo> bindings_; |
101 }; | 94 }; |
102 | 95 |
103 // OneAtATimeServer works with only one pipe at a time. When a new pipe tries | 96 // OneAtATimeServer works with only one pipe at a time. When a new pipe tries |
104 // to bind, the previous pipe is closed. This would seem to be useful when | 97 // to bind, the previous pipe is closed. This would seem to be useful when |
105 // clients are expected to make a single call and then go away, but in fact it's | 98 // clients are expected to make a single call and then go away, but in fact it's |
106 // not reliable. There's a race condition because a second client could bind | 99 // not reliable. There's a race condition because a second client could bind |
107 // to the server before the first client called EchoString(). Therefore, this | 100 // to the server before the first client called EchoString(). Therefore, this |
108 // is an example of how not to write your code. | 101 // is an example of how not to write your code. |
109 class OneAtATimeServer : public mojo::ApplicationDelegate, | 102 class OneAtATimeServer : public mojo::ApplicationDelegate { |
110 public mojo::InterfaceFactory<Echo> { | |
111 public: | 103 public: |
112 OneAtATimeServer() : binding_(&echo_impl_) {} | 104 OneAtATimeServer() : binding_(&echo_impl_) {} |
113 | 105 |
114 // From ApplicationDelegate | 106 // From ApplicationDelegate |
115 bool ConfigureIncomingConnection( | 107 bool ConfigureIncomingConnection( |
116 mojo::ApplicationConnection* connection) override { | 108 mojo::ApplicationConnection* connection) override { |
117 connection->AddService<Echo>(this); | 109 connection->GetServiceProviderImpl().AddService<Echo>( |
| 110 [this](const mojo::ConnectionContext& connection_context, |
| 111 mojo::InterfaceRequest<Echo> echo_request) { |
| 112 binding_.Bind(echo_request.Pass()); |
| 113 }); |
118 return true; | 114 return true; |
119 } | 115 } |
120 | 116 |
121 // From InterfaceFactory<Echo> | |
122 void Create(const mojo::ConnectionContext& connection_context, | |
123 mojo::InterfaceRequest<Echo> request) override { | |
124 binding_.Bind(request.Pass()); | |
125 } | |
126 | |
127 private: | 117 private: |
128 EchoImpl echo_impl_; | 118 EchoImpl echo_impl_; |
129 | 119 |
130 mojo::Binding<Echo> binding_; | 120 mojo::Binding<Echo> binding_; |
131 }; | 121 }; |
132 | 122 |
133 } // namespace examples | 123 } // namespace examples |
134 } // namespace mojo | 124 } // namespace mojo |
135 | 125 |
136 MojoResult MojoMain(MojoHandle application_request) { | 126 MojoResult MojoMain(MojoHandle application_request) { |
137 // Uncomment one of the three servers at a time to see it work: | 127 // Uncomment one of the three servers at a time to see it work: |
138 mojo::ApplicationRunner runner(std::unique_ptr<mojo::examples::MultiServer>( | 128 mojo::ApplicationRunner runner(std::unique_ptr<mojo::examples::MultiServer>( |
139 new mojo::examples::MultiServer())); | 129 new mojo::examples::MultiServer())); |
140 // mojo::ApplicationRunner runner(new mojo::examples::SingletonServer()); | 130 // mojo::ApplicationRunner runner(new mojo::examples::SingletonServer()); |
141 // mojo::ApplicationRunner runner(new mojo::examples::OneAtATimeServer()); | 131 // mojo::ApplicationRunner runner(new mojo::examples::OneAtATimeServer()); |
142 | 132 |
143 return runner.Run(application_request); | 133 return runner.Run(application_request); |
144 } | 134 } |
OLD | NEW |