| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "content/common/message_port.h" | 5 #include "content/common/message_port.h" |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/threading/thread_task_runner_handle.h" |
| 8 | 10 |
| 9 namespace content { | 11 namespace content { |
| 10 | 12 |
| 11 MessagePort::~MessagePort() { | 13 MessagePort::~MessagePort() { |
| 12 } | 14 } |
| 13 | 15 |
| 14 MessagePort::MessagePort() : state_(new State()) { | 16 MessagePort::MessagePort() : state_(new State()) { |
| 15 } | 17 } |
| 16 | 18 |
| 17 MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) { | 19 MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } | 142 } |
| 141 | 143 |
| 142 MessagePort::State::State(mojo::ScopedMessagePipeHandle handle) | 144 MessagePort::State::State(mojo::ScopedMessagePipeHandle handle) |
| 143 : handle_(std::move(handle)) { | 145 : handle_(std::move(handle)) { |
| 144 } | 146 } |
| 145 | 147 |
| 146 void MessagePort::State::AddWatch() { | 148 void MessagePort::State::AddWatch() { |
| 147 if (!callback_) | 149 if (!callback_) |
| 148 return; | 150 return; |
| 149 | 151 |
| 152 DCHECK(!watcher_handle_.is_valid()); |
| 153 MojoResult rv = CreateWatcher(&State::CallOnHandleReady, &watcher_handle_); |
| 154 DCHECK_EQ(MOJO_RESULT_OK, rv); |
| 155 |
| 156 // We use a scoped_refptr<State> instance as the watch context. This is owned |
| 157 // by the watch and deleted upon receiving a cancellation notification. |
| 158 scoped_refptr<State>* state_ref = new scoped_refptr<State>(this); |
| 159 context_ = reinterpret_cast<uintptr_t>(state_ref); |
| 160 |
| 150 // NOTE: An HTML MessagePort does not receive an event to tell it when the | 161 // NOTE: An HTML MessagePort does not receive an event to tell it when the |
| 151 // peer has gone away, so we only watch for readability here. | 162 // peer has gone away, so we only watch for readability here. |
| 152 MojoResult rv = MojoWatch(handle_.get().value(), | 163 rv = MojoWatch(watcher_handle_.get().value(), handle_.get().value(), |
| 153 MOJO_HANDLE_SIGNAL_READABLE, | 164 MOJO_HANDLE_SIGNAL_READABLE, context_); |
| 154 &MessagePort::State::OnHandleReady, | 165 DCHECK_EQ(MOJO_RESULT_OK, rv); |
| 155 reinterpret_cast<uintptr_t>(this)); | 166 |
| 156 if (rv != MOJO_RESULT_OK) | 167 ArmWatcher(); |
| 157 DVLOG(1) << this << " MojoWatch failed: " << rv; | |
| 158 } | 168 } |
| 159 | 169 |
| 160 void MessagePort::State::CancelWatch() { | 170 void MessagePort::State::CancelWatch() { |
| 161 if (!callback_) | 171 watcher_handle_.reset(); |
| 172 context_ = 0; |
| 173 } |
| 174 |
| 175 MessagePort::State::~State() = default; |
| 176 |
| 177 void MessagePort::State::ArmWatcher() { |
| 178 if (!watcher_handle_.is_valid()) |
| 162 return; | 179 return; |
| 163 | 180 |
| 164 // NOTE: This synchronizes with the thread where OnHandleReady runs so we are | 181 uint32_t num_ready_contexts = 1; |
| 165 // sure to not be racing with it. | 182 uintptr_t ready_context; |
| 166 MojoCancelWatch(handle_.get().value(), reinterpret_cast<uintptr_t>(this)); | 183 MojoResult ready_result; |
| 184 MojoHandleSignalsState ready_state; |
| 185 MojoResult rv = |
| 186 MojoArmWatcher(watcher_handle_.get().value(), &num_ready_contexts, |
| 187 &ready_context, &ready_result, &ready_state); |
| 188 if (rv == MOJO_RESULT_OK) |
| 189 return; |
| 190 |
| 191 // The watcher could not be armed because it would notify immediately. |
| 192 DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); |
| 193 DCHECK_EQ(1u, num_ready_contexts); |
| 194 DCHECK_EQ(context_, ready_context); |
| 195 |
| 196 if (ready_result == MOJO_RESULT_OK) { |
| 197 // The handle is already signaled, so we trigger a callback now. |
| 198 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 199 FROM_HERE, base::Bind(&State::OnHandleReady, this, MOJO_RESULT_OK)); |
| 200 return; |
| 201 } |
| 202 |
| 203 if (ready_result == MOJO_RESULT_FAILED_PRECONDITION) { |
| 204 DVLOG(1) << this << " MojoArmWatcher failed because of a broken pipe."; |
| 205 return; |
| 206 } |
| 207 |
| 208 NOTREACHED(); |
| 167 } | 209 } |
| 168 | 210 |
| 169 // static | 211 void MessagePort::State::OnHandleReady(MojoResult result) { |
| 170 void MessagePort::State::OnHandleReady( | 212 if (result == MOJO_RESULT_OK && callback_) { |
| 171 uintptr_t context, | 213 callback_.Run(); |
| 172 MojoResult result, | 214 ArmWatcher(); |
| 173 MojoHandleSignalsState signals_state, | |
| 174 MojoWatchNotificationFlags flags) { | |
| 175 if (result == MOJO_RESULT_OK) { | |
| 176 reinterpret_cast<MessagePort::State*>(context)->callback_.Run(); | |
| 177 } else { | 215 } else { |
| 178 // And now his watch is ended. | 216 // And now his watch is ended. |
| 179 } | 217 } |
| 180 } | 218 } |
| 181 | 219 |
| 182 MessagePort::State::~State() { | 220 // static |
| 183 CancelWatch(); | 221 void MessagePort::State::CallOnHandleReady(uintptr_t context, |
| 222 MojoResult result, |
| 223 MojoHandleSignalsState signals_state, |
| 224 MojoWatcherNotificationFlags flags) { |
| 225 auto* state_ref = reinterpret_cast<scoped_refptr<State>*>(context); |
| 226 if (result == MOJO_RESULT_CANCELLED) { |
| 227 // Last notification. Delete the watch's owned State ref. |
| 228 delete state_ref; |
| 229 } else { |
| 230 (*state_ref)->OnHandleReady(result); |
| 231 } |
| 184 } | 232 } |
| 185 | 233 |
| 186 } // namespace content | 234 } // namespace content |
| OLD | NEW |