| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "remoting/host/desktop_session_proxy.h" | 5 #include "remoting/host/desktop_session_proxy.h" | 
| 6 | 6 | 
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" | 
| 8 #include "base/logging.h" | 8 #include "base/logging.h" | 
| 9 #include "base/platform_file.h" | 9 #include "base/platform_file.h" | 
|  | 10 #include "base/process_util.h" | 
| 10 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" | 
| 11 #include "ipc/ipc_channel_proxy.h" | 12 #include "ipc/ipc_channel_proxy.h" | 
| 12 #include "ipc/ipc_message_macros.h" | 13 #include "ipc/ipc_message_macros.h" | 
| 13 #include "media/video/capture/screen/screen_capture_data.h" | 14 #include "media/video/capture/screen/screen_capture_data.h" | 
| 14 #include "remoting/host/audio_capturer.h" | 15 #include "remoting/host/audio_capturer.h" | 
| 15 #include "remoting/host/chromoting_messages.h" | 16 #include "remoting/host/chromoting_messages.h" | 
| 16 #include "remoting/host/client_session.h" | 17 #include "remoting/host/client_session.h" | 
| 17 #include "remoting/host/ipc_audio_capturer.h" | 18 #include "remoting/host/ipc_audio_capturer.h" | 
| 18 #include "remoting/host/ipc_event_executor.h" | 19 #include "remoting/host/ipc_event_executor.h" | 
| 19 #include "remoting/host/ipc_video_frame_capturer.h" | 20 #include "remoting/host/ipc_video_frame_capturer.h" | 
| 20 #include "remoting/proto/audio.pb.h" | 21 #include "remoting/proto/audio.pb.h" | 
| 21 #include "remoting/proto/control.pb.h" | 22 #include "remoting/proto/control.pb.h" | 
| 22 #include "remoting/proto/event.pb.h" | 23 #include "remoting/proto/event.pb.h" | 
| 23 | 24 | 
| 24 #if defined(OS_WIN) | 25 #if defined(OS_WIN) | 
| 25 #include "base/win/scoped_handle.h" | 26 #include "base/win/scoped_handle.h" | 
| 26 #endif  // defined(OS_WIN) | 27 #endif  // defined(OS_WIN) | 
| 27 | 28 | 
| 28 namespace remoting { | 29 namespace remoting { | 
| 29 | 30 | 
| 30 DesktopSessionProxy::DesktopSessionProxy( | 31 DesktopSessionProxy::DesktopSessionProxy( | 
| 31     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 32     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 
|  | 33     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | 
| 32     const std::string& client_jid, | 34     const std::string& client_jid, | 
| 33     const base::Closure& disconnect_callback) | 35     const base::Closure& disconnect_callback) | 
| 34     : caller_task_runner_(caller_task_runner), | 36     : caller_task_runner_(caller_task_runner), | 
|  | 37       io_task_runner_(io_task_runner), | 
| 35       audio_capturer_(NULL), | 38       audio_capturer_(NULL), | 
| 36       client_jid_(client_jid), | 39       client_jid_(client_jid), | 
| 37       disconnect_callback_(disconnect_callback), | 40       disconnect_callback_(disconnect_callback), | 
|  | 41       desktop_process_(base::kNullProcessHandle), | 
| 38       pending_capture_frame_requests_(0), | 42       pending_capture_frame_requests_(0), | 
| 39       video_capturer_(NULL) { | 43       video_capturer_(NULL) { | 
| 40   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 44   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 41   DCHECK(!client_jid_.empty()); | 45   DCHECK(!client_jid_.empty()); | 
| 42   DCHECK(!disconnect_callback_.is_null()); | 46   DCHECK(!disconnect_callback_.is_null()); | 
| 43 } | 47 } | 
| 44 | 48 | 
| 45 scoped_ptr<AudioCapturer> DesktopSessionProxy::CreateAudioCapturer( | 49 scoped_ptr<AudioCapturer> DesktopSessionProxy::CreateAudioCapturer( | 
| 46     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner) { | 50     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner) { | 
| 47   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 51   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 99   VLOG(1) << "IPC: network <- desktop (" << peer_pid << ")"; | 103   VLOG(1) << "IPC: network <- desktop (" << peer_pid << ")"; | 
| 100 } | 104 } | 
| 101 | 105 | 
| 102 void DesktopSessionProxy::OnChannelError() { | 106 void DesktopSessionProxy::OnChannelError() { | 
| 103   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 107   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 104 | 108 | 
| 105   DetachFromDesktop(); | 109   DetachFromDesktop(); | 
| 106 } | 110 } | 
| 107 | 111 | 
| 108 bool DesktopSessionProxy::AttachToDesktop( | 112 bool DesktopSessionProxy::AttachToDesktop( | 
| 109     IPC::PlatformFileForTransit desktop_process, | 113     base::ProcessHandle desktop_process, | 
| 110     IPC::PlatformFileForTransit desktop_pipe) { | 114     IPC::PlatformFileForTransit desktop_pipe) { | 
| 111   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 115   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 112   DCHECK(!client_jid_.empty()); | 116   DCHECK(!client_jid_.empty()); | 
| 113   DCHECK(!desktop_channel_); | 117   DCHECK(!desktop_channel_); | 
|  | 118   DCHECK_EQ(desktop_process_, base::kNullProcessHandle); | 
| 114   DCHECK(!disconnect_callback_.is_null()); | 119   DCHECK(!disconnect_callback_.is_null()); | 
| 115 | 120 | 
|  | 121   desktop_process_ = desktop_process; | 
|  | 122 | 
| 116 #if defined(OS_WIN) | 123 #if defined(OS_WIN) | 
| 117   // On Windows: |desktop_process| is a valid handle, but |desktop_pipe| needs | 124   // On Windows: |desktop_process| is a valid handle, but |desktop_pipe| needs | 
| 118   // to be duplicated from the desktop process. | 125   // to be duplicated from the desktop process. | 
| 119   desktop_process_.Set(desktop_process); |  | 
| 120 |  | 
| 121   base::win::ScopedHandle pipe; | 126   base::win::ScopedHandle pipe; | 
| 122   if (!DuplicateHandle(desktop_process_, desktop_pipe, GetCurrentProcess(), | 127   if (!DuplicateHandle(desktop_process_, desktop_pipe, GetCurrentProcess(), | 
| 123                        pipe.Receive(), 0, FALSE, DUPLICATE_SAME_ACCESS)) { | 128                        pipe.Receive(), 0, FALSE, DUPLICATE_SAME_ACCESS)) { | 
| 124     LOG_GETLASTERROR(ERROR) << "Failed to duplicate the desktop-to-network" | 129     LOG_GETLASTERROR(ERROR) << "Failed to duplicate the desktop-to-network" | 
| 125                                " pipe handle"; | 130                                " pipe handle"; | 
| 126     return false; | 131     return false; | 
| 127   } | 132   } | 
| 128 | 133 | 
| 129   // Connect to the desktop process. | 134   IPC::ChannelHandle desktop_channel_handle(pipe); | 
| 130   desktop_channel_.reset(new IPC::ChannelProxy(IPC::ChannelHandle(pipe), | 135 | 
| 131                                                IPC::Channel::MODE_CLIENT, |  | 
| 132                                                this, |  | 
| 133                                                caller_task_runner_)); |  | 
| 134 #elif defined(OS_POSIX) | 136 #elif defined(OS_POSIX) | 
| 135   // On posix: both |desktop_process| and |desktop_pipe| are valid file | 137   // On posix: |desktop_pipe| is a valid file descriptor. | 
| 136   // descriptors. |  | 
| 137   DCHECK(desktop_process.auto_close); |  | 
| 138   DCHECK(desktop_pipe.auto_close); | 138   DCHECK(desktop_pipe.auto_close); | 
| 139 | 139 | 
| 140   base::ClosePlatformFile(desktop_process.fd); | 140   IPC::ChannelHandle desktop_channel_handle("", desktop_pipe); | 
| 141 | 141 | 
| 142   // Connect to the desktop process. |  | 
| 143   desktop_channel_.reset(new IPC::ChannelProxy( |  | 
| 144       IPC::ChannelHandle("", desktop_pipe), |  | 
| 145       IPC::Channel::MODE_CLIENT, |  | 
| 146       this, |  | 
| 147       caller_task_runner_)); |  | 
| 148 #else | 142 #else | 
| 149 #error Unsupported platform. | 143 #error Unsupported platform. | 
| 150 #endif | 144 #endif | 
| 151 | 145 | 
|  | 146   // Connect to the desktop process. | 
|  | 147   desktop_channel_.reset(new IPC::ChannelProxy(desktop_channel_handle, | 
|  | 148                                                IPC::Channel::MODE_CLIENT, | 
|  | 149                                                this, | 
|  | 150                                                io_task_runner_)); | 
|  | 151 | 
| 152   // Pass ID of the client (which is authenticated at this point) to the desktop | 152   // Pass ID of the client (which is authenticated at this point) to the desktop | 
| 153   // session agent and start the agent. | 153   // session agent and start the agent. | 
| 154   SendToDesktop(new ChromotingNetworkDesktopMsg_StartSessionAgent(client_jid_)); | 154   SendToDesktop(new ChromotingNetworkDesktopMsg_StartSessionAgent(client_jid_)); | 
| 155   return true; | 155   return true; | 
| 156 } | 156 } | 
| 157 | 157 | 
| 158 void DesktopSessionProxy::DetachFromDesktop() { | 158 void DesktopSessionProxy::DetachFromDesktop() { | 
| 159   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 159   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 160 | 160 | 
| 161   desktop_channel_.reset(); | 161   desktop_channel_.reset(); | 
| 162 | 162 | 
| 163 #if defined(OS_WIN) | 163   if (desktop_process_ != base::kNullProcessHandle) { | 
| 164   desktop_process_.Close(); | 164     base::CloseProcessHandle(desktop_process_); | 
| 165 #endif  // defined(OS_WIN) | 165     desktop_process_ = base::kNullProcessHandle; | 
|  | 166   } | 
| 166 | 167 | 
| 167   shared_buffers_.clear(); | 168   shared_buffers_.clear(); | 
| 168 | 169 | 
| 169   // Generate fake responses to keep the video capturer in sync. | 170   // Generate fake responses to keep the video capturer in sync. | 
| 170   while (pending_capture_frame_requests_) { | 171   while (pending_capture_frame_requests_) { | 
| 171     --pending_capture_frame_requests_; | 172     --pending_capture_frame_requests_; | 
| 172     PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); | 173     PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); | 
| 173   } | 174   } | 
| 174 } | 175 } | 
| 175 | 176 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 187 } | 188 } | 
| 188 | 189 | 
| 189 void DesktopSessionProxy::InvalidateRegion(const SkRegion& invalid_region) { | 190 void DesktopSessionProxy::InvalidateRegion(const SkRegion& invalid_region) { | 
| 190   if (!caller_task_runner_->BelongsToCurrentThread()) { | 191   if (!caller_task_runner_->BelongsToCurrentThread()) { | 
| 191     caller_task_runner_->PostTask( | 192     caller_task_runner_->PostTask( | 
| 192         FROM_HERE, base::Bind(&DesktopSessionProxy::InvalidateRegion, this, | 193         FROM_HERE, base::Bind(&DesktopSessionProxy::InvalidateRegion, this, | 
| 193                               invalid_region)); | 194                               invalid_region)); | 
| 194     return; | 195     return; | 
| 195   } | 196   } | 
| 196 | 197 | 
| 197   std::vector<SkIRect> invalid_rects; | 198   if (desktop_channel_) { | 
| 198   for (SkRegion::Iterator i(invalid_region); !i.done(); i.next()) | 199     std::vector<SkIRect> invalid_rects; | 
| 199     invalid_rects.push_back(i.rect()); | 200     for (SkRegion::Iterator i(invalid_region); !i.done(); i.next()) | 
|  | 201       invalid_rects.push_back(i.rect()); | 
| 200 | 202 | 
| 201   SendToDesktop( | 203     SendToDesktop( | 
| 202       new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects)); | 204         new ChromotingNetworkDesktopMsg_InvalidateRegion(invalid_rects)); | 
|  | 205   } | 
| 203 } | 206 } | 
| 204 | 207 | 
| 205 void DesktopSessionProxy::CaptureFrame() { | 208 void DesktopSessionProxy::CaptureFrame() { | 
| 206   if (!caller_task_runner_->BelongsToCurrentThread()) { | 209   if (!caller_task_runner_->BelongsToCurrentThread()) { | 
| 207     caller_task_runner_->PostTask( | 210     caller_task_runner_->PostTask( | 
| 208         FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); | 211         FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this)); | 
| 209     return; | 212     return; | 
| 210   } | 213   } | 
| 211 | 214 | 
| 212   ++pending_capture_frame_requests_; | 215   if (desktop_channel_) { | 
| 213   SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); | 216     ++pending_capture_frame_requests_; | 
|  | 217     SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame()); | 
|  | 218   } else { | 
|  | 219     PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); | 
|  | 220   } | 
| 214 } | 221 } | 
| 215 | 222 | 
| 216 void DesktopSessionProxy::StartVideoCapturer( | 223 void DesktopSessionProxy::StartVideoCapturer( | 
| 217     IpcVideoFrameCapturer* video_capturer) { | 224     IpcVideoFrameCapturer* video_capturer) { | 
| 218   DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); | 225   DCHECK(video_capture_task_runner_->BelongsToCurrentThread()); | 
| 219   DCHECK(video_capturer_ == NULL); | 226   DCHECK(video_capturer_ == NULL); | 
| 220 | 227 | 
| 221   video_capturer_ = video_capturer; | 228   video_capturer_ = video_capturer; | 
| 222 } | 229 } | 
| 223 | 230 | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 275 } | 282 } | 
| 276 | 283 | 
| 277 void DesktopSessionProxy::StartEventExecutor( | 284 void DesktopSessionProxy::StartEventExecutor( | 
| 278     scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 285     scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 
| 279   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 286   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 280 | 287 | 
| 281   client_clipboard_ = client_clipboard.Pass(); | 288   client_clipboard_ = client_clipboard.Pass(); | 
| 282 } | 289 } | 
| 283 | 290 | 
| 284 DesktopSessionProxy::~DesktopSessionProxy() { | 291 DesktopSessionProxy::~DesktopSessionProxy() { | 
|  | 292   if (desktop_process_ != base::kNullProcessHandle) { | 
|  | 293     base::CloseProcessHandle(desktop_process_); | 
|  | 294     desktop_process_ = base::kNullProcessHandle; | 
|  | 295   } | 
| 285 } | 296 } | 
| 286 | 297 | 
| 287 scoped_refptr<media::SharedBuffer> DesktopSessionProxy::GetSharedBuffer( | 298 scoped_refptr<media::SharedBuffer> DesktopSessionProxy::GetSharedBuffer( | 
| 288     int id) { | 299     int id) { | 
| 289   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 300   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 290 | 301 | 
| 291   SharedBuffers::const_iterator i = shared_buffers_.find(id); | 302   SharedBuffers::const_iterator i = shared_buffers_.find(id); | 
| 292   if (i != shared_buffers_.end()) { | 303   if (i != shared_buffers_.end()) { | 
| 293     return i->second; | 304     return i->second; | 
| 294   } else { | 305   } else { | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 453   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 464   DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
| 454 | 465 | 
| 455   if (desktop_channel_) { | 466   if (desktop_channel_) { | 
| 456     desktop_channel_->Send(message); | 467     desktop_channel_->Send(message); | 
| 457   } else { | 468   } else { | 
| 458     delete message; | 469     delete message; | 
| 459   } | 470   } | 
| 460 } | 471 } | 
| 461 | 472 | 
| 462 }  // namespace remoting | 473 }  // namespace remoting | 
| OLD | NEW | 
|---|