OLD | NEW |
| (Empty) |
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/common/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.h" | |
14 #include "base/string16.h" | |
15 #include "base/utf_string_conversions.h" | |
16 #include "content/common/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 "googleurl/src/gurl.h" | |
21 #include "net/base/net_errors.h" | |
22 #include "webkit/glue/websocketstreamhandle_bridge.h" | |
23 #include "webkit/glue/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: | |
32 IPCWebSocketStreamHandleBridge( | |
33 ChildThread* child_thread, | |
34 WebKit::WebSocketStreamHandle* handle, | |
35 webkit_glue::WebSocketStreamHandleDelegate* delegate) | |
36 : socket_id_(kNoSocketId), | |
37 child_thread_(child_thread), | |
38 handle_(handle), | |
39 delegate_(delegate) {} | |
40 | |
41 // Returns the handle having given id or NULL if there is no such handle. | |
42 static IPCWebSocketStreamHandleBridge* FromSocketId(int id); | |
43 | |
44 // webkit_glue::WebSocketStreamHandleBridge methods. | |
45 virtual void Connect(const GURL& url) OVERRIDE; | |
46 virtual bool Send(const std::vector<char>& data) OVERRIDE; | |
47 virtual void Close() OVERRIDE; | |
48 | |
49 // Called by SocketStreamDispatcher. | |
50 void OnConnected(int max_amount_send_allowed); | |
51 void OnSentData(int amount_sent); | |
52 void OnReceivedData(const std::vector<char>& data); | |
53 void OnClosed(); | |
54 void OnFailed(int error_code, const char* error_msg); | |
55 | |
56 private: | |
57 virtual ~IPCWebSocketStreamHandleBridge(); | |
58 | |
59 void DoConnect(const GURL& url); | |
60 void DoClose(); | |
61 | |
62 // The ID for this bridge and corresponding SocketStream instance in the | |
63 // browser process. | |
64 int socket_id_; | |
65 | |
66 ChildThread* child_thread_; | |
67 WebKit::WebSocketStreamHandle* handle_; | |
68 webkit_glue::WebSocketStreamHandleDelegate* delegate_; | |
69 | |
70 // Map from ID to bridge instance. | |
71 static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky | |
72 all_bridges; | |
73 }; | |
74 | |
75 // static | |
76 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky | |
77 IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER; | |
78 | |
79 /* static */ | |
80 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId( | |
81 int id) { | |
82 return all_bridges.Get().Lookup(id); | |
83 } | |
84 | |
85 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() { | |
86 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_ | |
87 << ") Destructor"; | |
88 | |
89 if (socket_id_ == kNoSocketId) | |
90 return; | |
91 | |
92 child_thread_->Send(new SocketStreamHostMsg_Close(socket_id_)); | |
93 socket_id_ = kNoSocketId; | |
94 } | |
95 | |
96 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) { | |
97 DCHECK(child_thread_); | |
98 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")"; | |
99 | |
100 child_thread_->message_loop()->PostTask( | |
101 FROM_HERE, | |
102 base::Bind(&IPCWebSocketStreamHandleBridge::DoConnect, this, url)); | |
103 } | |
104 | |
105 bool IPCWebSocketStreamHandleBridge::Send( | |
106 const std::vector<char>& data) { | |
107 DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size() | |
108 << " bytes)"; | |
109 | |
110 if (child_thread_->Send( | |
111 new SocketStreamHostMsg_SendData(socket_id_, data))) { | |
112 if (delegate_) | |
113 delegate_->WillSendData(handle_, &data[0], data.size()); | |
114 return true; | |
115 } | |
116 return false; | |
117 } | |
118 | |
119 void IPCWebSocketStreamHandleBridge::Close() { | |
120 DVLOG(1) << "Bridge #" << socket_id_ << " Close"; | |
121 | |
122 AddRef(); // Released in DoClose(). | |
123 child_thread_->message_loop()->PostTask( | |
124 FROM_HERE, | |
125 base::Bind(&IPCWebSocketStreamHandleBridge::DoClose, this)); | |
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 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 | |
174 void IPCWebSocketStreamHandleBridge::DoConnect(const GURL& url) { | |
175 DCHECK(child_thread_); | |
176 DCHECK_EQ(socket_id_, kNoSocketId); | |
177 if (delegate_) | |
178 delegate_->WillOpenStream(handle_, url); | |
179 | |
180 socket_id_ = all_bridges.Get().Add(this); | |
181 DCHECK_NE(socket_id_, kNoSocketId); | |
182 int render_view_id = MSG_ROUTING_NONE; | |
183 const SocketStreamHandleData* data = | |
184 SocketStreamHandleData::ForHandle(handle_); | |
185 if (data) | |
186 render_view_id = data->render_view_id(); | |
187 AddRef(); // Released in OnClosed(). | |
188 if (child_thread_->Send( | |
189 new SocketStreamHostMsg_Connect(render_view_id, url, socket_id_))) { | |
190 DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect"; | |
191 // TODO(ukai): timeout to OnConnected. | |
192 } else { | |
193 DLOG(ERROR) << "Bridge #" << socket_id_ << " failed to send IPC Connect"; | |
194 OnClosed(); | |
195 } | |
196 } | |
197 | |
198 void IPCWebSocketStreamHandleBridge::DoClose() { | |
199 child_thread_->Send(new SocketStreamHostMsg_Close(socket_id_)); | |
200 Release(); | |
201 } | |
202 | |
203 SocketStreamDispatcher::SocketStreamDispatcher() { | |
204 } | |
205 | |
206 /* static */ | |
207 webkit_glue::WebSocketStreamHandleBridge* | |
208 SocketStreamDispatcher::CreateBridge( | |
209 WebKit::WebSocketStreamHandle* handle, | |
210 webkit_glue::WebSocketStreamHandleDelegate* delegate) { | |
211 return new IPCWebSocketStreamHandleBridge( | |
212 ChildThread::current(), handle, delegate); | |
213 } | |
214 | |
215 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) { | |
216 bool handled = true; | |
217 IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg) | |
218 IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected) | |
219 IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData) | |
220 IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData) | |
221 IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed) | |
222 IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed) | |
223 IPC_MESSAGE_UNHANDLED(handled = false) | |
224 IPC_END_MESSAGE_MAP() | |
225 return handled; | |
226 } | |
227 | |
228 void SocketStreamDispatcher::OnConnected(int socket_id, | |
229 int max_pending_send_allowed) { | |
230 DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed=" | |
231 << max_pending_send_allowed << ") to socket_id=" << socket_id; | |
232 | |
233 IPCWebSocketStreamHandleBridge* bridge = | |
234 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); | |
235 if (bridge) | |
236 bridge->OnConnected(max_pending_send_allowed); | |
237 else | |
238 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; | |
239 } | |
240 | |
241 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) { | |
242 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent | |
243 << " bytes) to socket_id=" << socket_id; | |
244 | |
245 IPCWebSocketStreamHandleBridge* bridge = | |
246 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); | |
247 if (bridge) | |
248 bridge->OnSentData(amount_sent); | |
249 else | |
250 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; | |
251 } | |
252 | |
253 void SocketStreamDispatcher::OnReceivedData( | |
254 int socket_id, const std::vector<char>& data) { | |
255 DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size() | |
256 << " bytes) to socket_id=" << socket_id; | |
257 | |
258 IPCWebSocketStreamHandleBridge* bridge = | |
259 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); | |
260 if (bridge) | |
261 bridge->OnReceivedData(data); | |
262 else | |
263 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; | |
264 } | |
265 | |
266 void SocketStreamDispatcher::OnClosed(int socket_id) { | |
267 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id; | |
268 | |
269 IPCWebSocketStreamHandleBridge* bridge = | |
270 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); | |
271 if (bridge) | |
272 bridge->OnClosed(); | |
273 else | |
274 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; | |
275 } | |
276 | |
277 void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) { | |
278 IPCWebSocketStreamHandleBridge* bridge = | |
279 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); | |
280 if (bridge) | |
281 bridge->OnFailed(error_code, net::ErrorToString(error_code)); | |
282 else | |
283 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; | |
284 } | |
285 | |
286 } // namespace content | |
OLD | NEW |