Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / child / socket_stream_dispatcher.cc
blob87f299f0bf38e0e10aea28f908edbab6d9e21074
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/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"
25 namespace content {
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 WebKit::WebSocketStreamHandle* handle,
34 webkit_glue::WebSocketStreamHandleDelegate* delegate)
35 : socket_id_(kNoSocketId),
36 handle_(handle),
37 delegate_(delegate) {}
39 // Returns the handle having given id or NULL if there is no such handle.
40 static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
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;
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);
54 private:
55 virtual ~IPCWebSocketStreamHandleBridge();
57 // The ID for this bridge and corresponding SocketStream instance in the
58 // browser process.
59 int socket_id_;
61 WebKit::WebSocketStreamHandle* handle_;
62 webkit_glue::WebSocketStreamHandleDelegate* delegate_;
64 // Map from ID to bridge instance.
65 static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
66 all_bridges;
69 // static
70 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
71 IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
73 /* static */
74 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
75 int id) {
76 return all_bridges.Get().Lookup(id);
79 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
80 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
81 << ") Destructor";
83 if (socket_id_ == kNoSocketId)
84 return;
86 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
87 socket_id_ = kNoSocketId;
90 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
91 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
93 DCHECK_EQ(socket_id_, kNoSocketId);
94 if (delegate_)
95 delegate_->WillOpenStream(handle_, url);
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.
111 bool IPCWebSocketStreamHandleBridge::Send(const std::vector<char>& data) {
112 DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
113 << " bytes)";
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;
122 void IPCWebSocketStreamHandleBridge::Close() {
123 DVLOG(1) << "Bridge #" << socket_id_ << " Close";
125 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
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 << ")";
133 if (delegate_)
134 delegate_->DidOpenStream(handle_, max_pending_send_allowed);
137 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
138 DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
139 << " bytes)";
141 if (delegate_)
142 delegate_->DidSendData(handle_, amount_sent);
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());
153 void IPCWebSocketStreamHandleBridge::OnClosed() {
154 DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
156 if (socket_id_ != kNoSocketId) {
157 all_bridges.Get().Remove(socket_id_);
158 socket_id_ = kNoSocketId;
160 if (delegate_)
161 delegate_->DidClose(handle_);
162 delegate_ = NULL;
163 Release();
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));
174 SocketStreamDispatcher::SocketStreamDispatcher() {
177 /* static */
178 webkit_glue::WebSocketStreamHandleBridge*
179 SocketStreamDispatcher::CreateBridge(
180 WebKit::WebSocketStreamHandle* handle,
181 webkit_glue::WebSocketStreamHandleDelegate* delegate) {
182 return new IPCWebSocketStreamHandleBridge(handle, delegate);
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;
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;
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;
211 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
212 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
213 << " bytes) to socket_id=" << socket_id;
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;
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;
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;
236 void SocketStreamDispatcher::OnClosed(int socket_id) {
237 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
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;
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;
256 } // namespace content