Ignore non-active fullscreen windows for shelf state.
[chromium-blink-merge.git] / content / browser / renderer_host / p2p / socket_dispatcher_host.cc
blob1608ae0f40ce3fb71551631b48e3ea1182a5cad6
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/browser/renderer_host/p2p/socket_dispatcher_host.h"
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "content/browser/renderer_host/p2p/socket_host.h"
10 #include "content/common/p2p_messages.h"
11 #include "content/public/browser/resource_context.h"
12 #include "net/base/address_list.h"
13 #include "net/base/completion_callback.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_log.h"
16 #include "net/base/sys_addrinfo.h"
17 #include "net/dns/single_request_host_resolver.h"
18 #include "net/url_request/url_request_context_getter.h"
20 using content::BrowserMessageFilter;
21 using content::BrowserThread;
23 namespace content {
25 const size_t kMaximumPacketSize = 32768;
27 class P2PSocketDispatcherHost::DnsRequest {
28 public:
29 typedef base::Callback<void(const net::IPAddressNumber&)> DoneCallback;
31 DnsRequest(int32 request_id, net::HostResolver* host_resolver)
32 : request_id_(request_id),
33 resolver_(host_resolver) {
36 void Resolve(const std::string& host_name,
37 const DoneCallback& done_callback) {
38 DCHECK(!done_callback.is_null());
40 host_name_ = host_name;
41 done_callback_ = done_callback;
43 // Return an error if it's an empty string.
44 if (host_name_.empty()) {
45 done_callback_.Run(net::IPAddressNumber());
46 return;
49 // Add period at the end to make sure that we only resolve
50 // fully-qualified names.
51 if (host_name_.at(host_name_.size() - 1) != '.')
52 host_name_ = host_name_ + '.';
54 net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
55 int result = resolver_.Resolve(
56 info,
57 net::DEFAULT_PRIORITY,
58 &addresses_,
59 base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone,
60 base::Unretained(this)),
61 net::BoundNetLog());
62 if (result != net::ERR_IO_PENDING)
63 OnDone(result);
66 int32 request_id() { return request_id_; }
68 private:
69 void OnDone(int result) {
70 if (result != net::OK) {
71 LOG(ERROR) << "Failed to resolve address for " << host_name_
72 << ", errorcode: " << result;
73 done_callback_.Run(net::IPAddressNumber());
74 return;
77 DCHECK(!addresses_.empty());
78 done_callback_.Run(addresses_.front().address());
81 int32 request_id_;
82 net::AddressList addresses_;
84 std::string host_name_;
85 net::SingleRequestHostResolver resolver_;
87 DoneCallback done_callback_;
90 P2PSocketDispatcherHost::P2PSocketDispatcherHost(
91 content::ResourceContext* resource_context,
92 net::URLRequestContextGetter* url_context)
93 : resource_context_(resource_context),
94 url_context_(url_context),
95 monitoring_networks_(false) {
98 void P2PSocketDispatcherHost::OnChannelClosing() {
99 // Since the IPC channel is gone, close pending connections.
100 STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end());
101 sockets_.clear();
103 STLDeleteContainerPointers(dns_requests_.begin(), dns_requests_.end());
104 dns_requests_.clear();
106 if (monitoring_networks_) {
107 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
108 monitoring_networks_ = false;
112 void P2PSocketDispatcherHost::OnDestruct() const {
113 BrowserThread::DeleteOnIOThread::Destruct(this);
116 bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message,
117 bool* message_was_ok) {
118 bool handled = true;
119 IPC_BEGIN_MESSAGE_MAP_EX(P2PSocketDispatcherHost, message, *message_was_ok)
120 IPC_MESSAGE_HANDLER(P2PHostMsg_StartNetworkNotifications,
121 OnStartNetworkNotifications)
122 IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications,
123 OnStopNetworkNotifications)
124 IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress)
125 IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket)
126 IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection,
127 OnAcceptIncomingTcpConnection)
128 IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend)
129 IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket)
130 IPC_MESSAGE_UNHANDLED(handled = false)
131 IPC_END_MESSAGE_MAP_EX()
132 return handled;
135 void P2PSocketDispatcherHost::OnIPAddressChanged() {
136 // Notify the renderer about changes to list of network interfaces.
137 BrowserThread::PostTask(
138 BrowserThread::FILE, FROM_HERE, base::Bind(
139 &P2PSocketDispatcherHost::DoGetNetworkList, this));
142 P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {
143 DCHECK(sockets_.empty());
144 DCHECK(dns_requests_.empty());
146 if (monitoring_networks_)
147 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
150 P2PSocketHost* P2PSocketDispatcherHost::LookupSocket(int socket_id) {
151 SocketsMap::iterator it = sockets_.find(socket_id);
152 return (it == sockets_.end()) ? NULL : it->second;
155 void P2PSocketDispatcherHost::OnStartNetworkNotifications(
156 const IPC::Message& msg) {
157 if (!monitoring_networks_) {
158 net::NetworkChangeNotifier::AddIPAddressObserver(this);
159 monitoring_networks_ = true;
162 BrowserThread::PostTask(
163 BrowserThread::FILE, FROM_HERE, base::Bind(
164 &P2PSocketDispatcherHost::DoGetNetworkList, this));
167 void P2PSocketDispatcherHost::OnStopNetworkNotifications(
168 const IPC::Message& msg) {
169 if (monitoring_networks_) {
170 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
171 monitoring_networks_ = false;
175 void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name,
176 int32 request_id) {
177 DnsRequest* request = new DnsRequest(request_id,
178 resource_context_->GetHostResolver());
179 dns_requests_.insert(request);
180 request->Resolve(host_name, base::Bind(
181 &P2PSocketDispatcherHost::OnAddressResolved,
182 base::Unretained(this), request));
185 void P2PSocketDispatcherHost::OnCreateSocket(
186 P2PSocketType type, int socket_id,
187 const net::IPEndPoint& local_address,
188 const net::IPEndPoint& remote_address) {
189 if (LookupSocket(socket_id)) {
190 LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket "
191 "that already exists.";
192 return;
195 scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create(
196 this, socket_id, type, url_context_.get(), &throttler_));
198 if (!socket) {
199 Send(new P2PMsg_OnError(socket_id));
200 return;
203 if (socket->Init(local_address, remote_address)) {
204 sockets_[socket_id] = socket.release();
208 void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection(
209 int listen_socket_id, const net::IPEndPoint& remote_address,
210 int connected_socket_id) {
211 P2PSocketHost* socket = LookupSocket(listen_socket_id);
212 if (!socket) {
213 LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection "
214 "for invalid socket_id.";
215 return;
217 P2PSocketHost* accepted_connection =
218 socket->AcceptIncomingTcpConnection(remote_address, connected_socket_id);
219 if (accepted_connection) {
220 sockets_[connected_socket_id] = accepted_connection;
224 void P2PSocketDispatcherHost::OnSend(int socket_id,
225 const net::IPEndPoint& socket_address,
226 const std::vector<char>& data,
227 net::DiffServCodePoint dscp,
228 uint64 packet_id) {
229 P2PSocketHost* socket = LookupSocket(socket_id);
230 if (!socket) {
231 LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id.";
232 return;
235 if (data.size() > kMaximumPacketSize) {
236 LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: "
237 << data.size();
238 Send(new P2PMsg_OnError(socket_id));
239 delete socket;
240 sockets_.erase(socket_id);
241 return;
244 socket->Send(socket_address, data, dscp, packet_id);
247 void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) {
248 SocketsMap::iterator it = sockets_.find(socket_id);
249 if (it != sockets_.end()) {
250 delete it->second;
251 sockets_.erase(it);
252 } else {
253 LOG(ERROR) << "Received P2PHostMsg_DestroySocket for invalid socket_id.";
257 void P2PSocketDispatcherHost::DoGetNetworkList() {
258 net::NetworkInterfaceList list;
259 net::GetNetworkList(&list);
260 BrowserThread::PostTask(
261 BrowserThread::IO, FROM_HERE, base::Bind(
262 &P2PSocketDispatcherHost::SendNetworkList, this, list));
265 void P2PSocketDispatcherHost::SendNetworkList(
266 const net::NetworkInterfaceList& list) {
267 Send(new P2PMsg_NetworkListChanged(list));
270 void P2PSocketDispatcherHost::OnAddressResolved(
271 DnsRequest* request,
272 const net::IPAddressNumber& result) {
273 Send(new P2PMsg_GetHostAddressResult(request->request_id(), result));
275 dns_requests_.erase(request);
276 delete request;
279 } // namespace content