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 |