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/browser/media/midi_host.h" | 5 #include "content/browser/media/midi_host.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/metrics/histogram_macros.h" | |
10 #include "base/process/process.h" | 9 #include "base/process/process.h" |
11 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
12 #include "content/browser/bad_message.h" | 11 #include "content/browser/bad_message.h" |
13 #include "content/browser/browser_main_loop.h" | 12 #include "content/browser/browser_main_loop.h" |
14 #include "content/browser/child_process_security_policy_impl.h" | 13 #include "content/browser/child_process_security_policy_impl.h" |
15 #include "content/common/media/midi_messages.h" | 14 #include "content/common/media/midi_messages.h" |
16 #include "content/public/browser/content_browser_client.h" | 15 #include "content/public/browser/content_browser_client.h" |
17 #include "content/public/browser/user_metrics.h" | 16 #include "content/public/browser/user_metrics.h" |
| 17 #include "media/midi/message_util.h" |
18 #include "media/midi/midi_manager.h" | 18 #include "media/midi/midi_manager.h" |
19 #include "media/midi/midi_message_queue.h" | 19 #include "media/midi/midi_message_queue.h" |
20 #include "media/midi/midi_message_util.h" | |
21 | 20 |
22 namespace content { | 21 namespace content { |
23 namespace { | 22 namespace { |
24 | 23 |
25 // The total number of bytes which we're allowed to send to the OS | 24 // The total number of bytes which we're allowed to send to the OS |
26 // before knowing that they have been successfully sent. | 25 // before knowing that they have been successfully sent. |
27 const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. | 26 const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. |
28 | 27 |
29 // We keep track of the number of bytes successfully sent to | 28 // We keep track of the number of bytes successfully sent to |
30 // the hardware. Every once in a while we report back to the renderer | 29 // the hardware. Every once in a while we report back to the renderer |
31 // the number of bytes sent since the last report. This threshold determines | 30 // the number of bytes sent since the last report. This threshold determines |
32 // how many bytes will be sent before reporting back to the renderer. | 31 // how many bytes will be sent before reporting back to the renderer. |
33 const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. | 32 const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. |
34 | 33 |
35 bool IsDataByte(uint8_t data) { | |
36 return (data & 0x80) == 0; | |
37 } | |
38 | |
39 bool IsSystemRealTimeMessage(uint8_t data) { | |
40 return 0xf8 <= data && data <= 0xff; | |
41 } | |
42 | |
43 } // namespace | 34 } // namespace |
44 | 35 |
| 36 using midi::IsDataByte; |
| 37 using midi::IsSystemRealTimeMessage; |
| 38 using midi::IsValidWebMIDIData; |
| 39 using midi::MidiPortInfo; |
45 using midi::kSysExByte; | 40 using midi::kSysExByte; |
46 using midi::kEndOfSysExByte; | 41 using midi::kEndOfSysExByte; |
47 using midi::mojom::Result; | 42 using midi::mojom::Result; |
48 | 43 |
49 MidiHost::MidiHost(int renderer_process_id, | 44 MidiHost::MidiHost(int renderer_process_id, |
50 midi::MidiManager* midi_manager) | 45 midi::MidiManager* midi_manager) |
51 : BrowserMessageFilter(MidiMsgStart), | 46 : BrowserMessageFilter(MidiMsgStart), |
52 renderer_process_id_(renderer_process_id), | 47 renderer_process_id_(renderer_process_id), |
53 has_sys_ex_permission_(false), | 48 has_sys_ex_permission_(false), |
54 is_session_requested_(false), | 49 is_session_requested_(false), |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 DCHECK(is_session_requested_); | 141 DCHECK(is_session_requested_); |
147 if (result == Result::OK) { | 142 if (result == Result::OK) { |
148 // ChildSecurityPolicy is set just before OnStartSession by | 143 // ChildSecurityPolicy is set just before OnStartSession by |
149 // MidiDispatcherHost. So we can safely cache the policy. | 144 // MidiDispatcherHost. So we can safely cache the policy. |
150 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> | 145 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> |
151 CanSendMidiSysExMessage(renderer_process_id_); | 146 CanSendMidiSysExMessage(renderer_process_id_); |
152 } | 147 } |
153 Send(new MidiMsg_SessionStarted(result)); | 148 Send(new MidiMsg_SessionStarted(result)); |
154 } | 149 } |
155 | 150 |
156 void MidiHost::AddInputPort(const midi::MidiPortInfo& info) { | 151 void MidiHost::AddInputPort(const MidiPortInfo& info) { |
157 base::AutoLock auto_lock(messages_queues_lock_); | 152 base::AutoLock auto_lock(messages_queues_lock_); |
158 // MidiMessageQueue is created later in ReceiveMidiData(). | 153 // MidiMessageQueue is created later in ReceiveMidiData(). |
159 received_messages_queues_.push_back(nullptr); | 154 received_messages_queues_.push_back(nullptr); |
160 Send(new MidiMsg_AddInputPort(info)); | 155 Send(new MidiMsg_AddInputPort(info)); |
161 } | 156 } |
162 | 157 |
163 void MidiHost::AddOutputPort(const midi::MidiPortInfo& info) { | 158 void MidiHost::AddOutputPort(const MidiPortInfo& info) { |
164 base::AutoLock auto_lock(output_port_count_lock_); | 159 base::AutoLock auto_lock(output_port_count_lock_); |
165 output_port_count_++; | 160 output_port_count_++; |
166 Send(new MidiMsg_AddOutputPort(info)); | 161 Send(new MidiMsg_AddOutputPort(info)); |
167 } | 162 } |
168 | 163 |
169 void MidiHost::SetInputPortState(uint32_t port, | 164 void MidiHost::SetInputPortState(uint32_t port, |
170 midi::MidiPortState state) { | 165 midi::MidiPortState state) { |
171 Send(new MidiMsg_SetInputPortState(port, state)); | 166 Send(new MidiMsg_SetInputPortState(port, state)); |
172 } | 167 } |
173 | 168 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 Send(new MidiMsg_AcknowledgeSentData( | 219 Send(new MidiMsg_AcknowledgeSentData( |
225 bytes_sent_since_last_acknowledgement_)); | 220 bytes_sent_since_last_acknowledgement_)); |
226 bytes_sent_since_last_acknowledgement_ = 0; | 221 bytes_sent_since_last_acknowledgement_ = 0; |
227 } | 222 } |
228 } | 223 } |
229 | 224 |
230 void MidiHost::Detach() { | 225 void MidiHost::Detach() { |
231 midi_manager_ = nullptr; | 226 midi_manager_ = nullptr; |
232 } | 227 } |
233 | 228 |
234 // static | |
235 bool MidiHost::IsValidWebMIDIData(const std::vector<uint8_t>& data) { | |
236 bool in_sysex = false; | |
237 size_t sysex_start_offset = 0; | |
238 size_t waiting_data_length = 0; | |
239 for (size_t i = 0; i < data.size(); ++i) { | |
240 const uint8_t current = data[i]; | |
241 if (IsSystemRealTimeMessage(current)) | |
242 continue; // Real time message can be placed at any point. | |
243 if (waiting_data_length > 0) { | |
244 if (!IsDataByte(current)) | |
245 return false; // Error: |current| should have been data byte. | |
246 --waiting_data_length; | |
247 continue; // Found data byte as expected. | |
248 } | |
249 if (in_sysex) { | |
250 if (data[i] == kEndOfSysExByte) { | |
251 in_sysex = false; | |
252 UMA_HISTOGRAM_COUNTS("Media.Midi.SysExMessageSizeUpTo1MB", | |
253 i - sysex_start_offset + 1); | |
254 } else if (!IsDataByte(current)) { | |
255 return false; // Error: |current| should have been data byte. | |
256 } | |
257 continue; // Found data byte as expected. | |
258 } | |
259 if (current == kSysExByte) { | |
260 in_sysex = true; | |
261 sysex_start_offset = i; | |
262 continue; // Found SysEX | |
263 } | |
264 waiting_data_length = midi::GetMidiMessageLength(current); | |
265 if (waiting_data_length == 0) | |
266 return false; // Error: |current| should have been a valid status byte. | |
267 --waiting_data_length; // Found status byte | |
268 } | |
269 return waiting_data_length == 0 && !in_sysex; | |
270 } | |
271 | |
272 } // namespace content | 229 } // namespace content |
OLD | NEW |