OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "mojo/shell/external_application_listener.h" |
| 6 |
| 7 #include "base/callback.h" |
| 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/sequenced_task_runner.h" |
| 15 #include "base/tracked_objects.h" |
| 16 #include "mojo/embedder/channel_init.h" |
| 17 #include "mojo/public/cpp/bindings/error_handler.h" |
| 18 #include "mojo/shell/external_application_registrar.mojom.h" |
| 19 #include "net/base/net_errors.h" |
| 20 #include "net/socket/socket_descriptor.h" |
| 21 |
| 22 namespace mojo { |
| 23 namespace shell { |
| 24 |
| 25 const char ExternalApplicationListener::kDefaultListenSocketPath[] = |
| 26 "/var/run/mojo/system_socket"; |
| 27 |
| 28 class ExternalApplicationListener::RegistrarImpl |
| 29 : public InterfaceImpl<ExternalApplicationRegistrar> { |
| 30 public: |
| 31 explicit RegistrarImpl(const RegisterCallback& callback); |
| 32 virtual ~RegistrarImpl() MOJO_OVERRIDE; |
| 33 |
| 34 virtual void OnConnectionError() MOJO_OVERRIDE; |
| 35 |
| 36 embedder::ChannelInit channel_init; |
| 37 |
| 38 private: |
| 39 virtual void Register(const String& app_url, |
| 40 InterfaceRequest<Shell> shell, |
| 41 const mojo::Closure& callback) MOJO_OVERRIDE; |
| 42 |
| 43 const RegisterCallback register_callback_; |
| 44 }; |
| 45 |
| 46 ExternalApplicationListener::ExternalApplicationListener( |
| 47 const scoped_refptr<base::SequencedTaskRunner>& shell_runner, |
| 48 const scoped_refptr<base::SequencedTaskRunner>& io_runner) |
| 49 : shell_runner_(shell_runner), |
| 50 io_runner_(io_runner), |
| 51 signal_on_listening_(true, false), |
| 52 weak_ptr_factory_(this) { |
| 53 DCHECK(shell_runner_.get() && shell_runner_->RunsTasksOnCurrentThread()); |
| 54 DCHECK(io_runner_.get()); |
| 55 listener_thread_checker_.DetachFromThread(); // Will attach in StartListener. |
| 56 } |
| 57 |
| 58 ExternalApplicationListener::~ExternalApplicationListener() { |
| 59 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 60 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 61 |
| 62 // listener_ needs to be destroyed on io_runner_, and it has to die before |
| 63 // this object does, as it holds a pointer back to this instance. |
| 64 base::WaitableEvent stop_listening_event(true, false); |
| 65 io_runner_->PostTask(FROM_HERE, |
| 66 base::Bind(&ExternalApplicationListener::StopListening, |
| 67 base::Unretained(this), |
| 68 &stop_listening_event)); |
| 69 stop_listening_event.Wait(); |
| 70 } |
| 71 |
| 72 void ExternalApplicationListener::ListenInBackground( |
| 73 const base::FilePath& listen_socket_path, |
| 74 const RegisterCallback& register_callback) { |
| 75 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 76 ListenInBackgroundWithErrorCallback( |
| 77 listen_socket_path, register_callback, ErrorCallback()); |
| 78 } |
| 79 |
| 80 void ExternalApplicationListener::ListenInBackgroundWithErrorCallback( |
| 81 const base::FilePath& listen_socket_path, |
| 82 const RegisterCallback& register_callback, |
| 83 const ErrorCallback& error_callback) { |
| 84 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 85 register_callback_ = register_callback; |
| 86 error_callback_ = error_callback; |
| 87 |
| 88 io_runner_->PostTask(FROM_HERE, |
| 89 base::Bind(&ExternalApplicationListener::StartListening, |
| 90 base::Unretained(this), |
| 91 listen_socket_path)); |
| 92 } |
| 93 |
| 94 void ExternalApplicationListener::WaitForListening() { |
| 95 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 96 signal_on_listening_.Wait(); |
| 97 } |
| 98 |
| 99 void ExternalApplicationListener::StartListening( |
| 100 const base::FilePath& listen_socket_path) { |
| 101 CHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_IO); |
| 102 DCHECK(listener_thread_checker_.CalledOnValidThread()); |
| 103 listener_.reset(new IncomingConnectionListener(listen_socket_path, this)); |
| 104 listener_->StartListening(); |
| 105 } |
| 106 |
| 107 void ExternalApplicationListener::StopListening(base::WaitableEvent* event) { |
| 108 DCHECK(listener_thread_checker_.CalledOnValidThread()); |
| 109 listener_.reset(); |
| 110 event->Signal(); |
| 111 } |
| 112 |
| 113 void ExternalApplicationListener::OnListening(int rv) { |
| 114 DCHECK(listener_thread_checker_.CalledOnValidThread()); |
| 115 signal_on_listening_.Signal(); |
| 116 shell_runner_->PostTask( |
| 117 FROM_HERE, |
| 118 base::Bind( |
| 119 &ExternalApplicationListener::RunErrorCallbackIfListeningFailed, |
| 120 weak_ptr_factory_.GetWeakPtr(), |
| 121 rv)); |
| 122 } |
| 123 |
| 124 void ExternalApplicationListener::OnConnection(net::SocketDescriptor incoming) { |
| 125 DCHECK(listener_thread_checker_.CalledOnValidThread()); |
| 126 shell_runner_->PostTask( |
| 127 FROM_HERE, |
| 128 base::Bind(&ExternalApplicationListener::CreatePipeAndBindToRegistrarImpl, |
| 129 weak_ptr_factory_.GetWeakPtr(), |
| 130 incoming)); |
| 131 } |
| 132 |
| 133 void ExternalApplicationListener::RunErrorCallbackIfListeningFailed(int rv) { |
| 134 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 135 if (rv != net::OK && !error_callback_.is_null()) { |
| 136 error_callback_.Run(rv); |
| 137 } |
| 138 } |
| 139 |
| 140 void ExternalApplicationListener::CreatePipeAndBindToRegistrarImpl( |
| 141 net::SocketDescriptor incoming_socket) { |
| 142 DCHECK(register_thread_checker_.CalledOnValidThread()); |
| 143 |
| 144 DVLOG(1) << "Accepted incoming connection"; |
| 145 scoped_ptr<RegistrarImpl> registrar(new RegistrarImpl(register_callback_)); |
| 146 // Passes ownership of incoming_socket to registrar->channel_init. |
| 147 mojo::ScopedMessagePipeHandle message_pipe = |
| 148 registrar->channel_init.Init(incoming_socket, io_runner_); |
| 149 CHECK(message_pipe.is_valid()); |
| 150 |
| 151 BindToPipe(registrar.release(), message_pipe.Pass()); |
| 152 } |
| 153 |
| 154 ExternalApplicationListener::RegistrarImpl::RegistrarImpl( |
| 155 const RegisterCallback& callback) |
| 156 : register_callback_(callback) { |
| 157 } |
| 158 |
| 159 ExternalApplicationListener::RegistrarImpl::~RegistrarImpl() { |
| 160 } |
| 161 |
| 162 void ExternalApplicationListener::RegistrarImpl::OnConnectionError() { |
| 163 channel_init.WillDestroySoon(); |
| 164 } |
| 165 |
| 166 void ExternalApplicationListener::RegistrarImpl::Register( |
| 167 const String& app_url, |
| 168 InterfaceRequest<Shell> shell, |
| 169 const mojo::Closure& callback) { |
| 170 register_callback_.Run(app_url.To<GURL>(), shell.PassMessagePipe()); |
| 171 callback.Run(); |
| 172 } |
| 173 |
| 174 } // namespace shell |
| 175 } // namespace mojo |
OLD | NEW |