Added unit test for DevTools' ephemeral port support.
[chromium-blink-merge.git] / content / child / socket_stream_dispatcher.cc
blob017a116466af111f4547056984bd2ea8e8ca3dc8
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.
5 #include "content/child/socket_stream_dispatcher.h"
7 #include <vector>
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"
26 namespace content {
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) {}
36 // Returns the handle having given id or NULL if there is no such handle.
37 static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
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;
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);
51 private:
52 virtual ~IPCWebSocketStreamHandleBridge();
54 // The ID for this bridge and corresponding SocketStream instance in the
55 // browser process.
56 int socket_id_;
58 blink::WebSocketStreamHandle* handle_;
59 WebSocketStreamHandleDelegate* delegate_;
61 // Map from ID to bridge instance.
62 static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
63 all_bridges;
66 // static
67 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
68 IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
70 /* static */
71 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
72 int id) {
73 return all_bridges.Get().Lookup(id);
76 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
77 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
78 << ") Destructor";
80 if (socket_id_ == kNoSocketId)
81 return;
83 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
84 socket_id_ = kNoSocketId;
87 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
88 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
90 DCHECK_EQ(socket_id_, kNoSocketId);
91 if (delegate_)
92 delegate_->WillOpenStream(handle_, url);
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.
110 bool IPCWebSocketStreamHandleBridge::Send(const std::vector<char>& data) {
111 DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
112 << " bytes)";
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;
121 void IPCWebSocketStreamHandleBridge::Close() {
122 DVLOG(1) << "Bridge #" << socket_id_ << " Close";
124 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
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 << ")";
132 if (delegate_)
133 delegate_->DidOpenStream(handle_, max_pending_send_allowed);
136 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
137 DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
138 << " bytes)";
140 if (delegate_)
141 delegate_->DidSendData(handle_, amount_sent);
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());
152 void IPCWebSocketStreamHandleBridge::OnClosed() {
153 DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
155 if (socket_id_ != kNoSocketId) {
156 all_bridges.Get().Remove(socket_id_);
157 socket_id_ = kNoSocketId;
159 if (delegate_)
160 delegate_->DidClose(handle_);
161 delegate_ = NULL;
162 Release();
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));
173 SocketStreamDispatcher::SocketStreamDispatcher() {
176 // static
177 WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
178 blink::WebSocketStreamHandle* handle,
179 WebSocketStreamHandleDelegate* delegate) {
180 return new IPCWebSocketStreamHandleBridge(handle, delegate);
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;
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;
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;
209 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
210 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
211 << " bytes) to socket_id=" << socket_id;
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;
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;
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;
234 void SocketStreamDispatcher::OnClosed(int socket_id) {
235 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
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;
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;
254 } // namespace content