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/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 void Connect(const GURL& url) override; | |
42 bool Send(const std::vector<char>& data) override; | |
43 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 ~IPCWebSocketStreamHandleBridge() override; | |
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 | |
OLD | NEW |