summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcrogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-22 04:03:03 +0000
committercrogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-22 04:03:03 +0000
commita987515b634b4d8aaecc55ec4bb9491be8788b67 (patch)
tree7925b49f6b3884aff276a43a19463d3a73127c79 /content
parent9f7a254a647dd14bb00532d8e570dbb328704281 (diff)
downloadchromium_src-a987515b634b4d8aaecc55ec4bb9491be8788b67.zip
chromium_src-a987515b634b4d8aaecc55ec4bb9491be8788b67.tar.gz
chromium_src-a987515b634b4d8aaecc55ec4bb9491be8788b67.tar.bz2
Re-land 16025005 with tiny fix for statics perf issue
16025005 had review from: palmer@chromium.org, piman@chromium.org, scherkus@chromium.org BUG=163795 TBR=scherkus@chromium.org Review URL: https://codereview.chromium.org/17288018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208003 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/DEPS1
-rw-r--r--content/browser/browser_main_loop.cc6
-rw-r--r--content/browser/browser_main_loop.h3
-rw-r--r--content/browser/renderer_host/media/midi_host.cc99
-rw-r--r--content/browser/renderer_host/media/midi_host.h62
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc3
-rw-r--r--content/common/content_message_generator.h1
-rw-r--r--content/common/media/midi_messages.h46
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/content_renderer.gypi4
-rw-r--r--content/renderer/media/midi_message_filter.cc199
-rw-r--r--content/renderer/media/midi_message_filter.h116
-rw-r--r--content/renderer/media/renderer_webmidiaccessor_impl.cc43
-rw-r--r--content/renderer/media/renderer_webmidiaccessor_impl.h41
-rw-r--r--content/renderer/render_thread_impl.cc4
-rw-r--r--content/renderer/render_thread_impl.h5
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.cc10
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.h2
19 files changed, 647 insertions, 1 deletions
diff --git a/content/browser/DEPS b/content/browser/DEPS
index c447bea..67ca2ef 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+content/child/webkitplatformsupport_impl.h", # For in-process webkit
"+media/audio", # For audio input for speech input feature.
"+media/base", # For Android JNI registration.
+ "+media/midi", # For Web MIDI API
"+sql",
"+ui/webui",
"+win8/util",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 4e1411d..9599d85 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -47,6 +47,7 @@
#include "crypto/nss_util.h"
#include "media/audio/audio_manager.h"
#include "media/base/media.h"
+#include "media/midi/midi_manager.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/ssl/ssl_config_service.h"
@@ -400,7 +401,10 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMan")
audio_manager_.reset(media::AudioManager::Create());
}
-
+ {
+ TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MIDIManager")
+ midi_manager_.reset(media::MIDIManager::Create());
+ }
#if !defined(OS_IOS)
{
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 0317e03..fc412cc 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -20,6 +20,7 @@ class SystemMonitor;
namespace media {
class AudioManager;
+class MIDIManager;
}
namespace net {
@@ -81,6 +82,7 @@ class BrowserMainLoop {
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
}
+ media::MIDIManager* midi_manager() const { return midi_manager_.get(); }
private:
class MemoryObserver;
@@ -106,6 +108,7 @@ class BrowserMainLoop {
scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
scoped_ptr<media::AudioManager> audio_manager_;
+ scoped_ptr<media::MIDIManager> midi_manager_;
scoped_ptr<AudioMirroringManager> audio_mirroring_manager_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
// Per-process listener for online state changes.
diff --git a/content/browser/renderer_host/media/midi_host.cc b/content/browser/renderer_host/media/midi_host.cc
new file mode 100644
index 0000000..56f4099
--- /dev/null
+++ b/content/browser/renderer_host/media/midi_host.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/midi_host.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/debug/trace_event.h"
+#include "base/process.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/media/media_internals.h"
+#include "content/common/media/midi_messages.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/media_observer.h"
+#include "media/midi/midi_manager.h"
+
+using media::MIDIManager;
+using media::MIDIPortInfoList;
+
+namespace content {
+
+MIDIHost::MIDIHost(media::MIDIManager* midi_manager)
+ : midi_manager_(midi_manager) {
+}
+
+MIDIHost::~MIDIHost() {
+ if (midi_manager_)
+ midi_manager_->ReleaseAccess(this);
+}
+
+void MIDIHost::OnChannelClosing() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ BrowserMessageFilter::OnChannelClosing();
+}
+
+void MIDIHost::OnDestruct() const {
+ BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// IPC Messages handler
+bool MIDIHost::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(MIDIHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(MIDIHostMsg_RequestAccess, OnRequestAccess)
+ IPC_MESSAGE_HANDLER(MIDIHostMsg_SendData, OnSendData)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+
+ return handled;
+}
+
+void MIDIHost::OnRequestAccess(int client_id, int access) {
+ MIDIPortInfoList input_ports;
+ MIDIPortInfoList output_ports;
+
+ // Ask permission and register to receive MIDI data.
+ bool approved = false;
+ if (midi_manager_) {
+ approved = midi_manager_->RequestAccess(this, access);
+ if (approved) {
+ input_ports = midi_manager_->input_ports();
+ output_ports = midi_manager_->output_ports();
+ }
+ }
+
+ Send(new MIDIMsg_AccessApproved(
+ client_id,
+ access,
+ approved,
+ input_ports,
+ output_ports));
+}
+
+void MIDIHost::OnSendData(int port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ // TODO(crogers): we need to post this to a dedicated thread for
+ // sending MIDI. For now, we will not implement the sending of MIDI data.
+ NOTIMPLEMENTED();
+ // if (midi_manager_)
+ // midi_manager_->SendMIDIData(port, data.data(), data.size(), timestamp);
+}
+
+void MIDIHost::ReceiveMIDIData(
+ int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) {
+ TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
+ // Send to the renderer.
+ std::vector<uint8> v(data, data + length);
+ Send(new MIDIMsg_DataReceived(port_index, v, timestamp));
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/media/midi_host.h b/content/browser/renderer_host/media/midi_host.h
new file mode 100644
index 0000000..e46ed53
--- /dev/null
+++ b/content/browser/renderer_host/media/midi_host.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_thread.h"
+#include "media/midi/midi_manager.h"
+
+namespace media {
+class MIDIManager;
+}
+
+namespace content {
+
+class CONTENT_EXPORT MIDIHost
+ : public BrowserMessageFilter,
+ public media::MIDIManagerClient {
+ public:
+ // Called from UI thread from the owner of this object.
+ MIDIHost(media::MIDIManager* midi_manager);
+
+ // BrowserMessageFilter implementation.
+ virtual void OnChannelClosing() OVERRIDE;
+ virtual void OnDestruct() const OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ // MIDIManagerClient implementation.
+ virtual void ReceiveMIDIData(
+ int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) OVERRIDE;
+
+ // Request access to MIDI hardware.
+ void OnRequestAccess(int client_id, int access);
+
+ // Data to be sent to a MIDI output port.
+ void OnSendData(int port,
+ const std::vector<uint8>& data,
+ double timestamp);
+
+ private:
+ friend class base::DeleteHelper<MIDIHost>;
+ friend class BrowserThread;
+
+ virtual ~MIDIHost();
+
+ media::MIDIManager* const midi_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(MIDIHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 65268c1..20b7b99 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -73,6 +73,7 @@
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
+#include "content/browser/renderer_host/media/midi_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
@@ -604,6 +605,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
media_internals, media_stream_manager));
+ channel_->AddFilter(
+ new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
channel_->AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(),
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 2a54f56..35927dd 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -31,6 +31,7 @@
#include "content/common/input_messages.h"
#include "content/common/java_bridge_messages.h"
#include "content/common/media/audio_messages.h"
+#include "content/common/media/midi_messages.h"
#if defined(OS_ANDROID)
#include "content/common/media/media_player_messages_android.h"
#endif
diff --git a/content/common/media/midi_messages.h b/content/common/media/midi_messages.h
new file mode 100644
index 0000000..de3cca6
--- /dev/null
+++ b/content/common/media/midi_messages.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for access to MIDI hardware.
+// Multiply-included message file, hence no include guard.
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+#include "media/midi/midi_port_info.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START MIDIMsgStart
+
+IPC_STRUCT_TRAITS_BEGIN(media::MIDIPortInfo)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(manufacturer)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(version)
+IPC_STRUCT_TRAITS_END()
+
+// Renderer request to browser for access to MIDI services.
+IPC_MESSAGE_CONTROL2(MIDIHostMsg_RequestAccess,
+ int /* client id */,
+ int /* access */)
+
+IPC_MESSAGE_CONTROL3(MIDIHostMsg_SendData,
+ int /* port */,
+ std::vector<uint8> /* data */,
+ double /* timestamp */)
+
+// Messages sent from the browser to the renderer.
+
+IPC_MESSAGE_CONTROL5(MIDIMsg_AccessApproved,
+ int /* client id */,
+ int /* access */,
+ bool /* success */,
+ media::MIDIPortInfoList /* input ports */,
+ media::MIDIPortInfoList /* output ports */)
+
+IPC_MESSAGE_CONTROL3(MIDIMsg_DataReceived,
+ int /* port */,
+ std::vector<uint8> /* data */,
+ double /* timestamp */)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index c7425fb..1984709 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -791,6 +791,8 @@
'browser/renderer_host/media/media_stream_requester.h',
'browser/renderer_host/media/media_stream_ui_proxy.cc',
'browser/renderer_host/media/media_stream_ui_proxy.h',
+ 'browser/renderer_host/media/midi_host.cc',
+ 'browser/renderer_host/media/midi_host.h',
'browser/renderer_host/media/video_capture_buffer_pool.cc',
'browser/renderer_host/media/video_capture_buffer_pool.h',
'browser/renderer_host/media/video_capture_controller.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 29b6e07..1ed029b 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -265,6 +265,7 @@
'common/media/media_stream_messages.h',
'common/media/media_stream_options.cc',
'common/media/media_stream_options.h',
+ 'common/media/midi_messages.h',
'common/media/video_capture.h',
'common/media/video_capture_messages.h',
'common/memory_benchmark_messages.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index c8e52fd..24cd543b 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -156,6 +156,8 @@
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/media_stream_impl.h',
+ 'renderer/media/midi_message_filter.cc',
+ 'renderer/media/midi_message_filter.h',
'renderer/media/pepper_platform_video_decoder_impl.cc',
'renderer/media/pepper_platform_video_decoder_impl.h',
'renderer/media/render_media_log.cc',
@@ -164,6 +166,8 @@
'renderer/media/renderer_gpu_video_decoder_factories.h',
'renderer/media/renderer_webaudiodevice_impl.cc',
'renderer/media/renderer_webaudiodevice_impl.h',
+ 'renderer/media/renderer_webmidiaccessor_impl.cc',
+ 'renderer/media/renderer_webmidiaccessor_impl.h',
'renderer/media/rtc_video_renderer.cc',
'renderer/media/rtc_video_renderer.h',
'renderer/media/stream_texture_factory_impl_android.cc',
diff --git a/content/renderer/media/midi_message_filter.cc b/content/renderer/media/midi_message_filter.cc
new file mode 100644
index 0000000..1abb537
--- /dev/null
+++ b/content/renderer/media/midi_message_filter.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/midi_message_filter.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/common/media/midi_messages.h"
+#include "content/renderer/render_thread_impl.h"
+#include "ipc/ipc_logging.h"
+
+using media::MIDIPortInfoList;
+using base::AutoLock;
+
+namespace content {
+
+MIDIMessageFilter::MIDIMessageFilter(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
+ : channel_(NULL),
+ io_message_loop_(io_message_loop),
+ next_available_id_(0) {
+}
+
+MIDIMessageFilter::~MIDIMessageFilter() {}
+
+void MIDIMessageFilter::Send(IPC::Message* message) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ if (!channel_) {
+ delete message;
+ } else {
+ channel_->Send(message);
+ }
+}
+
+bool MIDIMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MIDIMessageFilter, message)
+ IPC_MESSAGE_HANDLER(MIDIMsg_AccessApproved, OnAccessApproved)
+ IPC_MESSAGE_HANDLER(MIDIMsg_DataReceived, OnDataReceived)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void MIDIMessageFilter::OnFilterAdded(IPC::Channel* channel) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ channel_ = channel;
+}
+
+void MIDIMessageFilter::OnFilterRemoved() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+
+ // Once removed, a filter will not be used again. At this time all
+ // delegates must be notified so they release their reference.
+ OnChannelClosing();
+}
+
+void MIDIMessageFilter::OnChannelClosing() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ channel_ = NULL;
+}
+
+void MIDIMessageFilter::RequestAccess(
+ WebKit::WebMIDIAccessorClient* client, int access) {
+ // Generate and keep track of a "client id" which is sent to the browser
+ // to ask permission to talk to MIDI hardware.
+ // This id is handed back when we receive the answer in OnAccessApproved().
+ if (clients_.find(client) == clients_.end()) {
+ int client_id = next_available_id_++;
+ clients_[client] = client_id;
+
+ io_message_loop_->PostTask(FROM_HERE,
+ base::Bind(&MIDIMessageFilter::RequestAccessOnIOThread, this,
+ client_id, access));
+ }
+}
+
+void MIDIMessageFilter::RequestAccessOnIOThread(int client_id, int access) {
+ Send(new MIDIHostMsg_RequestAccess(client_id, access));
+}
+
+void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
+ ClientsMap::iterator i = clients_.find(client);
+ if (i != clients_.end())
+ clients_.erase(i);
+}
+
+// Received from browser.
+
+void MIDIMessageFilter::OnAccessApproved(
+ int client_id,
+ int access,
+ bool success,
+ MIDIPortInfoList inputs,
+ MIDIPortInfoList outputs) {
+ // Handle on the main JS thread.
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ base::Bind(&MIDIMessageFilter::HandleAccessApproved, this,
+ client_id, access, success, inputs, outputs));
+}
+
+void MIDIMessageFilter::HandleAccessApproved(
+ int client_id,
+ int access,
+ bool success,
+ MIDIPortInfoList inputs,
+ MIDIPortInfoList outputs) {
+ WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
+ if (!client)
+ return;
+
+ if (success) {
+ // Add the client's input and output ports.
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ client->didAddInputPort(
+ UTF8ToUTF16(inputs[i].id),
+ UTF8ToUTF16(inputs[i].manufacturer),
+ UTF8ToUTF16(inputs[i].name),
+ UTF8ToUTF16(inputs[i].version));
+ }
+
+ for (size_t i = 0; i < outputs.size(); ++i) {
+ client->didAddOutputPort(
+ UTF8ToUTF16(outputs[i].id),
+ UTF8ToUTF16(outputs[i].manufacturer),
+ UTF8ToUTF16(outputs[i].name),
+ UTF8ToUTF16(outputs[i].version));
+ }
+ }
+
+ if (success)
+ client->didAllowAccess();
+ else
+ client->didBlockAccess();
+}
+
+WebKit::WebMIDIAccessorClient*
+MIDIMessageFilter::GetClientFromId(int client_id) {
+ // Iterating like this seems inefficient, but in practice there generally
+ // will be very few clients (usually one). Additionally, this lookup
+ // usually happens one time during page load. So the performance hit is
+ // negligible.
+ for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
+ if ((*i).second == client_id)
+ return (*i).first;
+ }
+ return NULL;
+}
+
+void MIDIMessageFilter::OnDataReceived(int port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");
+
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
+ port, data, timestamp));
+}
+
+void MIDIMessageFilter::HandleDataReceived(int port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");
+
+#if defined(OS_ANDROID)
+ // TODO(crogers): figure out why data() method does not compile on Android.
+ NOTIMPLEMENTED();
+#else
+ for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
+ (*i).first->didReceiveMIDIData(port, data.data(), data.size(), timestamp);
+#endif
+}
+
+void MIDIMessageFilter::SendMIDIData(int port,
+ const uint8* data,
+ size_t length,
+ double timestamp) {
+ // TODO(crogers): we need more work to check the amount of data sent,
+ // throttle if necessary, and filter out the SYSEX messages if not
+ // approved. For now, we will not implement the sending of MIDI data.
+ NOTIMPLEMENTED();
+ // std::vector<uint8> v(data, data + length);
+ // io_message_loop_->PostTask(FROM_HERE,
+ // base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
+ // port, v, timestamp));
+}
+
+void MIDIMessageFilter::SendMIDIDataOnIOThread(int port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ // Send to the browser.
+ Send(new MIDIHostMsg_SendData(port, data, timestamp));
+}
+
+} // namespace content
diff --git a/content/renderer/media/midi_message_filter.h b/content/renderer/media/midi_message_filter.h
new file mode 100644
index 0000000..236ae47
--- /dev/null
+++ b/content/renderer/media/midi_message_filter.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
+#define CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "media/midi/midi_port_info.h"
+#include "third_party/WebKit/public/platform/WebMIDIAccessor.h"
+#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+// MessageFilter that handles MIDI messages.
+class CONTENT_EXPORT MIDIMessageFilter
+ : public IPC::ChannelProxy::MessageFilter {
+ public:
+ explicit MIDIMessageFilter(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
+
+ // Each client registers for MIDI access here.
+ // If permission is granted, then the client's
+ // addInputPort() and addOutputPort() methods will be called,
+ // giving the client access to receive and send data.
+ void RequestAccess(WebKit::WebMIDIAccessorClient* client, int access);
+ void RemoveClient(WebKit::WebMIDIAccessorClient* client);
+
+ // A client will only be able to call this method if it has a suitable
+ // output port (from addOutputPort()).
+ void SendMIDIData(int port,
+ const uint8* data,
+ size_t length,
+ double timestamp);
+
+ // IO message loop associated with this message filter.
+ scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
+ return io_message_loop_;
+ }
+
+ protected:
+ virtual ~MIDIMessageFilter();
+
+ private:
+ // Sends an IPC message using |channel_|.
+ void Send(IPC::Message* message);
+
+ // IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
+ virtual void OnFilterRemoved() OVERRIDE;
+ virtual void OnChannelClosing() OVERRIDE;
+
+ // Called when the browser process has approved (or denied) access to
+ // MIDI hardware.
+ void OnAccessApproved(int client_id,
+ int access,
+ bool success,
+ media::MIDIPortInfoList inputs,
+ media::MIDIPortInfoList outputs);
+
+ // Called when the browser process has sent MIDI data containing one or
+ // more messages.
+ void OnDataReceived(int port,
+ const std::vector<uint8>& data,
+ double timestamp);
+
+ void HandleAccessApproved(int client_id,
+ int access,
+ bool success,
+ media::MIDIPortInfoList inputs,
+ media::MIDIPortInfoList outputs);
+
+ void HandleDataReceived(int port,
+ const std::vector<uint8>& data,
+ double timestamp);
+
+ void RequestAccessOnIOThread(int client_id, int access);
+
+ void SendMIDIDataOnIOThread(int port,
+ const std::vector<uint8>& data,
+ double timestamp);
+
+ WebKit::WebMIDIAccessorClient* GetClientFromId(int client_id);
+
+ // IPC channel for Send(); must only be accessed on |io_message_loop_|.
+ IPC::Channel* channel_;
+
+ // Message loop on which IPC calls are driven.
+ const scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+
+ // Keeps track of all MIDI clients.
+ // We map client to "client id" used to track permission.
+ // When access has been approved, we add the input and output ports to
+ // the client, allowing it to actually receive and send MIDI data.
+ typedef std::map<WebKit::WebMIDIAccessorClient*, int> ClientsMap;
+ ClientsMap clients_;
+
+ // Dishes out client ids.
+ int next_available_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(MIDIMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
diff --git a/content/renderer/media/renderer_webmidiaccessor_impl.cc b/content/renderer/media/renderer_webmidiaccessor_impl.cc
new file mode 100644
index 0000000..0a8b68f
--- /dev/null
+++ b/content/renderer/media/renderer_webmidiaccessor_impl.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
+
+#include "base/logging.h"
+#include "content/renderer/media/midi_message_filter.h"
+#include "content/renderer/render_thread_impl.h"
+
+namespace content {
+
+RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl(
+ WebKit::WebMIDIAccessorClient* client)
+ : client_(client) {
+ DCHECK(client_);
+}
+
+RendererWebMIDIAccessorImpl::~RendererWebMIDIAccessorImpl() {
+ midi_message_filter()->RemoveClient(client_);
+}
+
+void RendererWebMIDIAccessorImpl::requestAccess(bool access) {
+ midi_message_filter()->RequestAccess(client_, access ? 1 : 0);
+}
+
+void RendererWebMIDIAccessorImpl::sendMIDIData(
+ unsigned port_index,
+ const unsigned char* data,
+ size_t length,
+ double timestamp) {
+ midi_message_filter()->SendMIDIData(
+ port_index,
+ data,
+ length,
+ timestamp);
+}
+
+MIDIMessageFilter* RendererWebMIDIAccessorImpl::midi_message_filter() {
+ return RenderThreadImpl::current()->midi_message_filter();
+}
+
+} // namespace content
diff --git a/content/renderer/media/renderer_webmidiaccessor_impl.h b/content/renderer/media/renderer_webmidiaccessor_impl.h
new file mode 100644
index 0000000..a6a07c9
--- /dev/null
+++ b/content/renderer/media/renderer_webmidiaccessor_impl.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "third_party/WebKit/public/platform/WebMIDIAccessor.h"
+#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
+
+namespace content {
+
+class MIDIMessageFilter;
+
+class RendererWebMIDIAccessorImpl
+ : public WebKit::WebMIDIAccessor {
+ public:
+ explicit RendererWebMIDIAccessorImpl(
+ WebKit::WebMIDIAccessorClient* client);
+ virtual ~RendererWebMIDIAccessorImpl();
+
+ // WebKit::WebMIDIAccessor implementation.
+ virtual void requestAccess(bool access) OVERRIDE;
+ virtual void sendMIDIData(unsigned port_index,
+ const unsigned char* data,
+ size_t length,
+ double timestamp) OVERRIDE;
+
+ private:
+ WebKit::WebMIDIAccessorClient* client_;
+
+ MIDIMessageFilter* midi_message_filter();
+
+ DISALLOW_COPY_AND_ASSIGN(RendererWebMIDIAccessorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 795a92a..72e7fb5 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -65,6 +65,7 @@
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/media_stream_center.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/midi_message_filter.h"
#include "content/renderer/media/peer_connection_tracker.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
@@ -368,6 +369,9 @@ void RenderThreadImpl::Init() {
audio_message_filter_ = new AudioMessageFilter(GetIOMessageLoopProxy());
AddFilter(audio_message_filter_.get());
+ midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy());
+ AddFilter(midi_message_filter_.get());
+
AddFilter(new IndexedDBMessageFilter);
GetContentClient()->renderer()->RenderThreadStarted();
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 63cc80c..9ef7002 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -81,6 +81,7 @@ class InputEventFilter;
class InputHandlerManager;
class MediaStreamCenter;
class MediaStreamDependencyFactory;
+class MIDIMessageFilter;
class P2PSocketDispatcher;
class PeerConnectionTracker;
class RendererWebKitPlatformSupportImpl;
@@ -227,6 +228,9 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
return audio_message_filter_.get();
}
+ MIDIMessageFilter* midi_message_filter() {
+ return midi_message_filter_.get();
+ }
// Creates the embedder implementation of WebMediaStreamCenter.
// The resulting object is owned by WebKit and deleted by WebKit at tear-down.
@@ -379,6 +383,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_refptr<DBMessageFilter> db_message_filter_;
scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
scoped_refptr<AudioMessageFilter> audio_message_filter_;
+ scoped_refptr<MIDIMessageFilter> midi_message_filter_;
scoped_refptr<DevToolsAgentFilter> devtools_agent_message_filter_;
scoped_ptr<MediaStreamDependencyFactory> media_stream_factory_;
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 5e74dc4..0ec76a1 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -31,6 +31,7 @@
#include "content/renderer/hyphenator/hyphenator.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/renderer_webaudiodevice_impl.h"
+#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_clipboard_client.h"
@@ -91,6 +92,7 @@ using WebKit::WebFileSystem;
using WebKit::WebFrame;
using WebKit::WebGamepads;
using WebKit::WebIDBFactory;
+using WebKit::WebMIDIAccessor;
using WebKit::Platform;
using WebKit::WebMediaStreamCenter;
using WebKit::WebMediaStreamCenterClient;
@@ -771,6 +773,14 @@ RendererWebKitPlatformSupportImpl::createContentDecryptionModule(
//------------------------------------------------------------------------------
+WebKit::WebMIDIAccessor*
+RendererWebKitPlatformSupportImpl::createMIDIAccessor(
+ WebKit::WebMIDIAccessorClient* client) {
+ return new RendererWebMIDIAccessorImpl(client);
+}
+
+//------------------------------------------------------------------------------
+
WebKit::WebString
RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
unsigned key_size_index,
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.h b/content/renderer/renderer_webkitplatformsupport_impl.h
index 104cd24..83990c4 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.h
+++ b/content/renderer/renderer_webkitplatformsupport_impl.h
@@ -107,6 +107,8 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
virtual WebKit::WebContentDecryptionModule* createContentDecryptionModule(
const WebKit::WebString& key_system);
+ virtual WebKit::WebMIDIAccessor*
+ createMIDIAccessor(WebKit::WebMIDIAccessorClient* client);
virtual WebKit::WebBlobRegistry* blobRegistry();
virtual void sampleGamepads(WebKit::WebGamepads&);