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 <algorithm> | 5 #include <algorithm> |
6 #include <utility> | 6 #include <utility> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "mojo/public/cpp/bindings/interface_ptr.h" | 11 #include "mojo/public/cpp/bindings/interface_ptr.h" |
12 #include "mojo/shell/public/cpp/connector.h" | 12 #include "mojo/shell/public/cpp/connector.h" |
13 #include "mojo/shell/public/cpp/lib/connection_impl.h" | 13 #include "mojo/shell/public/cpp/lib/connection_impl.h" |
14 #include "mojo/shell/public/cpp/lib/connector_impl.h" | 14 #include "mojo/shell/public/cpp/lib/connector_impl.h" |
15 #include "mojo/shell/public/cpp/shell_client.h" | 15 #include "mojo/shell/public/cpp/shell_client.h" |
16 #include "mojo/shell/public/cpp/shell_connection.h" | 16 #include "mojo/shell/public/cpp/shell_connection.h" |
17 | 17 |
18 namespace mojo { | 18 namespace mojo { |
19 | 19 |
20 namespace { | |
21 | |
22 void DefaultTerminationClosure() { | |
23 if (base::MessageLoop::current() && | |
24 base::MessageLoop::current()->is_running()) | |
25 base::MessageLoop::current()->QuitWhenIdle(); | |
26 } | |
27 | |
28 } // namespace | |
29 | |
30 class AppRefCountImpl : public AppRefCount { | 20 class AppRefCountImpl : public AppRefCount { |
31 public: | 21 public: |
32 AppRefCountImpl(ShellConnection* connection, | 22 AppRefCountImpl(ShellConnection* connection, |
33 scoped_refptr<base::SingleThreadTaskRunner> app_task_runner) | 23 scoped_refptr<base::SingleThreadTaskRunner> app_task_runner) |
34 : connection_(connection), | 24 : connection_(connection), |
35 app_task_runner_(app_task_runner) {} | 25 app_task_runner_(app_task_runner) {} |
36 ~AppRefCountImpl() override { | 26 ~AppRefCountImpl() override { |
37 #ifndef NDEBUG | 27 #ifndef NDEBUG |
38 // Ensure that this object is used on only one thread at a time, or else | 28 // Ensure that this object is used on only one thread at a time, or else |
39 // there could be races where the object is being reset on one thread and | 29 // there could be races where the object is being reset on one thread and |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 | 75 |
86 DISALLOW_COPY_AND_ASSIGN(AppRefCountImpl); | 76 DISALLOW_COPY_AND_ASSIGN(AppRefCountImpl); |
87 }; | 77 }; |
88 | 78 |
89 //////////////////////////////////////////////////////////////////////////////// | 79 //////////////////////////////////////////////////////////////////////////////// |
90 // ShellConnection, public: | 80 // ShellConnection, public: |
91 | 81 |
92 ShellConnection::ShellConnection( | 82 ShellConnection::ShellConnection( |
93 mojo::ShellClient* client, | 83 mojo::ShellClient* client, |
94 InterfaceRequest<shell::mojom::ShellClient> request) | 84 InterfaceRequest<shell::mojom::ShellClient> request) |
95 : ShellConnection(client, | |
96 std::move(request), | |
97 base::Bind(&DefaultTerminationClosure)) {} | |
98 | |
99 ShellConnection::ShellConnection( | |
100 mojo::ShellClient* client, | |
101 InterfaceRequest<shell::mojom::ShellClient> request, | |
102 const Closure& termination_closure) | |
103 : client_(client), | 85 : client_(client), |
104 binding_(this, std::move(request)), | 86 binding_(this, std::move(request)), |
105 termination_closure_(termination_closure), | |
106 quit_requested_(false), | |
107 ref_count_(0), | 87 ref_count_(0), |
108 weak_factory_(this) {} | 88 weak_factory_(this) {} |
109 | 89 |
110 ShellConnection::~ShellConnection() {} | 90 ShellConnection::~ShellConnection() {} |
111 | 91 |
112 void ShellConnection::WaitForInitialize() { | 92 void ShellConnection::WaitForInitialize() { |
113 DCHECK(!shell_.is_bound()); | 93 DCHECK(!connector_); |
114 binding_.WaitForIncomingMethodCall(); | 94 binding_.WaitForIncomingMethodCall(); |
115 } | 95 } |
116 | 96 |
117 //////////////////////////////////////////////////////////////////////////////// | 97 //////////////////////////////////////////////////////////////////////////////// |
118 // ShellConnection, Shell implementation: | 98 // ShellConnection, Shell implementation: |
119 | 99 |
120 scoped_ptr<Connection> ShellConnection::Connect(const std::string& url) { | 100 scoped_ptr<Connection> ShellConnection::Connect(const std::string& url) { |
121 return connector_->Connect(url); | 101 return connector_->Connect(url); |
122 } | 102 } |
123 | 103 |
124 scoped_ptr<Connection> ShellConnection::Connect( | 104 scoped_ptr<Connection> ShellConnection::Connect( |
125 Connector::ConnectParams* params) { | 105 Connector::ConnectParams* params) { |
126 return connector_->Connect(params); | 106 return connector_->Connect(params); |
127 } | 107 } |
128 | 108 |
129 scoped_ptr<Connector> ShellConnection::CloneConnector() const { | 109 scoped_ptr<Connector> ShellConnection::CloneConnector() const { |
130 return connector_->Clone(); | 110 return connector_->Clone(); |
131 } | 111 } |
132 | 112 |
133 void ShellConnection::Quit() { | |
134 // We can't quit immediately, since there could be in-flight requests from the | |
135 // shell. So check with it first. | |
136 if (shell_) { | |
137 quit_requested_ = true; | |
138 shell_->QuitApplication(); | |
139 } else { | |
140 QuitNow(); | |
141 } | |
142 } | |
143 | |
144 scoped_ptr<AppRefCount> ShellConnection::CreateAppRefCount() { | 113 scoped_ptr<AppRefCount> ShellConnection::CreateAppRefCount() { |
145 AddRef(); | 114 AddRef(); |
146 return make_scoped_ptr( | 115 return make_scoped_ptr( |
147 new AppRefCountImpl(this, base::MessageLoop::current()->task_runner())); | 116 new AppRefCountImpl(this, base::MessageLoop::current()->task_runner())); |
148 } | 117 } |
149 | 118 |
| 119 void ShellConnection::Quit() { |
| 120 client_->Quit(); |
| 121 if (base::MessageLoop::current() && |
| 122 base::MessageLoop::current()->is_running()) { |
| 123 base::MessageLoop::current()->QuitWhenIdle(); |
| 124 } |
| 125 } |
| 126 |
150 //////////////////////////////////////////////////////////////////////////////// | 127 //////////////////////////////////////////////////////////////////////////////// |
151 // ShellConnection, shell::mojom::ShellClient implementation: | 128 // ShellConnection, shell::mojom::ShellClient implementation: |
152 | 129 |
153 void ShellConnection::Initialize(shell::mojom::ShellPtr shell, | 130 void ShellConnection::Initialize(shell::mojom::ConnectorPtr connector, |
154 const mojo::String& url, | 131 const mojo::String& url, |
155 uint32_t id, | 132 uint32_t id, |
156 uint32_t user_id) { | 133 uint32_t user_id) { |
157 shell_ = std::move(shell); | 134 connector_.reset(new ConnectorImpl( |
158 shell_.set_connection_error_handler([this]() { OnConnectionError(); }); | 135 std::move(connector), |
159 | 136 base::Bind(&ShellConnection::OnConnectionError, |
160 shell::mojom::ConnectorPtr connector; | 137 weak_factory_.GetWeakPtr()))); |
161 shell_->GetConnector(GetProxy(&connector)); | |
162 connector_.reset(new ConnectorImpl(connector.PassInterface())); | |
163 | |
164 client_->Initialize(this, url, id, user_id); | 138 client_->Initialize(this, url, id, user_id); |
165 } | 139 } |
166 | 140 |
167 void ShellConnection::AcceptConnection( | 141 void ShellConnection::AcceptConnection( |
168 const String& requestor_url, | 142 const String& requestor_url, |
169 uint32_t requestor_id, | 143 uint32_t requestor_id, |
170 uint32_t requestor_user_id, | 144 uint32_t requestor_user_id, |
171 shell::mojom::InterfaceProviderRequest local_interfaces, | 145 shell::mojom::InterfaceProviderRequest local_interfaces, |
172 shell::mojom::InterfaceProviderPtr remote_interfaces, | 146 shell::mojom::InterfaceProviderPtr remote_interfaces, |
173 Array<String> allowed_interfaces, | 147 Array<String> allowed_interfaces, |
174 const String& url) { | 148 const String& url) { |
175 scoped_ptr<Connection> registry(new internal::ConnectionImpl( | 149 scoped_ptr<Connection> registry(new internal::ConnectionImpl( |
176 url, requestor_url, requestor_id, requestor_user_id, | 150 url, requestor_url, requestor_id, requestor_user_id, |
177 std::move(remote_interfaces), std::move(local_interfaces), | 151 std::move(remote_interfaces), std::move(local_interfaces), |
178 allowed_interfaces.To<std::set<std::string>>())); | 152 allowed_interfaces.To<std::set<std::string>>())); |
179 if (!client_->AcceptConnection(registry.get())) | 153 if (!client_->AcceptConnection(registry.get())) |
180 return; | 154 return; |
181 | 155 |
182 // If we were quitting because we thought there were no more interfaces for | 156 // TODO(beng): it appears we never prune this list. We should, when the |
183 // this app in use, then that has changed so cancel the quit request. | 157 // connection's remote service provider pipe breaks. |
184 if (quit_requested_) | |
185 quit_requested_ = false; | |
186 | |
187 incoming_connections_.push_back(std::move(registry)); | 158 incoming_connections_.push_back(std::move(registry)); |
188 } | 159 } |
189 | 160 |
190 void ShellConnection::OnQuitRequested(const Callback<void(bool)>& callback) { | |
191 // If by the time we got the reply from the shell, more requests had come in | |
192 // then we don't want to quit the app anymore so we return false. Otherwise | |
193 // |quit_requested_| is true so we tell the shell to proceed with the quit. | |
194 callback.Run(quit_requested_); | |
195 if (quit_requested_) | |
196 QuitNow(); | |
197 } | |
198 | |
199 //////////////////////////////////////////////////////////////////////////////// | 161 //////////////////////////////////////////////////////////////////////////////// |
200 // ShellConnection, private: | 162 // ShellConnection, private: |
201 | 163 |
202 void ShellConnection::OnConnectionError() { | 164 void ShellConnection::OnConnectionError() { |
203 base::WeakPtr<ShellConnection> ptr(weak_factory_.GetWeakPtr()); | 165 base::WeakPtr<ShellConnection> ptr(weak_factory_.GetWeakPtr()); |
204 | 166 |
205 // We give the client notice first, since it might want to do something on | 167 // We give the client notice first, since it might want to do something on |
206 // shell connection errors other than immediate termination of the run | 168 // shell connection errors other than immediate termination of the run |
207 // loop. The application might want to continue servicing connections other | 169 // loop. The application might want to continue servicing connections other |
208 // than the one to the shell. | 170 // than the one to the shell. |
209 bool quit_now = client_->ShellConnectionLost(); | 171 bool quit_now = client_->ShellConnectionLost(); |
210 if (quit_now) | 172 if (quit_now) |
211 QuitNow(); | 173 Quit(); |
212 if (!ptr) | 174 if (!ptr) |
213 return; | 175 return; |
214 shell_ = nullptr; | 176 connector_.reset(); |
215 } | |
216 | |
217 void ShellConnection::QuitNow() { | |
218 client_->Quit(); | |
219 termination_closure_.Run(); | |
220 } | |
221 | |
222 void ShellConnection::UnbindConnections( | |
223 InterfaceRequest<shell::mojom::ShellClient>* request, | |
224 shell::mojom::ShellPtr* shell) { | |
225 *request = binding_.Unbind(); | |
226 shell->Bind(shell_.PassInterface()); | |
227 } | 177 } |
228 | 178 |
229 void ShellConnection::AddRef() { | 179 void ShellConnection::AddRef() { |
230 ++ref_count_; | 180 ++ref_count_; |
231 } | 181 } |
232 | 182 |
233 void ShellConnection::Release() { | 183 void ShellConnection::Release() { |
234 if (!--ref_count_) | 184 if (!--ref_count_) |
235 Quit(); | 185 Quit(); |
236 } | 186 } |
237 | 187 |
238 } // namespace mojo | 188 } // namespace mojo |
OLD | NEW |