3a520d286d765ad7aae7bdbd33f5e59e78f95a52
[platform/framework/web/crosswalk.git] / src / content / child / socket_stream_dispatcher.cc
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
27 namespace content {
28
29 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
30 // It communicates with the main browser process via SocketStreamDispatcher.
31 class 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
68 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
69     IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
70
71 /* static */
72 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
73     int id) {
74   return all_bridges.Get().Lookup(id);
75 }
76
77 IPCWebSocketStreamHandleBridge::~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
88 void 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
111 bool 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
122 void IPCWebSocketStreamHandleBridge::Close() {
123   DVLOG(1) << "Bridge #" << socket_id_ << " Close";
124
125   ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
126 }
127
128 void 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
137 void 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
145 void 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
153 void 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
166 void 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
174 SocketStreamDispatcher::SocketStreamDispatcher() {
175 }
176
177 // static
178 WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
179     blink::WebSocketStreamHandle* handle,
180     WebSocketStreamHandleDelegate* delegate) {
181   return new IPCWebSocketStreamHandleBridge(handle, delegate);
182 }
183
184 bool 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
197 void 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
210 void 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
222 void 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
235 void 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
246 void 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