| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/renderer/media/midi_message_filter.h" | 5 #include "content/renderer/media/midi_message_filter.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 13 #include "content/common/media/midi_messages.h" | 13 #include "content/common/media/midi_messages.h" |
| 14 #include "content/renderer/render_thread_impl.h" | 14 #include "content/renderer/render_thread_impl.h" |
| 15 #include "ipc/ipc_logging.h" | 15 #include "ipc/ipc_logging.h" |
| 16 | 16 |
| 17 using base::AutoLock; | 17 using base::AutoLock; |
| 18 using midi::mojom::Result; |
| 18 | 19 |
| 19 // The maximum number of bytes which we're allowed to send to the browser | 20 // The maximum number of bytes which we're allowed to send to the browser |
| 20 // before getting acknowledgement back from the browser that they've been | 21 // before getting acknowledgement back from the browser that they've been |
| 21 // successfully sent. | 22 // successfully sent. |
| 22 static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB. | 23 static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB. |
| 23 | 24 |
| 24 namespace content { | 25 namespace content { |
| 25 | 26 |
| 26 MidiMessageFilter::MidiMessageFilter( | 27 MidiMessageFilter::MidiMessageFilter( |
| 27 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) | 28 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) |
| 28 : sender_(nullptr), | 29 : sender_(nullptr), |
| 29 io_task_runner_(io_task_runner), | 30 io_task_runner_(io_task_runner), |
| 30 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 31 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 31 session_result_(midi::Result::NOT_INITIALIZED), | 32 session_result_(Result::NOT_INITIALIZED), |
| 32 unacknowledged_bytes_sent_(0u) { | 33 unacknowledged_bytes_sent_(0u) {} |
| 33 } | |
| 34 | 34 |
| 35 MidiMessageFilter::~MidiMessageFilter() {} | 35 MidiMessageFilter::~MidiMessageFilter() {} |
| 36 | 36 |
| 37 void MidiMessageFilter::AddClient(blink::WebMIDIAccessorClient* client) { | 37 void MidiMessageFilter::AddClient(blink::WebMIDIAccessorClient* client) { |
| 38 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 38 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 39 TRACE_EVENT0("midi", "MidiMessageFilter::AddClient"); | 39 TRACE_EVENT0("midi", "MidiMessageFilter::AddClient"); |
| 40 clients_waiting_session_queue_.push_back(client); | 40 clients_waiting_session_queue_.push_back(client); |
| 41 if (session_result_ != midi::Result::NOT_INITIALIZED) { | 41 if (session_result_ != Result::NOT_INITIALIZED) { |
| 42 HandleClientAdded(session_result_); | 42 HandleClientAdded(session_result_); |
| 43 } else if (clients_waiting_session_queue_.size() == 1u) { | 43 } else if (clients_waiting_session_queue_.size() == 1u) { |
| 44 io_task_runner_->PostTask( | 44 io_task_runner_->PostTask( |
| 45 FROM_HERE, | 45 FROM_HERE, |
| 46 base::Bind(&MidiMessageFilter::StartSessionOnIOThread, this)); | 46 base::Bind(&MidiMessageFilter::StartSessionOnIOThread, this)); |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 | 49 |
| 50 void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) { | 50 void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) { |
| 51 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 51 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 52 clients_.erase(client); | 52 clients_.erase(client); |
| 53 ClientsQueue::iterator it = std::find(clients_waiting_session_queue_.begin(), | 53 ClientsQueue::iterator it = std::find(clients_waiting_session_queue_.begin(), |
| 54 clients_waiting_session_queue_.end(), | 54 clients_waiting_session_queue_.end(), |
| 55 client); | 55 client); |
| 56 if (it != clients_waiting_session_queue_.end()) | 56 if (it != clients_waiting_session_queue_.end()) |
| 57 clients_waiting_session_queue_.erase(it); | 57 clients_waiting_session_queue_.erase(it); |
| 58 if (clients_.empty() && clients_waiting_session_queue_.empty()) { | 58 if (clients_.empty() && clients_waiting_session_queue_.empty()) { |
| 59 session_result_ = midi::Result::NOT_INITIALIZED; | 59 session_result_ = Result::NOT_INITIALIZED; |
| 60 inputs_.clear(); | 60 inputs_.clear(); |
| 61 outputs_.clear(); | 61 outputs_.clear(); |
| 62 io_task_runner_->PostTask( | 62 io_task_runner_->PostTask( |
| 63 FROM_HERE, base::Bind(&MidiMessageFilter::EndSessionOnIOThread, this)); | 63 FROM_HERE, base::Bind(&MidiMessageFilter::EndSessionOnIOThread, this)); |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 | 66 |
| 67 void MidiMessageFilter::SendMidiData(uint32_t port, | 67 void MidiMessageFilter::SendMidiData(uint32_t port, |
| 68 const uint8_t* data, | 68 const uint8_t* data, |
| 69 size_t length, | 69 size_t length, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 // Once removed, a filter will not be used again. At this time all | 135 // Once removed, a filter will not be used again. At this time all |
| 136 // delegates must be notified so they release their reference. | 136 // delegates must be notified so they release their reference. |
| 137 OnChannelClosing(); | 137 OnChannelClosing(); |
| 138 } | 138 } |
| 139 | 139 |
| 140 void MidiMessageFilter::OnChannelClosing() { | 140 void MidiMessageFilter::OnChannelClosing() { |
| 141 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 141 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 142 sender_ = nullptr; | 142 sender_ = nullptr; |
| 143 } | 143 } |
| 144 | 144 |
| 145 void MidiMessageFilter::OnSessionStarted(midi::Result result) { | 145 void MidiMessageFilter::OnSessionStarted(Result result) { |
| 146 TRACE_EVENT0("midi", "MidiMessageFilter::OnSessionStarted"); | 146 TRACE_EVENT0("midi", "MidiMessageFilter::OnSessionStarted"); |
| 147 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 147 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 148 // Handle on the main JS thread. | 148 // Handle on the main JS thread. |
| 149 main_task_runner_->PostTask( | 149 main_task_runner_->PostTask( |
| 150 FROM_HERE, | 150 FROM_HERE, |
| 151 base::Bind(&MidiMessageFilter::HandleClientAdded, this, result)); | 151 base::Bind(&MidiMessageFilter::HandleClientAdded, this, result)); |
| 152 } | 152 } |
| 153 | 153 |
| 154 void MidiMessageFilter::OnAddInputPort(midi::MidiPortInfo info) { | 154 void MidiMessageFilter::OnAddInputPort(midi::MidiPortInfo info) { |
| 155 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 155 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 data, timestamp)); | 192 data, timestamp)); |
| 193 } | 193 } |
| 194 | 194 |
| 195 void MidiMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) { | 195 void MidiMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) { |
| 196 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 196 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 197 main_task_runner_->PostTask( | 197 main_task_runner_->PostTask( |
| 198 FROM_HERE, base::Bind(&MidiMessageFilter::HandleAckknowledgeSentData, | 198 FROM_HERE, base::Bind(&MidiMessageFilter::HandleAckknowledgeSentData, |
| 199 this, bytes_sent)); | 199 this, bytes_sent)); |
| 200 } | 200 } |
| 201 | 201 |
| 202 void MidiMessageFilter::HandleClientAdded(midi::Result result) { | 202 void MidiMessageFilter::HandleClientAdded(Result result) { |
| 203 TRACE_EVENT0("midi", "MidiMessageFilter::HandleClientAdded"); | 203 TRACE_EVENT0("midi", "MidiMessageFilter::HandleClientAdded"); |
| 204 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 204 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 205 session_result_ = result; | 205 session_result_ = result; |
| 206 std::string error; | |
| 207 std::string message; | |
| 208 switch (result) { | |
| 209 case midi::Result::OK: | |
| 210 break; | |
| 211 case midi::Result::NOT_SUPPORTED: | |
| 212 error = "NotSupportedError"; | |
| 213 break; | |
| 214 case midi::Result::INITIALIZATION_ERROR: | |
| 215 error = "InvalidStateError"; | |
| 216 message = "Platform dependent initialization failed."; | |
| 217 break; | |
| 218 default: | |
| 219 NOTREACHED(); | |
| 220 error = "InvalidStateError"; | |
| 221 message = "Unknown internal error occurred."; | |
| 222 break; | |
| 223 } | |
| 224 base::string16 error16 = base::UTF8ToUTF16(error); | |
| 225 base::string16 message16 = base::UTF8ToUTF16(message); | |
| 226 | 206 |
| 227 // A for-loop using iterators does not work because |client| may touch | 207 // A for-loop using iterators does not work because |client| may touch |
| 228 // |clients_waiting_session_queue_| in callbacks. | 208 // |clients_waiting_session_queue_| in callbacks. |
| 229 while (!clients_waiting_session_queue_.empty()) { | 209 while (!clients_waiting_session_queue_.empty()) { |
| 230 auto* client = clients_waiting_session_queue_.back(); | 210 auto* client = clients_waiting_session_queue_.back(); |
| 231 clients_waiting_session_queue_.pop_back(); | 211 clients_waiting_session_queue_.pop_back(); |
| 232 if (result == midi::Result::OK) { | 212 if (result == Result::OK) { |
| 233 // Add the client's input and output ports. | 213 // Add the client's input and output ports. |
| 234 for (const auto& info : inputs_) { | 214 for (const auto& info : inputs_) { |
| 235 client->didAddInputPort( | 215 client->didAddInputPort( |
| 236 base::UTF8ToUTF16(info.id), | 216 base::UTF8ToUTF16(info.id), |
| 237 base::UTF8ToUTF16(info.manufacturer), | 217 base::UTF8ToUTF16(info.manufacturer), |
| 238 base::UTF8ToUTF16(info.name), | 218 base::UTF8ToUTF16(info.name), |
| 239 base::UTF8ToUTF16(info.version), | 219 base::UTF8ToUTF16(info.version), |
| 240 ToBlinkState(info.state)); | 220 ToBlinkState(info.state)); |
| 241 } | 221 } |
| 242 | 222 |
| 243 for (const auto& info : outputs_) { | 223 for (const auto& info : outputs_) { |
| 244 client->didAddOutputPort( | 224 client->didAddOutputPort( |
| 245 base::UTF8ToUTF16(info.id), | 225 base::UTF8ToUTF16(info.id), |
| 246 base::UTF8ToUTF16(info.manufacturer), | 226 base::UTF8ToUTF16(info.manufacturer), |
| 247 base::UTF8ToUTF16(info.name), | 227 base::UTF8ToUTF16(info.name), |
| 248 base::UTF8ToUTF16(info.version), | 228 base::UTF8ToUTF16(info.version), |
| 249 ToBlinkState(info.state)); | 229 ToBlinkState(info.state)); |
| 250 } | 230 } |
| 251 } | 231 } |
| 252 client->didStartSession(result == midi::Result::OK, error16, | 232 client->didStartSession(result); |
| 253 message16); | |
| 254 clients_.insert(client); | 233 clients_.insert(client); |
| 255 } | 234 } |
| 256 } | 235 } |
| 257 | 236 |
| 258 void MidiMessageFilter::HandleAddInputPort(midi::MidiPortInfo info) { | 237 void MidiMessageFilter::HandleAddInputPort(midi::MidiPortInfo info) { |
| 259 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 238 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 260 inputs_.push_back(info); | 239 inputs_.push_back(info); |
| 261 const base::string16 id = base::UTF8ToUTF16(info.id); | 240 const base::string16 id = base::UTF8ToUTF16(info.id); |
| 262 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); | 241 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); |
| 263 const base::string16 name = base::UTF8ToUTF16(info.name); | 242 const base::string16 name = base::UTF8ToUTF16(info.name); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 void MidiMessageFilter::HandleSetOutputPortState( | 290 void MidiMessageFilter::HandleSetOutputPortState( |
| 312 uint32_t port, | 291 uint32_t port, |
| 313 midi::MidiPortState state) { | 292 midi::MidiPortState state) { |
| 314 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 293 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 315 outputs_[port].state = state; | 294 outputs_[port].state = state; |
| 316 for (auto* client : clients_) | 295 for (auto* client : clients_) |
| 317 client->didSetOutputPortState(port, ToBlinkState(state)); | 296 client->didSetOutputPortState(port, ToBlinkState(state)); |
| 318 } | 297 } |
| 319 | 298 |
| 320 } // namespace content | 299 } // namespace content |
| OLD | NEW |