Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / renderer / p2p / ipc_network_manager.cc
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/renderer/p2p/ipc_network_manager.h"
6 #include <string>
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/metrics/histogram.h"
10 #include "base/sys_byteorder.h"
11 #include "content/public/common/content_switches.h"
12 #include "net/base/net_util.h"
13
14 namespace content {
15
16 namespace {
17
18 rtc::AdapterType ConvertConnectionTypeToAdapterType(
19     net::NetworkChangeNotifier::ConnectionType type) {
20   switch (type) {
21     case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
22         return rtc::ADAPTER_TYPE_UNKNOWN;
23     case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
24         return rtc::ADAPTER_TYPE_ETHERNET;
25     case net::NetworkChangeNotifier::CONNECTION_WIFI:
26         return rtc::ADAPTER_TYPE_WIFI;
27     case net::NetworkChangeNotifier::CONNECTION_2G:
28     case net::NetworkChangeNotifier::CONNECTION_3G:
29     case net::NetworkChangeNotifier::CONNECTION_4G:
30         return rtc::ADAPTER_TYPE_CELLULAR;
31     default:
32         return rtc::ADAPTER_TYPE_UNKNOWN;
33   }
34 }
35
36 }  // namespace
37
38 IpcNetworkManager::IpcNetworkManager(NetworkListManager* network_list_manager)
39     : network_list_manager_(network_list_manager),
40       start_count_(0),
41       network_list_received_(false),
42       weak_factory_(this) {
43   network_list_manager_->AddNetworkListObserver(this);
44 }
45
46 IpcNetworkManager::~IpcNetworkManager() {
47   DCHECK(!start_count_);
48   network_list_manager_->RemoveNetworkListObserver(this);
49 }
50
51 void IpcNetworkManager::StartUpdating() {
52   if (network_list_received_) {
53     // Post a task to avoid reentrancy.
54     base::MessageLoop::current()->PostTask(
55         FROM_HERE,
56         base::Bind(&IpcNetworkManager::SendNetworksChangedSignal,
57                    weak_factory_.GetWeakPtr()));
58   }
59   ++start_count_;
60 }
61
62 void IpcNetworkManager::StopUpdating() {
63   DCHECK_GT(start_count_, 0);
64   --start_count_;
65 }
66
67 void IpcNetworkManager::OnNetworkListChanged(
68     const net::NetworkInterfaceList& list) {
69
70   // Update flag if network list received for the first time.
71   if (!network_list_received_)
72     network_list_received_ = true;
73
74   // rtc::Network uses these prefix_length to compare network
75   // interfaces discovered.
76   std::vector<rtc::Network*> networks;
77   int ipv4_interfaces = 0;
78   int ipv6_interfaces = 0;
79   for (net::NetworkInterfaceList::const_iterator it = list.begin();
80        it != list.end(); it++) {
81     if (it->address.size() == net::kIPv4AddressSize) {
82       uint32 address;
83       memcpy(&address, &it->address[0], sizeof(uint32));
84       address = rtc::NetworkToHost32(address);
85       rtc::IPAddress prefix =
86           rtc::TruncateIP(rtc::IPAddress(address), it->network_prefix);
87       rtc::Network* network =
88           new rtc::Network(it->name,
89                            it->name,
90                            prefix,
91                            it->network_prefix,
92                            ConvertConnectionTypeToAdapterType(it->type));
93       network->AddIP(rtc::IPAddress(address));
94       networks.push_back(network);
95       ++ipv4_interfaces;
96     } else if (it->address.size() == net::kIPv6AddressSize) {
97       in6_addr address;
98       memcpy(&address, &it->address[0], sizeof(in6_addr));
99       rtc::IPAddress ip6_addr(address);
100       if (!rtc::IPIsPrivate(ip6_addr)) {
101         rtc::IPAddress prefix =
102             rtc::TruncateIP(rtc::IPAddress(ip6_addr), it->network_prefix);
103         rtc::Network* network =
104             new rtc::Network(it->name,
105                              it->name,
106                              prefix,
107                              it->network_prefix,
108                              ConvertConnectionTypeToAdapterType(it->type));
109         network->AddIP(ip6_addr);
110         networks.push_back(network);
111         ++ipv6_interfaces;
112       }
113     }
114   }
115
116
117   // Send interface counts to UMA.
118   UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
119                            ipv4_interfaces);
120   UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
121                            ipv6_interfaces);
122
123   if (CommandLine::ForCurrentProcess()->HasSwitch(
124       switches::kAllowLoopbackInPeerConnection)) {
125     std::string name_v4("loopback_ipv4");
126     rtc::IPAddress ip_address_v4(INADDR_LOOPBACK);
127     rtc::Network* network_v4 = new rtc::Network(
128         name_v4, name_v4, ip_address_v4, 32, rtc::ADAPTER_TYPE_UNKNOWN);
129     network_v4->AddIP(ip_address_v4);
130     networks.push_back(network_v4);
131
132     std::string name_v6("loopback_ipv6");
133     rtc::IPAddress ip_address_v6(in6addr_loopback);
134     rtc::Network* network_v6 = new rtc::Network(
135         name_v6, name_v6, ip_address_v6, 64, rtc::ADAPTER_TYPE_UNKNOWN);
136     network_v6->AddIP(ip_address_v6);
137     networks.push_back(network_v6);
138   }
139
140   bool changed = false;
141   MergeNetworkList(networks, &changed);
142   if (changed)
143     SignalNetworksChanged();
144 }
145
146 void IpcNetworkManager::SendNetworksChangedSignal() {
147   SignalNetworksChanged();
148 }
149
150 }  // namespace content