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 "remoting/client/plugin/pepper_network_manager.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/single_thread_task_runner.h" 10 #include "base/thread_task_runner_handle.h" 11 #include "ppapi/cpp/module.h" 12 #include "ppapi/cpp/net_address.h" 13 #include "ppapi/cpp/network_list.h" 14 #include "remoting/client/plugin/pepper_util.h" 15 #include "third_party/libjingle/source/talk/base/socketaddress.h" 16 17 namespace remoting { 18 19 PepperNetworkManager::PepperNetworkManager(const pp::InstanceHandle& instance) 20 : monitor_(instance), 21 start_count_(0), 22 network_list_received_(false), 23 callback_factory_(this), 24 weak_factory_(this) { 25 pp::CompletionCallbackWithOutput<pp::NetworkList> callback = 26 callback_factory_.NewCallbackWithOutput( 27 &PepperNetworkManager::OnNetworkList); 28 monitor_.UpdateNetworkList(callback); 29 } 30 31 PepperNetworkManager::~PepperNetworkManager() { 32 DCHECK(!start_count_); 33 } 34 35 void PepperNetworkManager::StartUpdating() { 36 if (network_list_received_) { 37 // Post a task to avoid reentrancy. 38 base::ThreadTaskRunnerHandle::Get()->PostTask( 39 FROM_HERE, base::Bind(&PepperNetworkManager::SendNetworksChangedSignal, 40 weak_factory_.GetWeakPtr())); 41 } 42 ++start_count_; 43 } 44 45 void PepperNetworkManager::StopUpdating() { 46 DCHECK_GT(start_count_, 0); 47 --start_count_; 48 } 49 50 void PepperNetworkManager::OnNetworkList(int32_t result, 51 const pp::NetworkList& list) { 52 if (result != PP_OK) { 53 SignalError(); 54 return; 55 } 56 DCHECK(!list.is_null()); 57 58 network_list_received_ = true; 59 60 // Request for the next update. 61 pp::CompletionCallbackWithOutput<pp::NetworkList> callback = 62 callback_factory_.NewCallbackWithOutput( 63 &PepperNetworkManager::OnNetworkList); 64 monitor_.UpdateNetworkList(callback); 65 66 // Convert the networks to talk_base::Network. 67 std::vector<talk_base::Network*> networks; 68 size_t count = list.GetCount(); 69 for (size_t i = 0; i < count; i++) { 70 std::vector<pp::NetAddress> addresses; 71 list.GetIpAddresses(i, &addresses); 72 73 if (addresses.size() == 0) 74 continue; 75 76 for (size_t i = 0; i < addresses.size(); ++i) { 77 talk_base::SocketAddress address; 78 PpNetAddressToSocketAddress(addresses[i], &address); 79 80 if (address.family() == AF_INET6 && IPIsSiteLocal(address.ipaddr())) { 81 // Link-local IPv6 addresses can't be bound via the current PPAPI 82 // Bind() interface as designed (see crbug.com/384854); trying to do so 83 // would fail. 84 continue; 85 } 86 87 talk_base::Network* network = new talk_base::Network( 88 list.GetName(i), list.GetDisplayName(i), address.ipaddr(), 0); 89 network->AddIP(address.ipaddr()); 90 networks.push_back(network); 91 } 92 } 93 94 bool changed = false; 95 MergeNetworkList(networks, &changed); 96 if (changed) 97 SignalNetworksChanged(); 98 } 99 100 void PepperNetworkManager::SendNetworksChangedSignal() { 101 SignalNetworksChanged(); 102 } 103 104 } // namespace remoting 105