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

Side by Side Diff: content/renderer/media/midi_message_filter.cc

Issue 16025005: Web MIDI API back-end (work-in-progress) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: For now disable sending data - fix IPC thread in renderer Created 7 years, 6 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/midi_message_filter.h"
6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/common/media/midi_messages.h"
12 #include "content/renderer/render_thread_impl.h"
13 #include "ipc/ipc_logging.h"
14
15 using media::MIDIPortInfoList;
16 using base::AutoLock;
17
18 namespace content {
19
20 MIDIMessageFilter::MIDIMessageFilter(
21 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
22 : channel_(NULL),
23 io_message_loop_(io_message_loop),
24 next_available_id_(0) {
25 }
26
27 MIDIMessageFilter::~MIDIMessageFilter() {}
28
29 void MIDIMessageFilter::Send(IPC::Message* message) {
30 DCHECK(io_message_loop_->BelongsToCurrentThread());
31 if (!channel_) {
32 delete message;
33 } else {
34 channel_->Send(message);
35 }
36 }
37
38 bool MIDIMessageFilter::OnMessageReceived(const IPC::Message& message) {
39 DCHECK(io_message_loop_->BelongsToCurrentThread());
40 bool handled = true;
41 IPC_BEGIN_MESSAGE_MAP(MIDIMessageFilter, message)
42 IPC_MESSAGE_HANDLER(MIDIMsg_AccessApproved, OnAccessApproved)
43 IPC_MESSAGE_HANDLER(MIDIMsg_DataReceived, OnDataReceived)
44 IPC_MESSAGE_UNHANDLED(handled = false)
45 IPC_END_MESSAGE_MAP()
46 return handled;
47 }
48
49 void MIDIMessageFilter::OnFilterAdded(IPC::Channel* channel) {
50 DCHECK(io_message_loop_->BelongsToCurrentThread());
51 channel_ = channel;
52 }
53
54 void MIDIMessageFilter::OnFilterRemoved() {
55 DCHECK(io_message_loop_->BelongsToCurrentThread());
56
57 // Once removed, a filter will not be used again. At this time all
58 // delegates must be notified so they release their reference.
59 OnChannelClosing();
60 }
61
62 void MIDIMessageFilter::OnChannelClosing() {
63 DCHECK(io_message_loop_->BelongsToCurrentThread());
64 channel_ = NULL;
65 }
66
67 void MIDIMessageFilter::RequestAccess(
68 WebKit::WebMIDIAccessorClient* client, int access) {
69 // Get the main thread message loop.
70 if (!client_message_loop_)
71 client_message_loop_ = base::MessageLoopProxy::current();
piman 2013/06/21 23:16:13 Do you mind moving this to the constructor? As is
72 else
73 CHECK(client_message_loop_ == base::MessageLoopProxy::current());
74
75 // Generate and keep track of a "client id" which is sent to the browser
76 // to ask permission to talk to MIDI hardware.
77 // This id is handed back when we receive the answer in OnAccessApproved().
78 if (clients_.find(client) == clients_.end()) {
79 int client_id = next_available_id_++;
80 clients_[client] = client_id;
81
82 io_message_loop_->PostTask(FROM_HERE,
83 base::Bind(&MIDIMessageFilter::RequestAccessOnIOThread, this,
84 client_id, access));
85 }
86 }
87
88 void MIDIMessageFilter::RequestAccessOnIOThread(int client_id, int access) {
89 Send(new MIDIHostMsg_RequestAccess(client_id, access));
90 }
91
92 void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
93 ClientsMap::iterator i = clients_.find(client);
94 if (i != clients_.end())
95 clients_.erase(i);
96 }
97
98 // Received from browser.
99
100 void MIDIMessageFilter::OnAccessApproved(
101 int client_id,
102 int access,
103 bool success,
104 MIDIPortInfoList inputs,
105 MIDIPortInfoList outputs) {
106 if (client_message_loop_) {
107 // Handle on the main JS thread.
108 client_message_loop_->PostTask(FROM_HERE,
109 base::Bind(&MIDIMessageFilter::HandleAccessApproved, this,
110 client_id, access, success, inputs, outputs));
111 }
112 }
113
114 void MIDIMessageFilter::HandleAccessApproved(
115 int client_id,
116 int access,
117 bool success,
118 MIDIPortInfoList inputs,
119 MIDIPortInfoList outputs) {
120 WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
121 if (!client)
122 return;
123
124 if (success) {
125 // Add the client's input and output ports.
126 for (size_t i = 0; i < inputs.size(); ++i) {
127 client->didAddInputPort(
128 UTF8ToUTF16(inputs[i].id),
129 UTF8ToUTF16(inputs[i].manufacturer),
130 UTF8ToUTF16(inputs[i].name),
131 UTF8ToUTF16(inputs[i].version));
132 }
133
134 for (size_t i = 0; i < outputs.size(); ++i) {
135 client->didAddOutputPort(
136 UTF8ToUTF16(outputs[i].id),
137 UTF8ToUTF16(outputs[i].manufacturer),
138 UTF8ToUTF16(outputs[i].name),
139 UTF8ToUTF16(outputs[i].version));
140 }
141 }
142
143 if (success)
144 client->didAllowAccess();
145 else
146 client->didBlockAccess();
147 }
148
149 WebKit::WebMIDIAccessorClient*
150 MIDIMessageFilter::GetClientFromId(int client_id) {
151 // Iterating like this seems inefficient, but in practice there generally
152 // will be very few clients (usually one). Additionally, this lookup
153 // usually happens one time during page load. So the performance hit is
154 // negligible.
155 for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
156 if ((*i).second == client_id)
157 return (*i).first;
158 }
159 return NULL;
160 }
161
162 void MIDIMessageFilter::OnDataReceived(int port,
163 const std::vector<uint8>& data,
164 double timestamp) {
165 TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");
166
167 if (client_message_loop_) {
168 client_message_loop_->PostTask(FROM_HERE,
169 base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
170 port, data, timestamp));
171 }
172 }
173
174 void MIDIMessageFilter::HandleDataReceived(int port,
175 const std::vector<uint8>& data,
176 double timestamp) {
177 TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");
178
179 for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
180 (*i).first->didReceiveMIDIData(port, data.data(), data.size(), timestamp);
181 }
182
183 void MIDIMessageFilter::SendMIDIData(int port,
184 const uint8* data,
185 size_t length,
186 double timestamp) {
187 // TODO(crogers): we need more work to check the amount of data sent,
188 // throttle if necessary, and filter out the SYSEX messages if not
189 // approved. For now, we will not implement the sending of MIDI data.
190 NOTIMPLEMENTED();
191 // std::vector<uint8> v(data, data + length);
192 // io_message_loop_->PostTask(FROM_HERE,
193 // base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
194 // port, v, timestamp));
195 }
196
197 void MIDIMessageFilter::SendMIDIDataOnIOThread(int port,
198 const std::vector<uint8>& data,
199 double timestamp) {
200 // Send to the browser.
201 Send(new MIDIHostMsg_SendData(port, data, timestamp));
202 }
203
204 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/midi_message_filter.h ('k') | content/renderer/media/renderer_webmidiaccessor_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698