| 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 |