| 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" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 // successfully sent. | 21 // successfully sent. |
| 22 static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB. | 22 static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB. |
| 23 | 23 |
| 24 namespace content { | 24 namespace content { |
| 25 | 25 |
| 26 MidiMessageFilter::MidiMessageFilter( | 26 MidiMessageFilter::MidiMessageFilter( |
| 27 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) | 27 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) |
| 28 : sender_(nullptr), | 28 : sender_(nullptr), |
| 29 io_task_runner_(io_task_runner), | 29 io_task_runner_(io_task_runner), |
| 30 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 30 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 31 session_result_(media::midi::Result::NOT_INITIALIZED), | 31 session_result_(midi::Result::NOT_INITIALIZED), |
| 32 unacknowledged_bytes_sent_(0u) { | 32 unacknowledged_bytes_sent_(0u) { |
| 33 } | 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_ != media::midi::Result::NOT_INITIALIZED) { | 41 if (session_result_ != midi::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_ = media::midi::Result::NOT_INITIALIZED; | 59 session_result_ = midi::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(media::midi::Result result) { | 145 void MidiMessageFilter::OnSessionStarted(midi::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(media::midi::MidiPortInfo info) { | 154 void MidiMessageFilter::OnAddInputPort(midi::MidiPortInfo info) { |
| 155 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 155 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 156 main_task_runner_->PostTask( | 156 main_task_runner_->PostTask( |
| 157 FROM_HERE, | 157 FROM_HERE, |
| 158 base::Bind(&MidiMessageFilter::HandleAddInputPort, this, info)); | 158 base::Bind(&MidiMessageFilter::HandleAddInputPort, this, info)); |
| 159 } | 159 } |
| 160 | 160 |
| 161 void MidiMessageFilter::OnAddOutputPort(media::midi::MidiPortInfo info) { | 161 void MidiMessageFilter::OnAddOutputPort(midi::MidiPortInfo info) { |
| 162 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 162 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 163 main_task_runner_->PostTask( | 163 main_task_runner_->PostTask( |
| 164 FROM_HERE, | 164 FROM_HERE, |
| 165 base::Bind(&MidiMessageFilter::HandleAddOutputPort, this, info)); | 165 base::Bind(&MidiMessageFilter::HandleAddOutputPort, this, info)); |
| 166 } | 166 } |
| 167 | 167 |
| 168 void MidiMessageFilter::OnSetInputPortState(uint32_t port, | 168 void MidiMessageFilter::OnSetInputPortState(uint32_t port, |
| 169 media::midi::MidiPortState state) { | 169 midi::MidiPortState state) { |
| 170 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 170 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 171 main_task_runner_->PostTask( | 171 main_task_runner_->PostTask( |
| 172 FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetInputPortState, this, | 172 FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetInputPortState, this, |
| 173 port, state)); | 173 port, state)); |
| 174 } | 174 } |
| 175 | 175 |
| 176 void MidiMessageFilter::OnSetOutputPortState(uint32_t port, | 176 void MidiMessageFilter::OnSetOutputPortState(uint32_t port, |
| 177 media::midi::MidiPortState state) { | 177 midi::MidiPortState state) { |
| 178 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 178 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 179 main_task_runner_->PostTask( | 179 main_task_runner_->PostTask( |
| 180 FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetOutputPortState, this, | 180 FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetOutputPortState, this, |
| 181 port, state)); | 181 port, state)); |
| 182 } | 182 } |
| 183 | 183 |
| 184 void MidiMessageFilter::OnDataReceived(uint32_t port, | 184 void MidiMessageFilter::OnDataReceived(uint32_t port, |
| 185 const std::vector<uint8_t>& data, | 185 const std::vector<uint8_t>& data, |
| 186 double timestamp) { | 186 double timestamp) { |
| 187 TRACE_EVENT0("midi", "MidiMessageFilter::OnDataReceived"); | 187 TRACE_EVENT0("midi", "MidiMessageFilter::OnDataReceived"); |
| 188 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 188 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 189 // Handle on the main JS thread. | 189 // Handle on the main JS thread. |
| 190 main_task_runner_->PostTask( | 190 main_task_runner_->PostTask( |
| 191 FROM_HERE, base::Bind(&MidiMessageFilter::HandleDataReceived, this, port, | 191 FROM_HERE, base::Bind(&MidiMessageFilter::HandleDataReceived, this, port, |
| 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(media::midi::Result result) { | 202 void MidiMessageFilter::HandleClientAdded(midi::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; | 206 std::string error; |
| 207 std::string message; | 207 std::string message; |
| 208 switch (result) { | 208 switch (result) { |
| 209 case media::midi::Result::OK: | 209 case midi::Result::OK: |
| 210 break; | 210 break; |
| 211 case media::midi::Result::NOT_SUPPORTED: | 211 case midi::Result::NOT_SUPPORTED: |
| 212 error = "NotSupportedError"; | 212 error = "NotSupportedError"; |
| 213 break; | 213 break; |
| 214 case media::midi::Result::INITIALIZATION_ERROR: | 214 case midi::Result::INITIALIZATION_ERROR: |
| 215 error = "InvalidStateError"; | 215 error = "InvalidStateError"; |
| 216 message = "Platform dependent initialization failed."; | 216 message = "Platform dependent initialization failed."; |
| 217 break; | 217 break; |
| 218 default: | 218 default: |
| 219 NOTREACHED(); | 219 NOTREACHED(); |
| 220 error = "InvalidStateError"; | 220 error = "InvalidStateError"; |
| 221 message = "Unknown internal error occurred."; | 221 message = "Unknown internal error occurred."; |
| 222 break; | 222 break; |
| 223 } | 223 } |
| 224 base::string16 error16 = base::UTF8ToUTF16(error); | 224 base::string16 error16 = base::UTF8ToUTF16(error); |
| 225 base::string16 message16 = base::UTF8ToUTF16(message); | 225 base::string16 message16 = base::UTF8ToUTF16(message); |
| 226 | 226 |
| 227 // A for-loop using iterators does not work because |client| may touch | 227 // A for-loop using iterators does not work because |client| may touch |
| 228 // |clients_waiting_session_queue_| in callbacks. | 228 // |clients_waiting_session_queue_| in callbacks. |
| 229 while (!clients_waiting_session_queue_.empty()) { | 229 while (!clients_waiting_session_queue_.empty()) { |
| 230 auto* client = clients_waiting_session_queue_.back(); | 230 auto* client = clients_waiting_session_queue_.back(); |
| 231 clients_waiting_session_queue_.pop_back(); | 231 clients_waiting_session_queue_.pop_back(); |
| 232 if (result == media::midi::Result::OK) { | 232 if (result == midi::Result::OK) { |
| 233 // Add the client's input and output ports. | 233 // Add the client's input and output ports. |
| 234 for (const auto& info : inputs_) { | 234 for (const auto& info : inputs_) { |
| 235 client->didAddInputPort( | 235 client->didAddInputPort( |
| 236 base::UTF8ToUTF16(info.id), | 236 base::UTF8ToUTF16(info.id), |
| 237 base::UTF8ToUTF16(info.manufacturer), | 237 base::UTF8ToUTF16(info.manufacturer), |
| 238 base::UTF8ToUTF16(info.name), | 238 base::UTF8ToUTF16(info.name), |
| 239 base::UTF8ToUTF16(info.version), | 239 base::UTF8ToUTF16(info.version), |
| 240 ToBlinkState(info.state)); | 240 ToBlinkState(info.state)); |
| 241 } | 241 } |
| 242 | 242 |
| 243 for (const auto& info : outputs_) { | 243 for (const auto& info : outputs_) { |
| 244 client->didAddOutputPort( | 244 client->didAddOutputPort( |
| 245 base::UTF8ToUTF16(info.id), | 245 base::UTF8ToUTF16(info.id), |
| 246 base::UTF8ToUTF16(info.manufacturer), | 246 base::UTF8ToUTF16(info.manufacturer), |
| 247 base::UTF8ToUTF16(info.name), | 247 base::UTF8ToUTF16(info.name), |
| 248 base::UTF8ToUTF16(info.version), | 248 base::UTF8ToUTF16(info.version), |
| 249 ToBlinkState(info.state)); | 249 ToBlinkState(info.state)); |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 client->didStartSession(result == media::midi::Result::OK, error16, | 252 client->didStartSession(result == midi::Result::OK, error16, |
| 253 message16); | 253 message16); |
| 254 clients_.insert(client); | 254 clients_.insert(client); |
| 255 } | 255 } |
| 256 } | 256 } |
| 257 | 257 |
| 258 void MidiMessageFilter::HandleAddInputPort(media::midi::MidiPortInfo info) { | 258 void MidiMessageFilter::HandleAddInputPort(midi::MidiPortInfo info) { |
| 259 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 259 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 260 inputs_.push_back(info); | 260 inputs_.push_back(info); |
| 261 const base::string16 id = base::UTF8ToUTF16(info.id); | 261 const base::string16 id = base::UTF8ToUTF16(info.id); |
| 262 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); | 262 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); |
| 263 const base::string16 name = base::UTF8ToUTF16(info.name); | 263 const base::string16 name = base::UTF8ToUTF16(info.name); |
| 264 const base::string16 version = base::UTF8ToUTF16(info.version); | 264 const base::string16 version = base::UTF8ToUTF16(info.version); |
| 265 const blink::WebMIDIAccessorClient::MIDIPortState state = | 265 const blink::WebMIDIAccessorClient::MIDIPortState state = |
| 266 ToBlinkState(info.state); | 266 ToBlinkState(info.state); |
| 267 for (auto* client : clients_) | 267 for (auto* client : clients_) |
| 268 client->didAddInputPort(id, manufacturer, name, version, state); | 268 client->didAddInputPort(id, manufacturer, name, version, state); |
| 269 } | 269 } |
| 270 | 270 |
| 271 void MidiMessageFilter::HandleAddOutputPort(media::midi::MidiPortInfo info) { | 271 void MidiMessageFilter::HandleAddOutputPort(midi::MidiPortInfo info) { |
| 272 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 272 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 273 outputs_.push_back(info); | 273 outputs_.push_back(info); |
| 274 const base::string16 id = base::UTF8ToUTF16(info.id); | 274 const base::string16 id = base::UTF8ToUTF16(info.id); |
| 275 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); | 275 const base::string16 manufacturer = base::UTF8ToUTF16(info.manufacturer); |
| 276 const base::string16 name = base::UTF8ToUTF16(info.name); | 276 const base::string16 name = base::UTF8ToUTF16(info.name); |
| 277 const base::string16 version = base::UTF8ToUTF16(info.version); | 277 const base::string16 version = base::UTF8ToUTF16(info.version); |
| 278 const blink::WebMIDIAccessorClient::MIDIPortState state = | 278 const blink::WebMIDIAccessorClient::MIDIPortState state = |
| 279 ToBlinkState(info.state); | 279 ToBlinkState(info.state); |
| 280 for (auto* client : clients_) | 280 for (auto* client : clients_) |
| 281 client->didAddOutputPort(id, manufacturer, name, version, state); | 281 client->didAddOutputPort(id, manufacturer, name, version, state); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 294 | 294 |
| 295 void MidiMessageFilter::HandleAckknowledgeSentData(size_t bytes_sent) { | 295 void MidiMessageFilter::HandleAckknowledgeSentData(size_t bytes_sent) { |
| 296 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 296 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 297 DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent); | 297 DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent); |
| 298 if (unacknowledged_bytes_sent_ >= bytes_sent) | 298 if (unacknowledged_bytes_sent_ >= bytes_sent) |
| 299 unacknowledged_bytes_sent_ -= bytes_sent; | 299 unacknowledged_bytes_sent_ -= bytes_sent; |
| 300 } | 300 } |
| 301 | 301 |
| 302 void MidiMessageFilter::HandleSetInputPortState( | 302 void MidiMessageFilter::HandleSetInputPortState( |
| 303 uint32_t port, | 303 uint32_t port, |
| 304 media::midi::MidiPortState state) { | 304 midi::MidiPortState state) { |
| 305 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 305 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 306 inputs_[port].state = state; | 306 inputs_[port].state = state; |
| 307 for (auto* client : clients_) | 307 for (auto* client : clients_) |
| 308 client->didSetInputPortState(port, ToBlinkState(state)); | 308 client->didSetInputPortState(port, ToBlinkState(state)); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void MidiMessageFilter::HandleSetOutputPortState( | 311 void MidiMessageFilter::HandleSetOutputPortState( |
| 312 uint32_t port, | 312 uint32_t port, |
| 313 media::midi::MidiPortState state) { | 313 midi::MidiPortState state) { |
| 314 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 314 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 315 outputs_[port].state = state; | 315 outputs_[port].state = state; |
| 316 for (auto* client : clients_) | 316 for (auto* client : clients_) |
| 317 client->didSetOutputPortState(port, ToBlinkState(state)); | 317 client->didSetOutputPortState(port, ToBlinkState(state)); |
| 318 } | 318 } |
| 319 | 319 |
| 320 } // namespace content | 320 } // namespace content |
| OLD | NEW |