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