| Index: remoting/host/desktop_session_proxy.cc
 | 
| diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
 | 
| index c557853f69a0519d8c9b3d60c341703530f0964f..55f7fc597df2d4f4ff9ab5b4185dd584fbf81fb3 100644
 | 
| --- a/remoting/host/desktop_session_proxy.cc
 | 
| +++ b/remoting/host/desktop_session_proxy.cc
 | 
| @@ -7,6 +7,7 @@
 | 
|  #include "base/compiler_specific.h"
 | 
|  #include "base/logging.h"
 | 
|  #include "base/platform_file.h"
 | 
| +#include "base/process_util.h"
 | 
|  #include "base/single_thread_task_runner.h"
 | 
|  #include "ipc/ipc_channel_proxy.h"
 | 
|  #include "ipc/ipc_message_macros.h"
 | 
| @@ -29,12 +30,15 @@ namespace remoting {
 | 
|  
 | 
|  DesktopSessionProxy::DesktopSessionProxy(
 | 
|      scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
 | 
| +    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
 | 
|      const std::string& client_jid,
 | 
|      const base::Closure& disconnect_callback)
 | 
|      : caller_task_runner_(caller_task_runner),
 | 
| +      io_task_runner_(io_task_runner),
 | 
|        audio_capturer_(NULL),
 | 
|        client_jid_(client_jid),
 | 
|        disconnect_callback_(disconnect_callback),
 | 
| +      desktop_process_(base::kNullProcessHandle),
 | 
|        pending_capture_frame_requests_(0),
 | 
|        video_capturer_(NULL) {
 | 
|    DCHECK(caller_task_runner_->BelongsToCurrentThread());
 | 
| @@ -106,18 +110,19 @@ void DesktopSessionProxy::OnChannelError() {
 | 
|  }
 | 
|  
 | 
|  bool DesktopSessionProxy::AttachToDesktop(
 | 
| -    IPC::PlatformFileForTransit desktop_process,
 | 
| +    base::ProcessHandle desktop_process,
 | 
|      IPC::PlatformFileForTransit desktop_pipe) {
 | 
|    DCHECK(caller_task_runner_->BelongsToCurrentThread());
 | 
|    DCHECK(!client_jid_.empty());
 | 
|    DCHECK(!desktop_channel_);
 | 
| +  DCHECK_EQ(desktop_process_, base::kNullProcessHandle);
 | 
|    DCHECK(!disconnect_callback_.is_null());
 | 
|  
 | 
| +  desktop_process_ = desktop_process;
 | 
| +
 | 
|  #if defined(OS_WIN)
 | 
|    // On Windows: |desktop_process| is a valid handle, but |desktop_pipe| needs
 | 
|    // to be duplicated from the desktop process.
 | 
| -  desktop_process_.Set(desktop_process);
 | 
| -
 | 
|    base::win::ScopedHandle pipe;
 | 
|    if (!DuplicateHandle(desktop_process_, desktop_pipe, GetCurrentProcess(),
 | 
|                         pipe.Receive(), 0, FALSE, DUPLICATE_SAME_ACCESS)) {
 | 
| @@ -126,29 +131,24 @@ bool DesktopSessionProxy::AttachToDesktop(
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| -  // Connect to the desktop process.
 | 
| -  desktop_channel_.reset(new IPC::ChannelProxy(IPC::ChannelHandle(pipe),
 | 
| -                                               IPC::Channel::MODE_CLIENT,
 | 
| -                                               this,
 | 
| -                                               caller_task_runner_));
 | 
| +  IPC::ChannelHandle desktop_channel_handle(pipe);
 | 
| +
 | 
|  #elif defined(OS_POSIX)
 | 
| -  // On posix: both |desktop_process| and |desktop_pipe| are valid file
 | 
| -  // descriptors.
 | 
| -  DCHECK(desktop_process.auto_close);
 | 
| +  // On posix: |desktop_pipe| is a valid file descriptor.
 | 
|    DCHECK(desktop_pipe.auto_close);
 | 
|  
 | 
| -  base::ClosePlatformFile(desktop_process.fd);
 | 
| +  IPC::ChannelHandle desktop_channel_handle("", desktop_pipe);
 | 
|  
 | 
| -  // Connect to the desktop process.
 | 
| -  desktop_channel_.reset(new IPC::ChannelProxy(
 | 
| -      IPC::ChannelHandle("", desktop_pipe),
 | 
| -      IPC::Channel::MODE_CLIENT,
 | 
| -      this,
 | 
| -      caller_task_runner_));
 | 
|  #else
 | 
|  #error Unsupported platform.
 | 
|  #endif
 | 
|  
 | 
| +  // Connect to the desktop process.
 | 
| +  desktop_channel_.reset(new IPC::ChannelProxy(desktop_channel_handle,
 | 
| +                                               IPC::Channel::MODE_CLIENT,
 | 
| +                                               this,
 | 
| +                                               io_task_runner_));
 | 
| +
 | 
|    // Pass ID of the client (which is authenticated at this point) to the desktop
 | 
|    // session agent and start the agent.
 | 
|    SendToDesktop(new ChromotingNetworkDesktopMsg_StartSessionAgent(client_jid_));
 | 
| @@ -160,9 +160,10 @@ void DesktopSessionProxy::DetachFromDesktop() {
 | 
|  
 | 
|    desktop_channel_.reset();
 | 
|  
 | 
| -#if defined(OS_WIN)
 | 
| -  desktop_process_.Close();
 | 
| -#endif  // defined(OS_WIN)
 | 
| +  if (desktop_process_ != base::kNullProcessHandle) {
 | 
| +    base::CloseProcessHandle(desktop_process_);
 | 
| +    desktop_process_ = base::kNullProcessHandle;
 | 
| +  }
 | 
|  
 | 
|    shared_buffers_.clear();
 | 
|  
 | 
| @@ -194,12 +195,14 @@ void DesktopSessionProxy::InvalidateRegion(const SkRegion& invalid_region) {
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  std::vector<SkIRect> invalid_rects;
 | 
| -  for (SkRegion::Iterator i(invalid_region); !i.done(); i.next())
 | 
| -    invalid_rects.push_back(i.rect());
 | 
| +  if (desktop_channel_) {
 | 
| +    std::vector<SkIRect> invalid_rects;
 | 
| +    for (SkRegion::Iterator i(invalid_region); !i.done(); i.next())
 | 
| +      invalid_rects.push_back(i.rect());
 | 
|  
 | 
| -  SendToDesktop(
 | 
| -      new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects));
 | 
| +    SendToDesktop(
 | 
| +        new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects));
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void DesktopSessionProxy::CaptureFrame() {
 | 
| @@ -209,8 +212,12 @@ void DesktopSessionProxy::CaptureFrame() {
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  ++pending_capture_frame_requests_;
 | 
| -  SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame());
 | 
| +  if (desktop_channel_) {
 | 
| +    ++pending_capture_frame_requests_;
 | 
| +    SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame());
 | 
| +  } else {
 | 
| +    PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>());
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void DesktopSessionProxy::StartVideoCapturer(
 | 
| @@ -282,6 +289,10 @@ void DesktopSessionProxy::StartEventExecutor(
 | 
|  }
 | 
|  
 | 
|  DesktopSessionProxy::~DesktopSessionProxy() {
 | 
| +  if (desktop_process_ != base::kNullProcessHandle) {
 | 
| +    base::CloseProcessHandle(desktop_process_);
 | 
| +    desktop_process_ = base::kNullProcessHandle;
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  scoped_refptr<media::SharedBuffer> DesktopSessionProxy::GetSharedBuffer(
 | 
| 
 |