| 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/process/process.h" | 9 #include "base/process/process.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| 11 #include "content/browser/bad_message.h" | 11 #include "content/browser/bad_message.h" |
| 12 #include "content/browser/browser_main_loop.h" | 12 #include "content/browser/browser_main_loop.h" |
| 13 #include "content/browser/child_process_security_policy_impl.h" | 13 #include "content/browser/child_process_security_policy_impl.h" |
| 14 #include "content/common/media/midi_messages.h" | 14 #include "content/common/media/midi_messages.h" |
| 15 #include "content/public/browser/content_browser_client.h" | 15 #include "content/public/browser/content_browser_client.h" |
| 16 #include "content/public/browser/user_metrics.h" | 16 #include "content/public/browser/user_metrics.h" |
| 17 #include "media/midi/message_util.h" | 17 #include "media/midi/message_util.h" |
| 18 #include "media/midi/midi_manager.h" | |
| 19 #include "media/midi/midi_message_queue.h" | 18 #include "media/midi/midi_message_queue.h" |
| 19 #include "media/midi/midi_service.h" |
| 20 | 20 |
| 21 namespace content { | 21 namespace content { |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // 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 |
| 25 // before knowing that they have been successfully sent. | 25 // before knowing that they have been successfully sent. |
| 26 const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. | 26 const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. |
| 27 | 27 |
| 28 // We keep track of the number of bytes successfully sent to | 28 // We keep track of the number of bytes successfully sent to |
| 29 // 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 |
| 30 // 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 |
| 31 // 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. |
| 32 const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. | 32 const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. |
| 33 | 33 |
| 34 } // namespace | 34 } // namespace |
| 35 | 35 |
| 36 using midi::IsDataByte; | 36 using midi::IsDataByte; |
| 37 using midi::IsSystemRealTimeMessage; | 37 using midi::IsSystemRealTimeMessage; |
| 38 using midi::IsValidWebMIDIData; | 38 using midi::IsValidWebMIDIData; |
| 39 using midi::MidiPortInfo; | 39 using midi::MidiPortInfo; |
| 40 using midi::kSysExByte; | 40 using midi::kSysExByte; |
| 41 using midi::kEndOfSysExByte; | 41 using midi::kEndOfSysExByte; |
| 42 using midi::mojom::PortState; | 42 using midi::mojom::PortState; |
| 43 using midi::mojom::Result; | 43 using midi::mojom::Result; |
| 44 | 44 |
| 45 MidiHost::MidiHost(int renderer_process_id, | 45 MidiHost::MidiHost(int renderer_process_id, midi::MidiService* midi_service) |
| 46 midi::MidiManager* midi_manager) | |
| 47 : BrowserMessageFilter(MidiMsgStart), | 46 : BrowserMessageFilter(MidiMsgStart), |
| 48 renderer_process_id_(renderer_process_id), | 47 renderer_process_id_(renderer_process_id), |
| 49 has_sys_ex_permission_(false), | 48 has_sys_ex_permission_(false), |
| 50 is_session_requested_(false), | 49 is_session_requested_(false), |
| 51 midi_manager_(midi_manager), | 50 midi_service_(midi_service), |
| 52 sent_bytes_in_flight_(0), | 51 sent_bytes_in_flight_(0), |
| 53 bytes_sent_since_last_acknowledgement_(0), | 52 bytes_sent_since_last_acknowledgement_(0), |
| 54 output_port_count_(0) { | 53 output_port_count_(0) { |
| 55 DCHECK(midi_manager_); | 54 DCHECK(midi_service_); |
| 56 } | 55 } |
| 57 | 56 |
| 58 MidiHost::~MidiHost() = default; | 57 MidiHost::~MidiHost() = default; |
| 59 | 58 |
| 60 void MidiHost::OnChannelClosing() { | 59 void MidiHost::OnChannelClosing() { |
| 61 // If we get here the MidiHost is going to be destroyed soon. Prevent any | 60 // If we get here the MidiHost is going to be destroyed soon. Prevent any |
| 62 // subsequent calls from MidiManager by closing our session. | 61 // subsequent calls from MidiService by closing our session. |
| 63 // If Send() is called from a different thread (e.g. a separate thread owned | 62 // If Send() is called from a different thread (e.g. a separate thread owned |
| 64 // by the MidiManager implementation), it will get posted to the IO thread. | 63 // by the MidiService implementation), it will get posted to the IO thread. |
| 65 // There is a race condition here if our refcount is 0 and we're about to or | 64 // There is a race condition here if our refcount is 0 and we're about to or |
| 66 // have already entered OnDestruct(). | 65 // have already entered OnDestruct(). |
| 67 if (is_session_requested_ && midi_manager_) { | 66 if (is_session_requested_ && midi_service_) { |
| 68 midi_manager_->EndSession(this); | 67 midi_service_->EndSession(this); |
| 69 is_session_requested_ = false; | 68 is_session_requested_ = false; |
| 70 } | 69 } |
| 71 } | 70 } |
| 72 | 71 |
| 73 void MidiHost::OnDestruct() const { | 72 void MidiHost::OnDestruct() const { |
| 74 BrowserThread::DeleteOnIOThread::Destruct(this); | 73 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 75 } | 74 } |
| 76 | 75 |
| 77 // IPC Messages handler | 76 // IPC Messages handler |
| 78 bool MidiHost::OnMessageReceived(const IPC::Message& message) { | 77 bool MidiHost::OnMessageReceived(const IPC::Message& message) { |
| 79 bool handled = true; | 78 bool handled = true; |
| 80 IPC_BEGIN_MESSAGE_MAP(MidiHost, message) | 79 IPC_BEGIN_MESSAGE_MAP(MidiHost, message) |
| 81 IPC_MESSAGE_HANDLER(MidiHostMsg_StartSession, OnStartSession) | 80 IPC_MESSAGE_HANDLER(MidiHostMsg_StartSession, OnStartSession) |
| 82 IPC_MESSAGE_HANDLER(MidiHostMsg_SendData, OnSendData) | 81 IPC_MESSAGE_HANDLER(MidiHostMsg_SendData, OnSendData) |
| 83 IPC_MESSAGE_HANDLER(MidiHostMsg_EndSession, OnEndSession) | 82 IPC_MESSAGE_HANDLER(MidiHostMsg_EndSession, OnEndSession) |
| 84 IPC_MESSAGE_UNHANDLED(handled = false) | 83 IPC_MESSAGE_UNHANDLED(handled = false) |
| 85 IPC_END_MESSAGE_MAP() | 84 IPC_END_MESSAGE_MAP() |
| 86 | 85 |
| 87 return handled; | 86 return handled; |
| 88 } | 87 } |
| 89 | 88 |
| 90 void MidiHost::OnStartSession() { | 89 void MidiHost::OnStartSession() { |
| 91 is_session_requested_ = true; | 90 is_session_requested_ = true; |
| 92 if (midi_manager_) | 91 if (midi_service_) |
| 93 midi_manager_->StartSession(this); | 92 midi_service_->StartSession(this); |
| 94 } | 93 } |
| 95 | 94 |
| 96 void MidiHost::OnSendData(uint32_t port, | 95 void MidiHost::OnSendData(uint32_t port, |
| 97 const std::vector<uint8_t>& data, | 96 const std::vector<uint8_t>& data, |
| 98 double timestamp) { | 97 double timestamp) { |
| 99 { | 98 { |
| 100 base::AutoLock auto_lock(output_port_count_lock_); | 99 base::AutoLock auto_lock(output_port_count_lock_); |
| 101 if (output_port_count_ <= port) { | 100 if (output_port_count_ <= port) { |
| 102 bad_message::ReceivedBadMessage(this, bad_message::MH_INVALID_MIDI_PORT); | 101 bad_message::ReceivedBadMessage(this, bad_message::MH_INVALID_MIDI_PORT); |
| 103 return; | 102 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 121 | 120 |
| 122 { | 121 { |
| 123 base::AutoLock auto_lock(in_flight_lock_); | 122 base::AutoLock auto_lock(in_flight_lock_); |
| 124 // Sanity check that we won't send too much data. | 123 // Sanity check that we won't send too much data. |
| 125 // TODO(yukawa): Consider to send an error event back to the renderer | 124 // TODO(yukawa): Consider to send an error event back to the renderer |
| 126 // after some future discussion in W3C. | 125 // after some future discussion in W3C. |
| 127 if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) | 126 if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) |
| 128 return; | 127 return; |
| 129 sent_bytes_in_flight_ += data.size(); | 128 sent_bytes_in_flight_ += data.size(); |
| 130 } | 129 } |
| 131 if (midi_manager_) | 130 if (midi_service_) |
| 132 midi_manager_->DispatchSendMidiData(this, port, data, timestamp); | 131 midi_service_->DispatchSendMidiData(this, port, data, timestamp); |
| 133 } | 132 } |
| 134 | 133 |
| 135 void MidiHost::OnEndSession() { | 134 void MidiHost::OnEndSession() { |
| 136 is_session_requested_ = false; | 135 is_session_requested_ = false; |
| 137 if (midi_manager_) | 136 if (midi_service_) |
| 138 midi_manager_->EndSession(this); | 137 midi_service_->EndSession(this); |
| 139 } | 138 } |
| 140 | 139 |
| 141 void MidiHost::CompleteStartSession(Result result) { | 140 void MidiHost::CompleteStartSession(Result result) { |
| 142 DCHECK(is_session_requested_); | 141 DCHECK(is_session_requested_); |
| 143 if (result == Result::OK) { | 142 if (result == Result::OK) { |
| 144 // ChildSecurityPolicy is set just before OnStartSession by | 143 // ChildSecurityPolicy is set just before OnStartSession by |
| 145 // MidiDispatcherHost. So we can safely cache the policy. | 144 // MidiDispatcherHost. So we can safely cache the policy. |
| 146 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> | 145 has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> |
| 147 CanSendMidiSysExMessage(renderer_process_id_); | 146 CanSendMidiSysExMessage(renderer_process_id_); |
| 148 } | 147 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 | 214 |
| 216 if (bytes_sent_since_last_acknowledgement_ >= | 215 if (bytes_sent_since_last_acknowledgement_ >= |
| 217 kAcknowledgementThresholdBytes) { | 216 kAcknowledgementThresholdBytes) { |
| 218 Send(new MidiMsg_AcknowledgeSentData( | 217 Send(new MidiMsg_AcknowledgeSentData( |
| 219 bytes_sent_since_last_acknowledgement_)); | 218 bytes_sent_since_last_acknowledgement_)); |
| 220 bytes_sent_since_last_acknowledgement_ = 0; | 219 bytes_sent_since_last_acknowledgement_ = 0; |
| 221 } | 220 } |
| 222 } | 221 } |
| 223 | 222 |
| 224 void MidiHost::Detach() { | 223 void MidiHost::Detach() { |
| 225 midi_manager_ = nullptr; | 224 midi_service_ = nullptr; |
| 226 } | 225 } |
| 227 | 226 |
| 228 } // namespace content | 227 } // namespace content |
| OLD | NEW |