OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 #if defined(OS_WIN) | |
6 #include <windows.h> | |
7 #endif | |
8 | |
9 #include "base/memory/shared_memory.h" | |
10 #include "content/browser/media/audio_output_impl.h" | |
11 #include "content/browser/media/audio_output_stream_impl.h" | |
12 #include "content/public/browser/render_frame_host.h" | |
13 #include "mojo/edk/embedder/embedder.h" | |
14 #include "mojo/public/cpp/system/handle.h" | |
15 #include "mojo/public/cpp/system/platform_handle.h" | |
16 | |
17 namespace content { | |
18 | |
19 namespace { | |
20 base::SyncSocket::TransitDescriptor DuplicateSocket( | |
nasko
2016/05/25 20:50:41
Empty line between namespace and the code.
rchtara
2016/05/27 15:24:38
Done.
| |
21 base::SyncSocket::TransitDescriptor socket_descriptor) { | |
22 base::SyncSocket::TransitDescriptor socket_descriptor_dup; | |
23 | |
24 #if defined(OS_WIN) | |
25 socket_descriptor_dup = 0; | |
26 if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle | |
27 socket_descriptor, | |
28 GetCurrentProcess(), // hTargetProcessHandle | |
29 &socket_descriptor_dup, | |
30 0, // dwDesiredAccess ignored due to SAME_ACCESS | |
31 FALSE, // !bInheritHandle | |
32 DUPLICATE_SAME_ACCESS)) { | |
33 LOG(ERROR) << "Unable to duplicate socket handle."; | |
34 } | |
35 | |
36 #else | |
37 socket_descriptor_dup.fd = dup(socket_descriptor.fd); | |
38 #endif | |
39 return socket_descriptor_dup; | |
40 } | |
41 } | |
nasko
2016/05/25 20:50:41
Empty line between the two } and a // namespace en
rchtara
2016/05/27 15:24:38
Done.
| |
42 | |
43 AudioOutputImpl::AudioOutputImpl(RenderProcessHost* process, | |
44 int render_frame_id, | |
45 media::mojom::AudioOutputRequest request) | |
46 : process_(process), render_frame_id_(render_frame_id), binding_(this) { | |
47 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
48 binding_.Bind(std::move(request)); | |
49 binding_.set_connection_error_handler(base::Bind( | |
50 &AudioOutputImpl::Disconnect, process->GetID(), render_frame_id)); | |
51 } | |
52 | |
53 AudioOutputImpl::~AudioOutputImpl() { | |
54 Disconnect(render_frame_id_, render_frame_id_); | |
55 for (auto it = create_stream_callbacks_.begin(); | |
56 it != create_stream_callbacks_.end(); ++it) | |
nasko
2016/05/25 20:50:42
Multiline loops need to have {}.
rchtara
2016/05/27 15:24:38
Done.
| |
57 it->second.reset(); | |
58 create_stream_callbacks_.clear(); | |
59 } | |
60 | |
61 // static | |
62 void AudioOutputImpl::CreateService(RenderProcessHost* process, | |
nasko
2016/05/25 20:50:41
The comment in the header was saying this object i
rchtara
2016/05/27 15:24:38
Done.
| |
63 int render_frame_id, | |
64 media::mojom::AudioOutputRequest request) { | |
65 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
66 | |
67 BrowserThread::PostTask( | |
68 BrowserThread::IO, FROM_HERE, | |
69 base::Bind(&AudioOutputImpl::CreateServiceOnIOThread, process, | |
70 render_frame_id, base::Passed(&request))); | |
71 } | |
72 | |
73 // static | |
74 void AudioOutputImpl::CreateServiceOnIOThread( | |
75 RenderProcessHost* process, | |
76 int render_frame_id, | |
77 media::mojom::AudioOutputRequest request) { | |
78 if (request.is_pending()) { | |
nasko
2016/05/25 20:50:41
Is it safe to call this on other threads if the re
rchtara
2016/05/27 15:24:38
Done.
| |
79 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
80 } | |
81 | |
82 new AudioOutputImpl(process, render_frame_id, std::move(request)); | |
83 } | |
84 | |
85 void AudioOutputImpl::CreateStream(int stream_id, | |
86 const media::AudioParameters& params, | |
87 const CreateStreamCallback& callback) { | |
88 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
89 | |
90 create_stream_callbacks_.insert(std::make_pair(stream_id, callback)); | |
91 process_->audio_renderer_host()->CreateStream(stream_id, render_frame_id_, | |
92 params, this); | |
93 } | |
94 | |
95 void AudioOutputImpl::CreateStreamFactory( | |
96 int stream_id, | |
97 base::SharedMemory* shared_memory, | |
98 base::SyncSocket::TransitDescriptor socket_descriptor) { | |
99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
100 | |
101 auto callback = create_stream_callbacks_.find(stream_id); | |
102 if (callback == create_stream_callbacks_.end()) { | |
nasko
2016/05/25 20:50:41
Single line if statements don't need {}.
rchtara
2016/05/27 15:24:38
Done.
| |
103 return; | |
104 } | |
105 | |
106 media::mojom::AudioOutputStreamPtr stream_ptr = | |
107 media::mojom::AudioOutputStreamPtr(); | |
108 std::unique_ptr<AudioOutputStreamImpl> stream(new AudioOutputStreamImpl( | |
109 stream_id, render_frame_id_, this, mojo::GetProxy(&stream_ptr))); | |
110 | |
111 DCHECK(stream_impls_.insert(std::make_pair(stream_id, std::move(stream))) | |
nasko
2016/05/25 20:50:41
This statement will never execute in release build
rchtara
2016/05/27 15:24:38
Done.
| |
112 .second); | |
113 | |
114 base::SharedMemoryHandle shared_memory_handle = | |
115 base::SharedMemory::DuplicateHandle(shared_memory->handle()); | |
116 mojo::ScopedSharedBufferHandle shared_buffer_handle = | |
117 mojo::WrapSharedMemoryHandle(shared_memory_handle, | |
nasko
2016/05/25 20:50:41
Would WrapSharedMemoryHandle work successfully if
rchtara
2016/05/27 15:24:38
Done.
| |
118 shared_memory->requested_size(), false); | |
119 | |
120 // The socket handle is going to be closed when |mojo_application_host_| is | |
121 // reset. The renderer is going to need to close the socket handle | |
nasko
2016/05/25 20:50:41
nit: s/renderer/renderer process/
rchtara
2016/05/27 15:24:38
Done.
| |
122 // too when the output steam is closed. This is going to cause an issue | |
123 // because both of them are going to close the same socket handle. | |
124 // This is why a duplicate of the socket handler is going to be created, | |
125 // stored in |socket_descriptor_dup| and sent through Mojo to the renderer so | |
126 // it can be used by AudioOutputIPCDelegate. | |
127 | |
128 base::SyncSocket::TransitDescriptor socket_descriptor_dup = | |
129 DuplicateSocket(socket_descriptor); | |
130 #if defined(OS_WIN) | |
131 mojo::ScopedHandle socket_handle = | |
132 mojo::WrapPlatformFil(socket_descriptor_dup); | |
133 #else | |
134 mojo::ScopedHandle socket_handle = | |
135 mojo::WrapPlatformFile(socket_descriptor_dup.fd); | |
136 #endif | |
137 callback->second.Run(stream_id, std::move(stream_ptr), | |
nasko
2016/05/25 20:50:41
If there is always a pointer to the stream, why is
rchtara
2016/05/27 15:24:38
Done.
nasko
2016/05/27 22:52:00
What does "Done" mean here? I don't see a change t
| |
138 std::move(shared_buffer_handle), | |
139 std::move(socket_handle)); | |
140 | |
141 callback->second.reset(); | |
142 create_stream_callbacks_.erase(stream_id); | |
143 } | |
144 | |
145 bool AudioOutputImpl::CloseStream(int stream_id) { | |
146 process_->audio_renderer_host()->CloseStream(stream_id); | |
147 | |
148 auto stream = stream_impls_.find(stream_id); | |
149 if (stream == stream_impls_.end()) { | |
150 return false; | |
151 } | |
152 stream_impls_.erase(stream_id); | |
153 | |
154 auto callback = create_stream_callbacks_.find(stream_id); | |
155 | |
156 if (callback != create_stream_callbacks_.end()) { | |
157 callback->second.reset(); | |
158 create_stream_callbacks_.erase(stream_id); | |
159 } | |
160 return true; | |
161 } | |
162 | |
163 // static | |
164 void AudioOutputImpl::Disconnect(int process_id, int render_frame_id) {} | |
165 | |
166 void AudioOutputImpl::ReportErrorAndCloseStream(int stream_id) { | |
167 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
168 | |
169 // Make sure this isn't a stray callback executing after the stream has been | |
170 // closed, so error notifications aren't sent after clients believe the stream | |
171 // is closed. | |
172 auto callback = create_stream_callbacks_.find(stream_id); | |
173 | |
174 mojo::ScopedSharedBufferHandle shared_buffer_handle = | |
175 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); | |
176 | |
177 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle()); | |
178 | |
179 callback->second.Run(stream_id, media::mojom::AudioOutputStreamPtr(), | |
180 std::move(shared_buffer_handle), | |
181 std::move(socket_handle)); | |
182 | |
183 process_->audio_renderer_host()->get_audio_log()->OnError(stream_id); | |
184 CloseStream(stream_id); | |
185 } | |
186 | |
187 } // namespace content | |
OLD | NEW |