Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / websocket_dispatcher_host.cc
blobd49199a7cb8f44e08ea03435a58905f63b618fc5
1 // Copyright 2013 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/browser/renderer_host/websocket_dispatcher_host.h"
7 #include <string>
8 #include <vector>
10 #include "base/callback.h"
11 #include "base/logging.h"
12 #include "base/stl_util.h"
13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/renderer_host/websocket_host.h"
15 #include "content/common/websocket_messages.h"
17 namespace content {
19 namespace {
21 // Many methods defined in this file return a WebSocketHostState enum
22 // value. Make WebSocketHostState visible at file scope so it doesn't have to be
23 // fully-qualified every time.
24 typedef WebSocketDispatcherHost::WebSocketHostState WebSocketHostState;
26 } // namespace
28 WebSocketDispatcherHost::WebSocketDispatcherHost(
29 int process_id,
30 const GetRequestContextCallback& get_context_callback)
31 : BrowserMessageFilter(WebSocketMsgStart),
32 process_id_(process_id),
33 get_context_callback_(get_context_callback),
34 websocket_host_factory_(
35 base::Bind(&WebSocketDispatcherHost::CreateWebSocketHost,
36 base::Unretained(this))) {}
38 WebSocketDispatcherHost::WebSocketDispatcherHost(
39 int process_id,
40 const GetRequestContextCallback& get_context_callback,
41 const WebSocketHostFactory& websocket_host_factory)
42 : BrowserMessageFilter(WebSocketMsgStart),
43 process_id_(process_id),
44 get_context_callback_(get_context_callback),
45 websocket_host_factory_(websocket_host_factory) {}
47 WebSocketHost* WebSocketDispatcherHost::CreateWebSocketHost(int routing_id) {
48 return new WebSocketHost(routing_id, this, get_context_callback_.Run());
51 bool WebSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
52 switch (message.type()) {
53 case WebSocketHostMsg_AddChannelRequest::ID:
54 case WebSocketMsg_SendFrame::ID:
55 case WebSocketMsg_FlowControl::ID:
56 case WebSocketMsg_DropChannel::ID:
57 break;
59 default:
60 // Every message that has not been handled by a previous filter passes
61 // through here, so it is good to pass them on as efficiently as possible.
62 return false;
65 int routing_id = message.routing_id();
66 WebSocketHost* host = GetHost(routing_id);
67 if (message.type() == WebSocketHostMsg_AddChannelRequest::ID) {
68 if (host) {
69 DVLOG(1) << "routing_id=" << routing_id << " already in use.";
70 // The websocket multiplexing spec says to should drop the physical
71 // connection in this case, but there isn't a real physical connection
72 // to the renderer, and killing the renderer for this would seem to be a
73 // little extreme. So for now just ignore the bogus request.
74 return true; // We handled the message (by ignoring it).
76 host = websocket_host_factory_.Run(routing_id);
77 hosts_.insert(WebSocketHostTable::value_type(routing_id, host));
79 if (!host) {
80 DVLOG(1) << "Received invalid routing ID " << routing_id
81 << " from renderer.";
82 return true; // We handled the message (by ignoring it).
84 return host->OnMessageReceived(message);
87 bool WebSocketDispatcherHost::CanReadRawCookies() const {
88 ChildProcessSecurityPolicyImpl* policy =
89 ChildProcessSecurityPolicyImpl::GetInstance();
90 return policy->CanReadRawCookies(process_id_);
93 WebSocketHost* WebSocketDispatcherHost::GetHost(int routing_id) const {
94 WebSocketHostTable::const_iterator it = hosts_.find(routing_id);
95 return it == hosts_.end() ? NULL : it->second;
98 WebSocketHostState WebSocketDispatcherHost::SendOrDrop(IPC::Message* message) {
99 const uint32 message_type = message->type();
100 const int32 message_routing_id = message->routing_id();
101 if (!Send(message)) {
102 message = NULL;
103 DVLOG(1) << "Sending of message type " << message_type
104 << " failed. Dropping channel.";
105 DeleteWebSocketHost(message_routing_id);
106 return WEBSOCKET_HOST_DELETED;
108 return WEBSOCKET_HOST_ALIVE;
111 WebSocketHostState WebSocketDispatcherHost::SendAddChannelResponse(
112 int routing_id,
113 bool fail,
114 const std::string& selected_protocol,
115 const std::string& extensions) {
116 if (SendOrDrop(new WebSocketMsg_AddChannelResponse(
117 routing_id, fail, selected_protocol, extensions)) ==
118 WEBSOCKET_HOST_DELETED)
119 return WEBSOCKET_HOST_DELETED;
120 if (fail) {
121 DeleteWebSocketHost(routing_id);
122 return WEBSOCKET_HOST_DELETED;
124 return WEBSOCKET_HOST_ALIVE;
127 WebSocketHostState WebSocketDispatcherHost::SendFrame(
128 int routing_id,
129 bool fin,
130 WebSocketMessageType type,
131 const std::vector<char>& data) {
132 return SendOrDrop(new WebSocketMsg_SendFrame(routing_id, fin, type, data));
135 WebSocketHostState WebSocketDispatcherHost::SendFlowControl(int routing_id,
136 int64 quota) {
137 return SendOrDrop(new WebSocketMsg_FlowControl(routing_id, quota));
140 WebSocketHostState WebSocketDispatcherHost::NotifyClosingHandshake(
141 int routing_id) {
142 return SendOrDrop(new WebSocketMsg_NotifyClosing(routing_id));
145 WebSocketHostState WebSocketDispatcherHost::NotifyStartOpeningHandshake(
146 int routing_id, const WebSocketHandshakeRequest& request) {
147 return SendOrDrop(new WebSocketMsg_NotifyStartOpeningHandshake(
148 routing_id, request));
151 WebSocketHostState WebSocketDispatcherHost::NotifyFinishOpeningHandshake(
152 int routing_id, const WebSocketHandshakeResponse& response) {
153 return SendOrDrop(new WebSocketMsg_NotifyFinishOpeningHandshake(
154 routing_id, response));
157 WebSocketHostState WebSocketDispatcherHost::NotifyFailure(
158 int routing_id,
159 const std::string& message) {
160 if (SendOrDrop(new WebSocketMsg_NotifyFailure(
161 routing_id, message)) == WEBSOCKET_HOST_DELETED) {
162 return WEBSOCKET_HOST_DELETED;
164 DeleteWebSocketHost(routing_id);
165 return WEBSOCKET_HOST_DELETED;
168 WebSocketHostState WebSocketDispatcherHost::DoDropChannel(
169 int routing_id,
170 bool was_clean,
171 uint16 code,
172 const std::string& reason) {
173 if (SendOrDrop(
174 new WebSocketMsg_DropChannel(routing_id, was_clean, code, reason)) ==
175 WEBSOCKET_HOST_DELETED)
176 return WEBSOCKET_HOST_DELETED;
177 DeleteWebSocketHost(routing_id);
178 return WEBSOCKET_HOST_DELETED;
181 WebSocketDispatcherHost::~WebSocketDispatcherHost() {
182 std::vector<WebSocketHost*> hosts;
183 for (base::hash_map<int, WebSocketHost*>::const_iterator i = hosts_.begin();
184 i != hosts_.end(); ++i) {
185 // In order to avoid changing the container while iterating, we copy
186 // the hosts.
187 hosts.push_back(i->second);
190 for (size_t i = 0; i < hosts.size(); ++i) {
191 // Note that some calls to GoAway could fail. In that case hosts[i] will be
192 // deleted and removed from |hosts_| in |DoDropChannel|.
193 hosts[i]->GoAway();
194 hosts[i] = NULL;
197 STLDeleteContainerPairSecondPointers(hosts_.begin(), hosts_.end());
200 void WebSocketDispatcherHost::DeleteWebSocketHost(int routing_id) {
201 WebSocketHostTable::iterator it = hosts_.find(routing_id);
202 DCHECK(it != hosts_.end());
203 delete it->second;
204 hosts_.erase(it);
207 } // namespace content