Commit 3d670050 authored by burnik's avatar burnik Committed by Commit bot

Preparing |SyncSocket|'s handle for the peer process is different for POSIX and Windows

which leads to code duplication, platform #ifdef checks on multiple levels and
general confusion on how to work with the SyncSocket.

Typical use case for |SyncSocket|:
1. Browser creates and connects the socket pair - one for browser and one for renderer.
2. Browser prepares the foreign socket (Windows duplicates, POSIX creates file descriptor).
3. Browser relays the foreign socket handle to the renderer via IPC.
4. Renderer receives the IPC and creates the socket using the handle provided.
5. Sockets are ready for send/receive on both ends.

Steps 1-4 get simplified since there is no need to check the platform in order to prepare the socket for transit.

What this CL brings:
1. Adds |SyncSocket::TransitDescriptor| type which wraps the socket handle and is cross-platform.
2. Adds |SyncSocket::PrepareTransitDescriptor| method which is implemented depending on the platform.
3. Adds |SyncSocket::UnwrapHandle| method which unwraps |SyncSocket::Handle| from |SyncSocket::TransitDescriptor|.
4. Removes #ifdefs for platform-checks in code using |SyncSocket| and simplifies preparing the SyncSocket.

Note:
- There is still some less evident duplication in the ppapi and pepper-broker code which should be addressed.
- SyncSocket unit test should also be reviewed.
- There is a similar pattern when using SharedMemory.

BUG=409656

Review URL: https://codereview.chromium.org/525313002

Cr-Commit-Position: refs/heads/master@{#293680}
parent 41894532
...@@ -17,17 +17,24 @@ ...@@ -17,17 +17,24 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/process/process_handle.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/time/time.h" #include "base/time/time.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif
namespace base { namespace base {
class BASE_EXPORT SyncSocket { class BASE_EXPORT SyncSocket {
public: public:
#if defined(OS_WIN) #if defined(OS_WIN)
typedef HANDLE Handle; typedef HANDLE Handle;
typedef Handle TransitDescriptor;
#else #else
typedef int Handle; typedef int Handle;
typedef FileDescriptor TransitDescriptor;
#endif #endif
static const Handle kInvalidHandle; static const Handle kInvalidHandle;
...@@ -42,6 +49,15 @@ class BASE_EXPORT SyncSocket { ...@@ -42,6 +49,15 @@ class BASE_EXPORT SyncSocket {
// return, the sockets will both be valid and connected. // return, the sockets will both be valid and connected.
static bool CreatePair(SyncSocket* socket_a, SyncSocket* socket_b); static bool CreatePair(SyncSocket* socket_a, SyncSocket* socket_b);
// Returns |Handle| wrapped in a |TransitDescriptor|.
static Handle UnwrapHandle(const TransitDescriptor& descriptor);
// Prepares a |TransitDescriptor| which wraps |Handle| used for transit.
// This is used to prepare the underlying shared resource before passing back
// the handle to be used by the peer process.
bool PrepareTransitDescriptor(ProcessHandle peer_process_handle,
TransitDescriptor* descriptor);
// Closes the SyncSocket. Returns true on success, false on failure. // Closes the SyncSocket. Returns true on success, false on failure.
virtual bool Close(); virtual bool Close();
......
...@@ -27,6 +27,24 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) { ...@@ -27,6 +27,24 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) {
return false; return false;
} }
// static
SyncSocket::Handle SyncSocket::UnwrapHandle(
const SyncSocket::TransitDescriptor& descriptor) {
// TODO(xians): Still unclear how NaCl uses SyncSocket.
// See http://crbug.com/409656
NOTIMPLEMENTED();
return SyncSocket::kInvalidHandle;
}
bool SyncSocket::PrepareTransitDescriptor(
ProcessHandle peer_process_handle,
SyncSocket::TransitDescriptor* descriptor) {
// TODO(xians): Still unclear how NaCl uses SyncSocket.
// See http://crbug.com/409656
NOTIMPLEMENTED();
return false;
}
bool SyncSocket::Close() { bool SyncSocket::Close() {
if (handle_ != kInvalidHandle) { if (handle_ != kInvalidHandle) {
if (close(handle_) < 0) if (close(handle_) < 0)
......
...@@ -96,6 +96,19 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) { ...@@ -96,6 +96,19 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) {
return true; return true;
} }
// static
SyncSocket::Handle SyncSocket::UnwrapHandle(
const TransitDescriptor& descriptor) {
return descriptor.fd;
}
bool SyncSocket::PrepareTransitDescriptor(ProcessHandle peer_process_handle,
TransitDescriptor* descriptor) {
descriptor->fd = handle();
descriptor->auto_close = false;
return descriptor->fd != kInvalidHandle;
}
bool SyncSocket::Close() { bool SyncSocket::Close() {
const bool retval = CloseHandle(handle_); const bool retval = CloseHandle(handle_);
handle_ = kInvalidHandle; handle_ = kInvalidHandle;
......
...@@ -207,6 +207,23 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) { ...@@ -207,6 +207,23 @@ bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) {
return CreatePairImpl(&socket_a->handle_, &socket_b->handle_, false); return CreatePairImpl(&socket_a->handle_, &socket_b->handle_, false);
} }
// static
SyncSocket::Handle SyncSocket::UnwrapHandle(
const TransitDescriptor& descriptor) {
return descriptor;
}
bool SyncSocket::PrepareTransitDescriptor(ProcessHandle peer_process_handle,
TransitDescriptor* descriptor) {
DCHECK(descriptor);
if (!::DuplicateHandle(GetCurrentProcess(), handle(), peer_process_handle,
descriptor, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
DPLOG(ERROR) << "Cannot duplicate socket handle for peer process.";
return false;
}
return true;
}
bool SyncSocket::Close() { bool SyncSocket::Close() {
if (handle_ == kInvalidHandle) if (handle_ == kInvalidHandle)
return true; return true;
......
...@@ -31,7 +31,7 @@ void LogMessage(int stream_id, const std::string& msg, bool add_prefix) { ...@@ -31,7 +31,7 @@ void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
DVLOG(1) << oss.str(); DVLOG(1) << oss.str();
} }
} } // namespace
namespace content { namespace content {
...@@ -178,16 +178,11 @@ void AudioInputRendererHost::DoCompleteCreation( ...@@ -178,16 +178,11 @@ void AudioInputRendererHost::DoCompleteCreation(
AudioInputSyncWriter* writer = AudioInputSyncWriter* writer =
static_cast<AudioInputSyncWriter*>(entry->writer.get()); static_cast<AudioInputSyncWriter*>(entry->writer.get());
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_transit_descriptor;
base::SyncSocket::Handle foreign_socket_handle;
#else
base::FileDescriptor foreign_socket_handle;
#endif
// If we failed to prepare the sync socket for the renderer then we fail // If we failed to prepare the sync socket for the renderer then we fail
// the construction of audio input stream. // the construction of audio input stream.
if (!writer->PrepareForeignSocketHandle(PeerHandle(), if (!writer->PrepareForeignSocket(PeerHandle(), &socket_transit_descriptor)) {
&foreign_socket_handle)) {
DeleteEntryOnError(entry, SYNC_SOCKET_ERROR); DeleteEntryOnError(entry, SYNC_SOCKET_ERROR);
return; return;
} }
...@@ -196,8 +191,8 @@ void AudioInputRendererHost::DoCompleteCreation( ...@@ -196,8 +191,8 @@ void AudioInputRendererHost::DoCompleteCreation(
"DoCompleteCreation: IPC channel and stream are now open", "DoCompleteCreation: IPC channel and stream are now open",
true); true);
Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id, Send(new AudioInputMsg_NotifyStreamCreated(
foreign_memory_handle, foreign_socket_handle, entry->stream_id, foreign_memory_handle, socket_transit_descriptor,
entry->shared_memory.requested_size(), entry->shared_memory.requested_size(),
entry->shared_memory_segment_count)); entry->shared_memory_segment_count));
} }
......
...@@ -107,27 +107,11 @@ bool AudioInputSyncWriter::Init() { ...@@ -107,27 +107,11 @@ bool AudioInputSyncWriter::Init() {
foreign_socket_.get()); foreign_socket_.get());
} }
#if defined(OS_WIN) bool AudioInputSyncWriter::PrepareForeignSocket(
bool AudioInputSyncWriter::PrepareForeignSocketHandle(
base::ProcessHandle process_handle,
base::SyncSocket::Handle* foreign_handle) {
::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(),
process_handle, foreign_handle,
0, FALSE, DUPLICATE_SAME_ACCESS);
return (*foreign_handle != 0);
}
#else
bool AudioInputSyncWriter::PrepareForeignSocketHandle(
base::ProcessHandle process_handle, base::ProcessHandle process_handle,
base::FileDescriptor* foreign_handle) { base::SyncSocket::TransitDescriptor* descriptor) {
foreign_handle->fd = foreign_socket_->handle(); return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor);
foreign_handle->auto_close = false;
return (foreign_handle->fd != -1);
} }
#endif
} // namespace content } // namespace content
...@@ -42,12 +42,8 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter { ...@@ -42,12 +42,8 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
virtual void Close() OVERRIDE; virtual void Close() OVERRIDE;
bool Init(); bool Init();
bool PrepareForeignSocketHandle(base::ProcessHandle process_handle, bool PrepareForeignSocket(base::ProcessHandle process_handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor* descriptor);
base::SyncSocket::Handle* foreign_handle);
#else
base::FileDescriptor* foreign_handle);
#endif
private: private:
base::SharedMemory* shared_memory_; base::SharedMemory* shared_memory_;
......
...@@ -238,24 +238,17 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) { ...@@ -238,24 +238,17 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor;
base::SyncSocket::Handle foreign_socket_handle;
#else
base::FileDescriptor foreign_socket_handle;
#endif
// If we failed to prepare the sync socket for the renderer then we fail // If we failed to prepare the sync socket for the renderer then we fail
// the construction of audio stream. // the construction of audio stream.
if (!reader->PrepareForeignSocketHandle(PeerHandle(), if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) {
&foreign_socket_handle)) {
ReportErrorAndClose(entry->stream_id()); ReportErrorAndClose(entry->stream_id());
return; return;
} }
Send(new AudioMsg_NotifyStreamCreated( Send(new AudioMsg_NotifyStreamCreated(
entry->stream_id(), entry->stream_id(), foreign_memory_handle, socket_descriptor,
foreign_memory_handle,
foreign_socket_handle,
entry->shared_memory()->requested_size())); entry->shared_memory()->requested_size()));
} }
......
...@@ -101,14 +101,9 @@ class MockAudioRendererHost : public AudioRendererHost { ...@@ -101,14 +101,9 @@ class MockAudioRendererHost : public AudioRendererHost {
return true; return true;
} }
void OnNotifyStreamCreated(int stream_id, void OnNotifyStreamCreated(
base::SharedMemoryHandle handle, int stream_id, base::SharedMemoryHandle handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) {
base::SyncSocket::Handle socket_handle,
#else
base::FileDescriptor socket_descriptor,
#endif
uint32 length) {
// Maps the shared memory. // Maps the shared memory.
shared_memory_.reset(new base::SharedMemory(handle, false)); shared_memory_.reset(new base::SharedMemory(handle, false));
CHECK(shared_memory_->Map(length)); CHECK(shared_memory_->Map(length));
...@@ -116,12 +111,8 @@ class MockAudioRendererHost : public AudioRendererHost { ...@@ -116,12 +111,8 @@ class MockAudioRendererHost : public AudioRendererHost {
shared_memory_length_ = length; shared_memory_length_ = length;
// Create the SyncSocket using the handle. // Create the SyncSocket using the handle.
base::SyncSocket::Handle sync_socket_handle; base::SyncSocket::Handle sync_socket_handle =
#if defined(OS_WIN) base::SyncSocket::UnwrapHandle(socket_descriptor);
sync_socket_handle = socket_handle;
#else
sync_socket_handle = socket_descriptor.fd;
#endif
sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
// And then delegate the call to the mock method. // And then delegate the call to the mock method.
......
...@@ -115,24 +115,11 @@ bool AudioSyncReader::Init() { ...@@ -115,24 +115,11 @@ bool AudioSyncReader::Init() {
foreign_socket_.get()); foreign_socket_.get());
} }
#if defined(OS_WIN) bool AudioSyncReader::PrepareForeignSocket(
bool AudioSyncReader::PrepareForeignSocketHandle(
base::ProcessHandle process_handle, base::ProcessHandle process_handle,
base::SyncSocket::Handle* foreign_handle) { base::SyncSocket::TransitDescriptor* descriptor) {
::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(), return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor);
process_handle, foreign_handle,
0, FALSE, DUPLICATE_SAME_ACCESS);
return (*foreign_handle != 0);
} }
#else
bool AudioSyncReader::PrepareForeignSocketHandle(
base::ProcessHandle process_handle,
base::FileDescriptor* foreign_handle) {
foreign_handle->fd = foreign_socket_->handle();
foreign_handle->auto_close = false;
return (foreign_handle->fd != -1);
}
#endif
bool AudioSyncReader::WaitUntilDataIsReady() { bool AudioSyncReader::WaitUntilDataIsReady() {
base::TimeDelta timeout = maximum_wait_time_; base::TimeDelta timeout = maximum_wait_time_;
......
...@@ -39,12 +39,8 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader { ...@@ -39,12 +39,8 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
virtual void Close() OVERRIDE; virtual void Close() OVERRIDE;
bool Init(); bool Init();
bool PrepareForeignSocketHandle(base::ProcessHandle process_handle, bool PrepareForeignSocket(base::ProcessHandle process_handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor* descriptor);
base::SyncSocket::Handle* foreign_handle);
#else
base::FileDescriptor* foreign_handle);
#endif
private: private:
// Blocks until data is ready for reading or a timeout expires. Returns false // Blocks until data is ready for reading or a timeout expires. Returns false
......
...@@ -39,38 +39,23 @@ IPC_STRUCT_END() ...@@ -39,38 +39,23 @@ IPC_STRUCT_END()
// buffer it shares with the browser process. It is also given a SyncSocket that // buffer it shares with the browser process. It is also given a SyncSocket that
// it uses to communicate with the browser process about the state of the // it uses to communicate with the browser process about the state of the
// buffered audio data. // buffered audio data.
#if defined(OS_WIN) IPC_MESSAGE_CONTROL4(
IPC_MESSAGE_CONTROL4(AudioMsg_NotifyStreamCreated, AudioMsg_NotifyStreamCreated,
int /* stream id */, int /* stream id */,
base::SharedMemoryHandle /* handle */, base::SharedMemoryHandle /* handle */,
base::SyncSocket::Handle /* socket handle */, base::SyncSocket::TransitDescriptor /* socket descriptor */,
uint32 /* length */) uint32 /* length */)
#else
IPC_MESSAGE_CONTROL4(AudioMsg_NotifyStreamCreated,
int /* stream id */,
base::SharedMemoryHandle /* handle */,
base::FileDescriptor /* socket handle */,
uint32 /* length */)
#endif
// Tell the renderer process that an audio input stream has been created. // Tell the renderer process that an audio input stream has been created.
// The renderer process would be given a SyncSocket that it should read // The renderer process would be given a SyncSocket that it should read
// from from then on. It is also given number of segments in shared memory. // from from then on. It is also given number of segments in shared memory.
#if defined(OS_WIN) IPC_MESSAGE_CONTROL5(
IPC_MESSAGE_CONTROL5(AudioInputMsg_NotifyStreamCreated, AudioInputMsg_NotifyStreamCreated,
int /* stream id */,
base::SharedMemoryHandle /* handle */,
base::SyncSocket::Handle /* socket handle */,
uint32 /* length */,
uint32 /* segment count */)
#else
IPC_MESSAGE_CONTROL5(AudioInputMsg_NotifyStreamCreated,
int /* stream id */, int /* stream id */,
base::SharedMemoryHandle /* handle */, base::SharedMemoryHandle /* handle */,
base::FileDescriptor /* socket handle */, base::SyncSocket::TransitDescriptor /* socket descriptor */,
uint32 /* length */, uint32 /* length */,
uint32 /* segment count */) uint32 /* segment count */)
#endif
// Notification message sent from AudioRendererHost to renderer after an output // Notification message sent from AudioRendererHost to renderer after an output
// device change has occurred. // device change has occurred.
......
...@@ -23,7 +23,7 @@ void LogMessage(int stream_id, const std::string& msg) { ...@@ -23,7 +23,7 @@ void LogMessage(int stream_id, const std::string& msg) {
DVLOG(1) << oss.str(); DVLOG(1) << oss.str();
} }
} } // namespace
namespace content { namespace content {
...@@ -126,19 +126,14 @@ void AudioInputMessageFilter::OnChannelClosing() { ...@@ -126,19 +126,14 @@ void AudioInputMessageFilter::OnChannelClosing() {
void AudioInputMessageFilter::OnStreamCreated( void AudioInputMessageFilter::OnStreamCreated(
int stream_id, int stream_id,
base::SharedMemoryHandle handle, base::SharedMemoryHandle handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor,
base::SyncSocket::Handle socket_handle,
#else
base::FileDescriptor socket_descriptor,
#endif
uint32 length, uint32 length,
uint32 total_segments) { uint32 total_segments) {
DCHECK(io_message_loop_->BelongsToCurrentThread()); DCHECK(io_message_loop_->BelongsToCurrentThread());
LogMessage(stream_id, "OnStreamCreated"); LogMessage(stream_id, "OnStreamCreated");
#if !defined(OS_WIN) base::SyncSocket::Handle socket_handle =
base::SyncSocket::Handle socket_handle = socket_descriptor.fd; base::SyncSocket::UnwrapHandle(socket_descriptor);
#endif
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id); media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) { if (!delegate) {
DLOG(WARNING) << "Got audio stream event for a non-existent or removed" DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
......
...@@ -168,11 +168,7 @@ void AudioMessageFilter::OnChannelClosing() { ...@@ -168,11 +168,7 @@ void AudioMessageFilter::OnChannelClosing() {
void AudioMessageFilter::OnStreamCreated( void AudioMessageFilter::OnStreamCreated(
int stream_id, int stream_id,
base::SharedMemoryHandle handle, base::SharedMemoryHandle handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor,
base::SyncSocket::Handle socket_handle,
#else
base::FileDescriptor socket_descriptor,
#endif
uint32 length) { uint32 length) {
DCHECK(io_message_loop_->BelongsToCurrentThread()); DCHECK(io_message_loop_->BelongsToCurrentThread());
...@@ -180,9 +176,8 @@ void AudioMessageFilter::OnStreamCreated( ...@@ -180,9 +176,8 @@ void AudioMessageFilter::OnStreamCreated(
"AMF::OnStreamCreated. stream_id=%d", "AMF::OnStreamCreated. stream_id=%d",
stream_id)); stream_id));
#if !defined(OS_WIN) base::SyncSocket::Handle socket_handle =
base::SyncSocket::Handle socket_handle = socket_descriptor.fd; base::SyncSocket::UnwrapHandle(socket_descriptor);
#endif
media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id); media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) { if (!delegate) {
......
...@@ -76,11 +76,7 @@ class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter { ...@@ -76,11 +76,7 @@ class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter {
// Received when browser process has created an audio output stream. // Received when browser process has created an audio output stream.
void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle, void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle,
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor,
base::SyncSocket::Handle socket_handle,
#else
base::FileDescriptor socket_descriptor,
#endif
uint32 length); uint32 length);
// Received when internal state of browser process' audio output device has // Received when internal state of browser process' audio output device has
......
...@@ -86,17 +86,11 @@ TEST(AudioMessageFilterTest, Basic) { ...@@ -86,17 +86,11 @@ TEST(AudioMessageFilterTest, Basic) {
EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId)); EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId));
// AudioMsg_NotifyStreamCreated // AudioMsg_NotifyStreamCreated
#if defined(OS_WIN) base::SyncSocket::TransitDescriptor socket_descriptor;
base::SyncSocket::Handle socket_handle;
#else
base::FileDescriptor socket_handle;
#endif
const uint32 kLength = 1024; const uint32 kLength = 1024;
EXPECT_FALSE(delegate.created_received()); EXPECT_FALSE(delegate.created_received());
filter->OnMessageReceived( filter->OnMessageReceived(AudioMsg_NotifyStreamCreated(
AudioMsg_NotifyStreamCreated( kStreamId, base::SharedMemory::NULLHandle(), socket_descriptor, kLength));
kStreamId, base::SharedMemory::NULLHandle(),
socket_handle, kLength));
EXPECT_TRUE(delegate.created_received()); EXPECT_TRUE(delegate.created_received());
EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle())); EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle()));
EXPECT_EQ(kLength, delegate.length()); EXPECT_EQ(kLength, delegate.length());
......
...@@ -54,25 +54,6 @@ class MockAudioOutputIPC : public AudioOutputIPC { ...@@ -54,25 +54,6 @@ class MockAudioOutputIPC : public AudioOutputIPC {
MOCK_METHOD1(SetVolume, void(double volume)); MOCK_METHOD1(SetVolume, void(double volume));
}; };
// Creates a copy of a SyncSocket handle that we can give to AudioOutputDevice.
// On Windows this means duplicating the pipe handle so that AudioOutputDevice
// can call CloseHandle() (since ownership has been transferred), but on other
// platforms, we just copy the same socket handle since AudioOutputDevice on
// those platforms won't actually own the socket (FileDescriptor.auto_close is
// false).
bool DuplicateSocketHandle(SyncSocket::Handle socket_handle,
SyncSocket::Handle* copy) {
#if defined(OS_WIN)
HANDLE process = GetCurrentProcess();
::DuplicateHandle(process, socket_handle, process, copy,
0, FALSE, DUPLICATE_SAME_ACCESS);
return *copy != NULL;
#else
*copy = socket_handle;
return *copy != -1;
#endif
}
ACTION_P2(SendPendingBytes, socket, pending_bytes) { ACTION_P2(SendPendingBytes, socket, pending_bytes) {
socket->Send(&pending_bytes, sizeof(pending_bytes)); socket->Send(&pending_bytes, sizeof(pending_bytes));
} }
...@@ -163,15 +144,16 @@ void AudioOutputDeviceTest::CreateStream() { ...@@ -163,15 +144,16 @@ void AudioOutputDeviceTest::CreateStream() {
// Create duplicates of the handles we pass to AudioOutputDevice since // Create duplicates of the handles we pass to AudioOutputDevice since
// ownership will be transferred and AudioOutputDevice is responsible for // ownership will be transferred and AudioOutputDevice is responsible for
// freeing. // freeing.
SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; SyncSocket::TransitDescriptor audio_device_socket_descriptor;
ASSERT_TRUE(DuplicateSocketHandle(renderer_socket_.handle(), ASSERT_TRUE(renderer_socket_.PrepareTransitDescriptor(
&audio_device_socket)); base::GetCurrentProcessHandle(), &audio_device_socket_descriptor));
base::SharedMemoryHandle duplicated_memory_handle; base::SharedMemoryHandle duplicated_memory_handle;
ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(), ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(),
&duplicated_memory_handle)); &duplicated_memory_handle));
audio_device_->OnStreamCreated(duplicated_memory_handle, audio_device_socket, audio_device_->OnStreamCreated(
kMemorySize); duplicated_memory_handle,
SyncSocket::UnwrapHandle(audio_device_socket_descriptor), kMemorySize);
io_loop_.RunUntilIdle(); io_loop_.RunUntilIdle();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment