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

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

Issue 17334006: Revert 207983 "Implement Web MIDI API back-end" (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: 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 // Generate and keep track of a "client id" which is sent to the browser
70 // to ask permission to talk to MIDI hardware.
71 // This id is handed back when we receive the answer in OnAccessApproved().
72 if (clients_.find(client) == clients_.end()) {
73 int client_id = next_available_id_++;
74 clients_[client] = client_id;
75
76 io_message_loop_->PostTask(FROM_HERE,
77 base::Bind(&MIDIMessageFilter::RequestAccessOnIOThread, this,
78 client_id, access));
79 }
80 }
81
82 void MIDIMessageFilter::RequestAccessOnIOThread(int client_id, int access) {
83 Send(new MIDIHostMsg_RequestAccess(client_id, access));
84 }
85
86 void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
87 ClientsMap::iterator i = clients_.find(client);
88 if (i != clients_.end())
89 clients_.erase(i);
90 }
91
92 // Received from browser.
93
94 void MIDIMessageFilter::OnAccessApproved(
95 int client_id,
96 int access,
97 bool success,
98 MIDIPortInfoList inputs,
99 MIDIPortInfoList outputs) {
100 // Handle on the main JS thread.
101 ChildThread::current()->message_loop()->PostTask(FROM_HERE,
102 base::Bind(&MIDIMessageFilter::HandleAccessApproved, this,
103 client_id, access, success, inputs, outputs));
104 }
105
106 void MIDIMessageFilter::HandleAccessApproved(
107 int client_id,
108 int access,
109 bool success,
110 MIDIPortInfoList inputs,
111 MIDIPortInfoList outputs) {
112 WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
113 if (!client)
114 return;
115
116 if (success) {
117 // Add the client's input and output ports.
118 for (size_t i = 0; i < inputs.size(); ++i) {
119 client->didAddInputPort(
120 UTF8ToUTF16(inputs[i].id),
121 UTF8ToUTF16(inputs[i].manufacturer),
122 UTF8ToUTF16(inputs[i].name),
123 UTF8ToUTF16(inputs[i].version));
124 }
125
126 for (size_t i = 0; i < outputs.size(); ++i) {
127 client->didAddOutputPort(
128 UTF8ToUTF16(outputs[i].id),
129 UTF8ToUTF16(outputs[i].manufacturer),
130 UTF8ToUTF16(outputs[i].name),
131 UTF8ToUTF16(outputs[i].version));
132 }
133 }
134
135 if (success)
136 client->didAllowAccess();
137 else
138 client->didBlockAccess();
139 }
140
141 WebKit::WebMIDIAccessorClient*
142 MIDIMessageFilter::GetClientFromId(int client_id) {
143 // Iterating like this seems inefficient, but in practice there generally
144 // will be very few clients (usually one). Additionally, this lookup
145 // usually happens one time during page load. So the performance hit is
146 // negligible.
147 for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
148 if ((*i).second == client_id)
149 return (*i).first;
150 }
151 return NULL;
152 }
153
154 void MIDIMessageFilter::OnDataReceived(int port,
155 const std::vector<uint8>& data,
156 double timestamp) {
157 TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");
158
159 ChildThread::current()->message_loop()->PostTask(FROM_HERE,
160 base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
161 port, data, timestamp));
162 }
163
164 void MIDIMessageFilter::HandleDataReceived(int port,
165 const std::vector<uint8>& data,
166 double timestamp) {
167 TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");
168
169 #if defined(OS_ANDROID)
170 // TODO(crogers): figure out why data() method does not compile on Android.
171 NOTIMPLEMENTED();
172 #else
173 for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
174 (*i).first->didReceiveMIDIData(port, data.data(), data.size(), timestamp);
175 #endif
176 }
177
178 void MIDIMessageFilter::SendMIDIData(int port,
179 const uint8* data,
180 size_t length,
181 double timestamp) {
182 // TODO(crogers): we need more work to check the amount of data sent,
183 // throttle if necessary, and filter out the SYSEX messages if not
184 // approved. For now, we will not implement the sending of MIDI data.
185 NOTIMPLEMENTED();
186 // std::vector<uint8> v(data, data + length);
187 // io_message_loop_->PostTask(FROM_HERE,
188 // base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
189 // port, v, timestamp));
190 }
191
192 void MIDIMessageFilter::SendMIDIDataOnIOThread(int port,
193 const std::vector<uint8>& data,
194 double timestamp) {
195 // Send to the browser.
196 Send(new MIDIHostMsg_SendData(port, data, timestamp));
197 }
198
199 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698