| 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/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/process/process.h" | 10 #include "base/process/process.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 | 45 |
| 46 } // namespace | 46 } // namespace |
| 47 | 47 |
| 48 using media::kSysExByte; | 48 using media::kSysExByte; |
| 49 using media::kEndOfSysExByte; | 49 using media::kEndOfSysExByte; |
| 50 | 50 |
| 51 MidiHost::MidiHost(int renderer_process_id, media::MidiManager* midi_manager) | 51 MidiHost::MidiHost(int renderer_process_id, media::MidiManager* midi_manager) |
| 52 : BrowserMessageFilter(MidiMsgStart), | 52 : BrowserMessageFilter(MidiMsgStart), |
| 53 renderer_process_id_(renderer_process_id), | 53 renderer_process_id_(renderer_process_id), |
| 54 has_sys_ex_permission_(false), | 54 has_sys_ex_permission_(false), |
| 55 is_session_requested_(false), |
| 55 midi_manager_(midi_manager), | 56 midi_manager_(midi_manager), |
| 56 sent_bytes_in_flight_(0), | 57 sent_bytes_in_flight_(0), |
| 57 bytes_sent_since_last_acknowledgement_(0) { | 58 bytes_sent_since_last_acknowledgement_(0) { |
| 59 CHECK(midi_manager_); |
| 58 } | 60 } |
| 59 | 61 |
| 60 MidiHost::~MidiHost() { | 62 MidiHost::~MidiHost() { |
| 61 if (midi_manager_) | 63 // Close an open session, or abort opening a session. |
| 64 if (is_session_requested_) |
| 62 midi_manager_->EndSession(this); | 65 midi_manager_->EndSession(this); |
| 63 } | 66 } |
| 64 | 67 |
| 65 void MidiHost::OnDestruct() const { | 68 void MidiHost::OnDestruct() const { |
| 66 BrowserThread::DeleteOnIOThread::Destruct(this); | 69 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 67 } | 70 } |
| 68 | 71 |
| 69 // IPC Messages handler | 72 // IPC Messages handler |
| 70 bool MidiHost::OnMessageReceived(const IPC::Message& message) { | 73 bool MidiHost::OnMessageReceived(const IPC::Message& message) { |
| 71 bool handled = true; | 74 bool handled = true; |
| 72 IPC_BEGIN_MESSAGE_MAP(MidiHost, message) | 75 IPC_BEGIN_MESSAGE_MAP(MidiHost, message) |
| 73 IPC_MESSAGE_HANDLER(MidiHostMsg_StartSession, OnStartSession) | 76 IPC_MESSAGE_HANDLER(MidiHostMsg_StartSession, OnStartSession) |
| 74 IPC_MESSAGE_HANDLER(MidiHostMsg_SendData, OnSendData) | 77 IPC_MESSAGE_HANDLER(MidiHostMsg_SendData, OnSendData) |
| 78 IPC_MESSAGE_HANDLER(MidiHostMsg_EndSession, OnEndSession) |
| 75 IPC_MESSAGE_UNHANDLED(handled = false) | 79 IPC_MESSAGE_UNHANDLED(handled = false) |
| 76 IPC_END_MESSAGE_MAP() | 80 IPC_END_MESSAGE_MAP() |
| 77 | 81 |
| 78 return handled; | 82 return handled; |
| 79 } | 83 } |
| 80 | 84 |
| 81 void MidiHost::OnStartSession(int client_id) { | 85 void MidiHost::OnStartSession() { |
| 82 if (midi_manager_) | 86 is_session_requested_ = true; |
| 83 midi_manager_->StartSession(this, client_id); | 87 midi_manager_->StartSession(this); |
| 84 } | 88 } |
| 85 | 89 |
| 86 void MidiHost::OnSendData(uint32 port, | 90 void MidiHost::OnSendData(uint32 port, |
| 87 const std::vector<uint8>& data, | 91 const std::vector<uint8>& data, |
| 88 double timestamp) { | 92 double timestamp) { |
| 89 if (!midi_manager_) | |
| 90 return; | |
| 91 | |
| 92 if (data.empty()) | 93 if (data.empty()) |
| 93 return; | 94 return; |
| 94 | 95 |
| 95 // Blink running in a renderer checks permission to raise a SecurityError | 96 // Blink running in a renderer checks permission to raise a SecurityError |
| 96 // in JavaScript. The actual permission check for security purposes | 97 // in JavaScript. The actual permission check for security purposes |
| 97 // happens here in the browser process. | 98 // happens here in the browser process. |
| 98 if (!has_sys_ex_permission_ && | 99 if (!has_sys_ex_permission_ && |
| 99 std::find(data.begin(), data.end(), kSysExByte) != data.end()) { | 100 std::find(data.begin(), data.end(), kSysExByte) != data.end()) { |
| 100 RecordAction(base::UserMetricsAction("BadMessageTerminate_MIDI")); | 101 RecordAction(base::UserMetricsAction("BadMessageTerminate_MIDI")); |
| 101 BadMessageReceived(); | 102 BadMessageReceived(); |
| 102 return; | 103 return; |
| 103 } | 104 } |
| 104 | 105 |
| 105 if (!IsValidWebMIDIData(data)) | 106 if (!IsValidWebMIDIData(data)) |
| 106 return; | 107 return; |
| 107 | 108 |
| 108 { | 109 { |
| 109 base::AutoLock auto_lock(in_flight_lock_); | 110 base::AutoLock auto_lock(in_flight_lock_); |
| 110 // Sanity check that we won't send too much data. | 111 // Sanity check that we won't send too much data. |
| 111 // TODO(yukawa): Consider to send an error event back to the renderer | 112 // TODO(yukawa): Consider to send an error event back to the renderer |
| 112 // after some future discussion in W3C. | 113 // after some future discussion in W3C. |
| 113 if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) | 114 if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) |
| 114 return; | 115 return; |
| 115 sent_bytes_in_flight_ += data.size(); | 116 sent_bytes_in_flight_ += data.size(); |
| 116 } | 117 } |
| 117 midi_manager_->DispatchSendMidiData(this, port, data, timestamp); | 118 midi_manager_->DispatchSendMidiData(this, port, data, timestamp); |
| 118 } | 119 } |
| 119 | 120 |
| 120 void MidiHost::CompleteStartSession(int client_id, media::MidiResult result) { | 121 void MidiHost::OnEndSession() { |
| 122 is_session_requested_ = false; |
| 123 midi_manager_->EndSession(this); |
| 124 } |
| 125 |
| 126 void MidiHost::CompleteStartSession(media::MidiResult result) { |
| 127 DCHECK(is_session_requested_); |
| 121 MidiPortInfoList input_ports; | 128 MidiPortInfoList input_ports; |
| 122 MidiPortInfoList output_ports; | 129 MidiPortInfoList output_ports; |
| 123 | 130 |
| 124 if (result == media::MIDI_OK) { | 131 if (result == media::MIDI_OK) { |
| 125 input_ports = midi_manager_->input_ports(); | 132 input_ports = midi_manager_->input_ports(); |
| 126 output_ports = midi_manager_->output_ports(); | 133 output_ports = midi_manager_->output_ports(); |
| 127 received_messages_queues_.clear(); | 134 received_messages_queues_.clear(); |
| 128 received_messages_queues_.resize(input_ports.size()); | 135 received_messages_queues_.resize(input_ports.size()); |
| 129 // ChildSecurityPolicy is set just before OnStartSession by | 136 // ChildSecurityPolicy is set just before OnStartSession by |
| 130 // MidiDispatcherHost. So we can safely cache the policy. | 137 // MidiDispatcherHost. So we can safely cache the policy. |
| 131 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> | 138 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> |
| 132 CanSendMidiSysExMessage(renderer_process_id_); | 139 CanSendMidiSysExMessage(renderer_process_id_); |
| 133 } | 140 } |
| 134 | 141 |
| 135 Send(new MidiMsg_SessionStarted(client_id, | 142 Send(new MidiMsg_SessionStarted(result, |
| 136 result, | |
| 137 input_ports, | 143 input_ports, |
| 138 output_ports)); | 144 output_ports)); |
| 139 } | 145 } |
| 140 | 146 |
| 141 void MidiHost::ReceiveMidiData( | 147 void MidiHost::ReceiveMidiData( |
| 142 uint32 port, | 148 uint32 port, |
| 143 const uint8* data, | 149 const uint8* data, |
| 144 size_t length, | 150 size_t length, |
| 145 double timestamp) { | 151 double timestamp) { |
| 146 TRACE_EVENT0("midi", "MidiHost::ReceiveMidiData"); | 152 TRACE_EVENT0("midi", "MidiHost::ReceiveMidiData"); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 } | 222 } |
| 217 waiting_data_length = media::GetMidiMessageLength(current); | 223 waiting_data_length = media::GetMidiMessageLength(current); |
| 218 if (waiting_data_length == 0) | 224 if (waiting_data_length == 0) |
| 219 return false; // Error: |current| should have been a valid status byte. | 225 return false; // Error: |current| should have been a valid status byte. |
| 220 --waiting_data_length; // Found status byte | 226 --waiting_data_length; // Found status byte |
| 221 } | 227 } |
| 222 return waiting_data_length == 0 && !in_sysex; | 228 return waiting_data_length == 0 && !in_sysex; |
| 223 } | 229 } |
| 224 | 230 |
| 225 } // namespace content | 231 } // namespace content |
| OLD | NEW |