1 // Copyright 2015 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 "third_party/blink/renderer/platform/p2p/filtering_network_manager.h"
6 
7 #include <utility>
8 
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "media/base/media_permission.h"
13 #include "third_party/blink/renderer/platform/wtf/functional.h"
14 
15 namespace blink {
16 
FilteringNetworkManager(rtc::NetworkManager * network_manager,media::MediaPermission * media_permission,bool allow_mdns_obfuscation)17 FilteringNetworkManager::FilteringNetworkManager(
18     rtc::NetworkManager* network_manager,
19     media::MediaPermission* media_permission,
20     bool allow_mdns_obfuscation)
21     : network_manager_(network_manager),
22       media_permission_(media_permission),
23       allow_mdns_obfuscation_(allow_mdns_obfuscation) {
24   DETACH_FROM_THREAD(thread_checker_);
25   set_enumeration_permission(ENUMERATION_BLOCKED);
26 
27   // If the feature is not enabled, just return ALLOWED as it's requested.
28   if (!media_permission_) {
29     started_permission_check_ = true;
30     set_enumeration_permission(ENUMERATION_ALLOWED);
31     VLOG(3) << "media_permission is not passed, granting permission";
32     return;
33   }
34 }
35 
~FilteringNetworkManager()36 FilteringNetworkManager::~FilteringNetworkManager() {
37   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
38   // This helps to catch the case if permission never comes back.
39   if (!start_updating_time_.is_null())
40     ReportMetrics(false);
41 }
42 
GetWeakPtr()43 base::WeakPtr<FilteringNetworkManager> FilteringNetworkManager::GetWeakPtr() {
44   return weak_ptr_factory_.GetWeakPtr();
45 }
46 
Initialize()47 void FilteringNetworkManager::Initialize() {
48   rtc::NetworkManagerBase::Initialize();
49   if (media_permission_)
50     CheckPermission();
51 }
52 
StartUpdating()53 void FilteringNetworkManager::StartUpdating() {
54   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
55   DCHECK(started_permission_check_);
56 
57   if (start_updating_time_.is_null()) {
58     start_updating_time_ = base::TimeTicks::Now();
59     network_manager_->SignalNetworksChanged.connect(
60         this, &FilteringNetworkManager::OnNetworksChanged);
61   }
62 
63   // Update |pending_network_update_| and |start_count_| before calling
64   // StartUpdating, in case the update signal is fired synchronously.
65   pending_network_update_ = true;
66   ++start_count_;
67   network_manager_->StartUpdating();
68   // If we have not sent the first update, which implies we have not received
69   // the first network update from the base network manager, we wait until the
70   // base network manager signals a network change for us to populate the
71   // network information in |OnNetworksChanged| and fire the event there.
72   if (sent_first_update_) {
73     FireEventIfStarted();
74   }
75 }
76 
StopUpdating()77 void FilteringNetworkManager::StopUpdating() {
78   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
79   network_manager_->StopUpdating();
80   DCHECK_GT(start_count_, 0);
81   --start_count_;
82 }
83 
GetNetworks(NetworkList * networks) const84 void FilteringNetworkManager::GetNetworks(NetworkList* networks) const {
85   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
86   networks->clear();
87 
88   if (enumeration_permission() == ENUMERATION_ALLOWED)
89     NetworkManagerBase::GetNetworks(networks);
90 
91   VLOG(3) << "GetNetworks() returns " << networks->size() << " networks.";
92 }
93 
GetMdnsResponder() const94 webrtc::MdnsResponderInterface* FilteringNetworkManager::GetMdnsResponder()
95     const {
96   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
97 
98   // mDNS responder is set to null if we have the enumeration permission or the
99   // mDNS obfuscation of IPs is disallowed.
100   if (enumeration_permission() == ENUMERATION_ALLOWED ||
101       !allow_mdns_obfuscation_)
102     return nullptr;
103 
104   return network_manager_->GetMdnsResponder();
105 }
106 
CheckPermission()107 void FilteringNetworkManager::CheckPermission() {
108   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
109   DCHECK(!started_permission_check_);
110 
111   started_permission_check_ = true;
112   pending_permission_checks_ = 2;
113 
114   VLOG(1) << "FilteringNetworkManager checking permission status.";
115   // Request for media permission asynchronously.
116   media_permission_->HasPermission(
117       media::MediaPermission::AUDIO_CAPTURE,
118       WTF::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
119   media_permission_->HasPermission(
120       media::MediaPermission::VIDEO_CAPTURE,
121       WTF::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
122 }
123 
OnPermissionStatus(bool granted)124 void FilteringNetworkManager::OnPermissionStatus(bool granted) {
125   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
126   DCHECK_GT(pending_permission_checks_, 0);
127   VLOG(1) << "FilteringNetworkManager received permission status: "
128           << (granted ? "granted" : "denied");
129   blink::IPPermissionStatus old_status = GetIPPermissionStatus();
130 
131   --pending_permission_checks_;
132 
133   if (granted)
134     set_enumeration_permission(ENUMERATION_ALLOWED);
135 
136   // If the IP permission status changed *and* we have an up-to-date network
137   // list, fire a network change event.
138   if (GetIPPermissionStatus() != old_status && !pending_network_update_)
139     FireEventIfStarted();
140 }
141 
OnNetworksChanged()142 void FilteringNetworkManager::OnNetworksChanged() {
143   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
144   pending_network_update_ = false;
145 
146   // Update the default local addresses.
147   rtc::IPAddress ipv4_default;
148   rtc::IPAddress ipv6_default;
149   network_manager_->GetDefaultLocalAddress(AF_INET, &ipv4_default);
150   network_manager_->GetDefaultLocalAddress(AF_INET6, &ipv6_default);
151   set_default_local_addresses(ipv4_default, ipv6_default);
152 
153   // Copy and merge the networks. Fire a signal if the permission status is
154   // known.
155   NetworkList networks;
156   network_manager_->GetNetworks(&networks);
157   NetworkList copied_networks;
158   copied_networks.reserve(networks.size());
159   for (rtc::Network* network : networks) {
160     auto copied_network = std::make_unique<rtc::Network>(*network);
161     copied_network->set_default_local_address_provider(this);
162     copied_network->set_mdns_responder_provider(this);
163     copied_networks.push_back(copied_network.release());
164   }
165   bool changed;
166   MergeNetworkList(copied_networks, &changed);
167   // We wait until our permission status is known before firing a network
168   // change signal, so that the listener(s) don't miss out on receiving a
169   // full network list.
170   if (changed && GetIPPermissionStatus() != blink::PERMISSION_UNKNOWN)
171     FireEventIfStarted();
172 }
173 
ReportMetrics(bool report_start_latency)174 void FilteringNetworkManager::ReportMetrics(bool report_start_latency) {
175   if (report_start_latency) {
176     blink::ReportTimeToUpdateNetworkList(base::TimeTicks::Now() -
177                                          start_updating_time_);
178   }
179 
180   ReportIPPermissionStatus(GetIPPermissionStatus());
181 }
182 
GetIPPermissionStatus() const183 blink::IPPermissionStatus FilteringNetworkManager::GetIPPermissionStatus()
184     const {
185   if (enumeration_permission() == ENUMERATION_ALLOWED) {
186     return media_permission_ ? blink::PERMISSION_GRANTED_WITH_CHECKING
187                              : blink::PERMISSION_GRANTED_WITHOUT_CHECKING;
188   }
189 
190   if (!pending_permission_checks_ &&
191       enumeration_permission() == ENUMERATION_BLOCKED) {
192     return blink::PERMISSION_DENIED;
193   }
194 
195   return blink::PERMISSION_UNKNOWN;
196 }
197 
FireEventIfStarted()198 void FilteringNetworkManager::FireEventIfStarted() {
199   if (!start_count_)
200     return;
201 
202   if (!sent_first_update_)
203     ReportMetrics(true);
204 
205   // Post a task to avoid reentrancy.
206   //
207   // TODO(crbug.com/787254): Use Frame-based TaskRunner here.
208   base::ThreadTaskRunnerHandle::Get()->PostTask(
209       FROM_HERE, WTF::Bind(&FilteringNetworkManager::SendNetworksChangedSignal,
210                            GetWeakPtr()));
211 
212   sent_first_update_ = true;
213 }
214 
SendNetworksChangedSignal()215 void FilteringNetworkManager::SendNetworksChangedSignal() {
216   SignalNetworksChanged();
217 }
218 
219 }  // namespace blink
220