• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/common/socket_stream.h"
18 #include "content/common/socket_stream_handle_data.h"
19 #include "content/common/socket_stream_messages.h"
20 #include "net/base/net_errors.h"
21 #include "url/gurl.h"
22 #include "webkit/child/websocketstreamhandle_bridge.h"
23 #include "webkit/child/websocketstreamhandle_delegate.h"
24 
25 namespace content {
26 
27 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
28 // It communicates with the main browser process via SocketStreamDispatcher.
29 class IPCWebSocketStreamHandleBridge
30     : public webkit_glue::WebSocketStreamHandleBridge {
31  public:
IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle * handle,webkit_glue::WebSocketStreamHandleDelegate * delegate)32   IPCWebSocketStreamHandleBridge(
33       blink::WebSocketStreamHandle* handle,
34       webkit_glue::WebSocketStreamHandleDelegate* delegate)
35       : socket_id_(kNoSocketId),
36         handle_(handle),
37         delegate_(delegate) {}
38 
39   // Returns the handle having given id or NULL if there is no such handle.
40   static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
41 
42   // webkit_glue::WebSocketStreamHandleBridge methods.
43   virtual void Connect(const GURL& url) OVERRIDE;
44   virtual bool Send(const std::vector<char>& data) OVERRIDE;
45   virtual void Close() OVERRIDE;
46 
47   // Called by SocketStreamDispatcher.
48   void OnConnected(int max_amount_send_allowed);
49   void OnSentData(int amount_sent);
50   void OnReceivedData(const std::vector<char>& data);
51   void OnClosed();
52   void OnFailed(int error_code, const char* error_msg);
53 
54  private:
55   virtual ~IPCWebSocketStreamHandleBridge();
56 
57   // The ID for this bridge and corresponding SocketStream instance in the
58   // browser process.
59   int socket_id_;
60 
61   blink::WebSocketStreamHandle* handle_;
62   webkit_glue::WebSocketStreamHandleDelegate* delegate_;
63 
64   // Map from ID to bridge instance.
65   static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
66       all_bridges;
67 };
68 
69 // static
70 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
71     IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
72 
73 /* static */
FromSocketId(int id)74 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
75     int id) {
76   return all_bridges.Get().Lookup(id);
77 }
78 
~IPCWebSocketStreamHandleBridge()79 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
80   DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
81            << ") Destructor";
82 
83   if (socket_id_ == kNoSocketId)
84     return;
85 
86   ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
87   socket_id_ = kNoSocketId;
88 }
89 
Connect(const GURL & url)90 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
91   DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
92 
93   DCHECK_EQ(socket_id_, kNoSocketId);
94   if (delegate_)
95     delegate_->WillOpenStream(handle_, url);
96 
97   socket_id_ = all_bridges.Get().Add(this);
98   DCHECK_NE(socket_id_, kNoSocketId);
99   int render_view_id = MSG_ROUTING_NONE;
100   const SocketStreamHandleData* data =
101       SocketStreamHandleData::ForHandle(handle_);
102   if (data)
103     render_view_id = data->render_view_id();
104   AddRef();  // Released in OnClosed().
105   ChildThread::current()->Send(
106       new SocketStreamHostMsg_Connect(render_view_id, url, socket_id_));
107   DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect";
108   // TODO(ukai): timeout to OnConnected.
109 }
110 
Send(const std::vector<char> & data)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 
Close()122 void IPCWebSocketStreamHandleBridge::Close() {
123   DVLOG(1) << "Bridge #" << socket_id_ << " Close";
124 
125   ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
126 }
127 
OnConnected(int max_pending_send_allowed)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 
OnSentData(int amount_sent)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 
OnReceivedData(const std::vector<char> & data)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 
OnClosed()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 
OnFailed(int error_code,const char * error_msg)166 void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
167                                               const char* error_msg) {
168   DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
169            << ")";
170   if (delegate_)
171     delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg));
172 }
173 
SocketStreamDispatcher()174 SocketStreamDispatcher::SocketStreamDispatcher() {
175 }
176 
177 /* static */
178 webkit_glue::WebSocketStreamHandleBridge*
CreateBridge(blink::WebSocketStreamHandle * handle,webkit_glue::WebSocketStreamHandleDelegate * delegate)179 SocketStreamDispatcher::CreateBridge(
180     blink::WebSocketStreamHandle* handle,
181     webkit_glue::WebSocketStreamHandleDelegate* delegate) {
182   return new IPCWebSocketStreamHandleBridge(handle, delegate);
183 }
184 
OnMessageReceived(const IPC::Message & msg)185 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
186   bool handled = true;
187   IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg)
188     IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected)
189     IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
190     IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
191     IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
192     IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
193     IPC_MESSAGE_UNHANDLED(handled = false)
194   IPC_END_MESSAGE_MAP()
195   return handled;
196 }
197 
OnConnected(int socket_id,int max_pending_send_allowed)198 void SocketStreamDispatcher::OnConnected(int socket_id,
199                                          int max_pending_send_allowed) {
200   DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
201            << max_pending_send_allowed << ") to socket_id=" << socket_id;
202 
203   IPCWebSocketStreamHandleBridge* bridge =
204       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
205   if (bridge)
206     bridge->OnConnected(max_pending_send_allowed);
207   else
208     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
209 }
210 
OnSentData(int socket_id,int amount_sent)211 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
212   DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
213            << " bytes) to socket_id=" << socket_id;
214 
215   IPCWebSocketStreamHandleBridge* bridge =
216       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
217   if (bridge)
218     bridge->OnSentData(amount_sent);
219   else
220     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
221 }
222 
OnReceivedData(int socket_id,const std::vector<char> & data)223 void SocketStreamDispatcher::OnReceivedData(
224     int socket_id, const std::vector<char>& data) {
225   DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size()
226            << " bytes) to socket_id=" << socket_id;
227 
228   IPCWebSocketStreamHandleBridge* bridge =
229       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
230   if (bridge)
231     bridge->OnReceivedData(data);
232   else
233     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
234 }
235 
OnClosed(int socket_id)236 void SocketStreamDispatcher::OnClosed(int socket_id) {
237   DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
238 
239   IPCWebSocketStreamHandleBridge* bridge =
240       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
241   if (bridge)
242     bridge->OnClosed();
243   else
244     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
245 }
246 
OnFailed(int socket_id,int error_code)247 void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
248   IPCWebSocketStreamHandleBridge* bridge =
249       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
250   if (bridge)
251     bridge->OnFailed(error_code, net::ErrorToString(error_code));
252   else
253     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
254 }
255 
256 }  // namespace content
257