Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(981)

Unified Diff: content/browser/renderer_host/media/midi_host.cc

Issue 68353002: Use MIDIMessageQueue/IsValidWebMIDIData for MIDI byte stream validation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use MIDIMessageQueue in MIDIHost::OnSendData as well as MIDIHost::ReceiveMIDIData Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/media/midi_host.cc
diff --git a/content/browser/renderer_host/media/midi_host.cc b/content/browser/renderer_host/media/midi_host.cc
index 934d5a21f1839fa97a5740fc60d28bba1936a05a..4132882a3fe9d9adf7d74345ba961ee33d1031d9 100644
--- a/content/browser/renderer_host/media/midi_host.cc
+++ b/content/browser/renderer_host/media/midi_host.cc
@@ -16,6 +16,7 @@
#include "content/public/browser/media_observer.h"
#include "content/public/browser/user_metrics.h"
#include "media/midi/midi_manager.h"
+#include "media/midi/midi_message_queue.h"
using media::MIDIManager;
using media::MIDIPortInfoList;
@@ -33,6 +34,37 @@ static const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB.
static const uint8 kSysExMessage = 0xf0;
namespace content {
+namespace {
+
+// A class to check if current child process security policy allows the the
+// renderer to use SysEx MIDI messages or not. This class fetches the policy
+// lazily and caches the result to avoid redundant access check.
+class CanSendMIDISysExMessageQuery {
+ public:
+ explicit CanSendMIDISysExMessageQuery(int renderer_process_id)
+ : renderer_process_id_(renderer_process_id),
+ value_(false),
+ initialized_(false) {
+ }
+
+ bool get() {
+ if (!initialized_) {
+ value_ = ChildProcessSecurityPolicyImpl::GetInstance()->
+ CanSendMIDISysExMessage(renderer_process_id_);
+ initialized_ = true;
+ }
+ return value_;
+ }
+
+ private:
+ const int renderer_process_id_;
+ bool value_;
+ bool initialized_;
+
+ DISALLOW_COPY_AND_ASSIGN(CanSendMIDISysExMessageQuery);
+};
+
+} // namespace
MIDIHost::MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager)
: renderer_process_id_(renderer_process_id),
@@ -75,6 +107,8 @@ void MIDIHost::OnStartSession(int client_id) {
if (success) {
input_ports = midi_manager_->input_ports();
output_ports = midi_manager_->output_ports();
+ received_messages_queues_.clear();
+ received_messages_queues_.resize(input_ports.size());
}
}
@@ -94,33 +128,39 @@ void MIDIHost::OnSendData(uint32 port,
if (data.empty())
return;
- base::AutoLock auto_lock(in_flight_lock_);
-
- // Sanity check that we won't send too much.
- if (sent_bytes_in_flight_ > kMaxInFlightBytes ||
- data.size() > kMaxInFlightBytes ||
- data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
- return;
-
- if (data[0] >= kSysExMessage) {
- // Blink running in a renderer checks permission to raise a SecurityError in
- // JavaScript. The actual permission check for security perposes happens
- // here in the browser process.
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
- renderer_process_id_)) {
+ CanSendMIDISysExMessageQuery can_send_sys_ex(renderer_process_id_);
Takashi Toyoshima 2013/11/19 01:08:37 Can we make it a member variable? IIRC, this code
yukawa 2013/11/19 09:41:41 Hmm, I think the construction cost of |can_send_sy
Takashi Toyoshima 2013/11/19 12:49:59 I see. It's ok to keep this code as is. FYI, Chil
+
+ // Note: In the spec, |data| can be any number of complete MIDI messages.
+ // Running status is disallowed explicitly.
+ media::MIDIMessageQueue message_queue(false);
+ message_queue.Add(data);
+ std::vector<uint8> message;
+ while (true) {
+ message_queue.Get(&message);
+ if (message.empty())
+ break;
+
+ // Sanity check that we won't send too large message.
Takashi Toyoshima 2013/11/19 01:08:37 Here, we concern the buffer size which may be allo
yukawa 2013/11/19 09:41:41 Done.
+ if (message.size() > kMaxInFlightBytes)
Takashi Toyoshima 2013/11/19 01:08:37 This check looks redundant.
yukawa 2013/11/19 09:41:41 I put this condition here as an early exit route b
+ continue;
+
+ if (message[0] == kSysExMessage && !can_send_sys_ex.get()) {
+ // Blink running in a renderer checks permission to raise a SecurityError
+ // in JavaScript. The actual permission check for security purposes
+ // happens here in the browser process.
RecordAction(UserMetricsAction("BadMessageTerminate_MIDI"));
BadMessageReceived();
return;
}
- }
-
- midi_manager_->DispatchSendMIDIData(
- this,
- port,
- data,
- timestamp);
- sent_bytes_in_flight_ += data.size();
+ base::AutoLock auto_lock(in_flight_lock_);
+ // Sanity check that we won't send too much data.
+ if (sent_bytes_in_flight_ > kMaxInFlightBytes ||
+ message.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
Takashi Toyoshima 2013/11/19 01:08:37 Same TODO here, and any reason to check twice? I f
yukawa 2013/11/19 09:41:41 Done. BTW, the redundancy came from the original c
Takashi Toyoshima 2013/11/19 12:49:59 lol
+ return;
+ midi_manager_->DispatchSendMIDIData(this, port, message, timestamp);
+ sent_bytes_in_flight_ += message.size();
+ }
}
void MIDIHost::ReceiveMIDIData(
@@ -130,20 +170,31 @@ void MIDIHost::ReceiveMIDIData(
double timestamp) {
TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
- // Check a process security policy to receive a system exclusive message.
- if (length > 0 && data[0] >= kSysExMessage) {
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
- renderer_process_id_)) {
- // MIDI devices may send a system exclusive messages even if the renderer
- // doesn't have a permission to receive it. Don't kill the renderer as
- // OnSendData() does.
- return;
- }
- }
+ if (received_messages_queues_.size() <= port)
+ return;
+
+ // Lazy initialization
+ if (received_messages_queues_[port] == NULL)
+ received_messages_queues_[port] = new media::MIDIMessageQueue(true);
+
+ CanSendMIDISysExMessageQuery can_send_sys_ex(renderer_process_id_);
Takashi Toyoshima 2013/11/19 01:08:37 ditto. I think we can share the same instance betw
yukawa 2013/11/19 09:41:41 See my previous comment.
Takashi Toyoshima 2013/11/19 12:49:59 ok
- // Send to the renderer.
- std::vector<uint8> v(data, data + length);
- Send(new MIDIMsg_DataReceived(port, v, timestamp));
+ received_messages_queues_[port]->Add(data, length);
+ std::vector<uint8> message;
+ while (true) {
+ received_messages_queues_[port]->Get(&message);
+ if (message.empty())
+ break;
+
+ // MIDI devices may send a system exclusive messages even if the renderer
+ // doesn't have a permission to receive it. Don't kill the renderer as
+ // OnSendData() does.
+ if (message[0] == kSysExMessage && !can_send_sys_ex.get())
+ continue;
+
+ // Send to the renderer.
+ Send(new MIDIMsg_DataReceived(port, message, timestamp));
+ }
}
void MIDIHost::AccumulateMIDIBytesSent(size_t n) {

Powered by Google App Engine
This is Rietveld 408576698