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