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
3// found in the LICENSE file.
4
5#include "content/child/socket_stream_dispatcher.h"
6
7#include <string>
8#include <vector>
9
10#include "base/bind.h"
11#include "base/id_map.h"
12#include "base/lazy_instance.h"
13#include "base/memory/ref_counted.h"
14#include "base/message_loop/message_loop.h"
15#include "base/strings/string16.h"
16#include "base/strings/utf_string_conversions.h"
17#include "content/child/child_thread.h"
18#include "content/child/web_socket_stream_handle_bridge.h"
19#include "content/child/web_socket_stream_handle_delegate.h"
20#include "content/child/web_socket_stream_handle_impl.h"
21#include "content/common/socket_stream.h"
22#include "content/common/socket_stream_handle_data.h"
23#include "content/common/socket_stream_messages.h"
24#include "net/base/net_errors.h"
25#include "url/gurl.h"
26
27namespace content {
28
29// IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
30// It communicates with the main browser process via SocketStreamDispatcher.
31class IPCWebSocketStreamHandleBridge : public WebSocketStreamHandleBridge {
32 public:
33  IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle* handle,
34                                 WebSocketStreamHandleDelegate* delegate)
35      : socket_id_(kNoSocketId), handle_(handle), delegate_(delegate) {}
36
37  // Returns the handle having given id or NULL if there is no such handle.
38  static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
39
40  // WebSocketStreamHandleBridge methods.
41  virtual void Connect(const GURL& url) OVERRIDE;
42  virtual bool Send(const std::vector<char>& data) OVERRIDE;
43  virtual void Close() OVERRIDE;
44
45  // Called by SocketStreamDispatcher.
46  void OnConnected(int max_amount_send_allowed);
47  void OnSentData(int amount_sent);
48  void OnReceivedData(const std::vector<char>& data);
49  void OnClosed();
50  void OnFailed(int error_code, const std::string& error_msg);
51
52 private:
53  virtual ~IPCWebSocketStreamHandleBridge();
54
55  // The ID for this bridge and corresponding SocketStream instance in the
56  // browser process.
57  int socket_id_;
58
59  blink::WebSocketStreamHandle* handle_;
60  WebSocketStreamHandleDelegate* delegate_;
61
62  // Map from ID to bridge instance.
63  static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
64      all_bridges;
65};
66
67// static
68base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
69    IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
70
71/* static */
72IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
73    int id) {
74  return all_bridges.Get().Lookup(id);
75}
76
77IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
78  DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
79           << ") Destructor";
80
81  if (socket_id_ == kNoSocketId)
82    return;
83
84  ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
85  socket_id_ = kNoSocketId;
86}
87
88void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
89  DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
90
91  DCHECK_EQ(socket_id_, kNoSocketId);
92  if (delegate_)
93    delegate_->WillOpenStream(handle_, url);
94
95  socket_id_ = all_bridges.Get().Add(this);
96  DCHECK_NE(socket_id_, kNoSocketId);
97  int render_frame_id = MSG_ROUTING_NONE;
98  WebSocketStreamHandleImpl* impl =
99      static_cast<WebSocketStreamHandleImpl*>(handle_);
100  const SocketStreamHandleData* data =
101      static_cast<SocketStreamHandleData*>(impl->GetUserData(handle_));
102  if (data)
103    render_frame_id = data->render_frame_id();
104  AddRef();  // Released in OnClosed().
105  ChildThread::current()->Send(
106      new SocketStreamHostMsg_Connect(render_frame_id, url, socket_id_));
107  DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect";
108  // TODO(ukai): timeout to OnConnected.
109}
110
111bool IPCWebSocketStreamHandleBridge::Send(const std::vector<char>& data) {
112  DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
113           << " bytes)";
114
115  ChildThread::current()->Send(
116      new SocketStreamHostMsg_SendData(socket_id_, data));
117  if (delegate_)
118    delegate_->WillSendData(handle_, &data[0], data.size());
119  return true;
120}
121
122void IPCWebSocketStreamHandleBridge::Close() {
123  DVLOG(1) << "Bridge #" << socket_id_ << " Close";
124
125  ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
126}
127
128void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed) {
129  DVLOG(1) << "Bridge #" << socket_id_
130           << " OnConnected (max_pending_send_allowed="
131           << max_pending_send_allowed << ")";
132
133  if (delegate_)
134    delegate_->DidOpenStream(handle_, max_pending_send_allowed);
135}
136
137void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
138  DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
139           << " bytes)";
140
141  if (delegate_)
142    delegate_->DidSendData(handle_, amount_sent);
143}
144
145void IPCWebSocketStreamHandleBridge::OnReceivedData(
146    const std::vector<char>& data) {
147  DVLOG(1) << "Bridge #" << socket_id_ << " OnReceiveData (" << data.size()
148           << " bytes)";
149  if (delegate_)
150    delegate_->DidReceiveData(handle_, &data[0], data.size());
151}
152
153void IPCWebSocketStreamHandleBridge::OnClosed() {
154  DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
155
156  if (socket_id_ != kNoSocketId) {
157    all_bridges.Get().Remove(socket_id_);
158    socket_id_ = kNoSocketId;
159  }
160  if (delegate_)
161    delegate_->DidClose(handle_);
162  delegate_ = NULL;
163  Release();
164}
165
166void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
167                                              const std::string& error_msg) {
168  DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
169           << ")";
170  if (delegate_)
171    delegate_->DidFail(handle_, error_code, base::ASCIIToUTF16(error_msg));
172}
173
174SocketStreamDispatcher::SocketStreamDispatcher() {
175}
176
177// static
178WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
179    blink::WebSocketStreamHandle* handle,
180    WebSocketStreamHandleDelegate* delegate) {
181  return new IPCWebSocketStreamHandleBridge(handle, delegate);
182}
183
184bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
185  bool handled = true;
186  IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg)
187    IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected)
188    IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
189    IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
190    IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
191    IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
192    IPC_MESSAGE_UNHANDLED(handled = false)
193  IPC_END_MESSAGE_MAP()
194  return handled;
195}
196
197void SocketStreamDispatcher::OnConnected(int socket_id,
198                                         int max_pending_send_allowed) {
199  DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
200           << max_pending_send_allowed << ") to socket_id=" << socket_id;
201
202  IPCWebSocketStreamHandleBridge* bridge =
203      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
204  if (bridge)
205    bridge->OnConnected(max_pending_send_allowed);
206  else
207    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
208}
209
210void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
211  DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
212           << " bytes) to socket_id=" << socket_id;
213
214  IPCWebSocketStreamHandleBridge* bridge =
215      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
216  if (bridge)
217    bridge->OnSentData(amount_sent);
218  else
219    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
220}
221
222void SocketStreamDispatcher::OnReceivedData(
223    int socket_id, const std::vector<char>& data) {
224  DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size()
225           << " bytes) to socket_id=" << socket_id;
226
227  IPCWebSocketStreamHandleBridge* bridge =
228      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
229  if (bridge)
230    bridge->OnReceivedData(data);
231  else
232    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
233}
234
235void SocketStreamDispatcher::OnClosed(int socket_id) {
236  DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
237
238  IPCWebSocketStreamHandleBridge* bridge =
239      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
240  if (bridge)
241    bridge->OnClosed();
242  else
243    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
244}
245
246void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
247  IPCWebSocketStreamHandleBridge* bridge =
248      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
249  if (bridge)
250    bridge->OnFailed(error_code, net::ErrorToString(error_code));
251  else
252    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
253}
254
255}  // namespace content
256