Home | History | Annotate | Download | only in plugin
      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/private/network_list_private.h"
     13 #include "ppapi/cpp/private/net_address_private.h"
     14 
     15 namespace remoting {
     16 
     17 PepperNetworkManager::PepperNetworkManager(const pp::InstanceHandle& instance)
     18     : monitor_(instance, &PepperNetworkManager::OnNetworkListCallbackHandler,
     19                this),
     20       start_count_(0),
     21       network_list_received_(false),
     22       weak_factory_(this) {
     23 }
     24 
     25 PepperNetworkManager::~PepperNetworkManager() {
     26   DCHECK(!start_count_);
     27 }
     28 
     29 void PepperNetworkManager::StartUpdating() {
     30   if (network_list_received_) {
     31     // Post a task to avoid reentrancy.
     32     base::ThreadTaskRunnerHandle::Get()->PostTask(
     33         FROM_HERE, base::Bind(&PepperNetworkManager::SendNetworksChangedSignal,
     34                               weak_factory_.GetWeakPtr()));
     35   }
     36   ++start_count_;
     37 }
     38 
     39 void PepperNetworkManager::StopUpdating() {
     40   DCHECK_GT(start_count_, 0);
     41   --start_count_;
     42 }
     43 
     44 // static
     45 void PepperNetworkManager::OnNetworkListCallbackHandler(
     46     void* user_data,
     47     PP_Resource list_resource) {
     48   PepperNetworkManager* object = static_cast<PepperNetworkManager*>(user_data);
     49   pp::NetworkListPrivate list(pp::PASS_REF, list_resource);
     50   object->OnNetworkList(list);
     51 }
     52 
     53 void PepperNetworkManager::OnNetworkList(const pp::NetworkListPrivate& list) {
     54   network_list_received_ = true;
     55 
     56   std::vector<talk_base::Network*> networks;
     57   size_t count = list.GetCount();
     58   for (size_t i = 0; i < count; i++) {
     59     std::vector<PP_NetAddress_Private> addresses;
     60     list.GetIpAddresses(i, &addresses);
     61 
     62     if (addresses.size() == 0)
     63       continue;
     64 
     65     char address_bytes[sizeof(in6_addr)];
     66     if (!pp::NetAddressPrivate::GetAddress(
     67             addresses[0], &address_bytes, sizeof(address_bytes))) {
     68       LOG(ERROR) << "Failed to get address for network interface.";
     69       continue;
     70     }
     71 
     72     int prefix_length;
     73 
     74     // TODO(sergeyu): Copy all addresses, not only the first one.
     75     talk_base::IPAddress address;
     76     switch (pp::NetAddressPrivate::GetFamily(addresses[0])) {
     77       case PP_NETADDRESSFAMILY_PRIVATE_IPV4: {
     78         in_addr* address_ipv4 = reinterpret_cast<in_addr*>(address_bytes);
     79         address = talk_base::IPAddress(*address_ipv4);
     80         prefix_length = sizeof(in_addr) * 8;
     81         break;
     82       }
     83 
     84       case PP_NETADDRESSFAMILY_PRIVATE_IPV6: {
     85         in6_addr* address_ipv6 = reinterpret_cast<in6_addr*>(address_bytes);
     86         address = talk_base::IPAddress(*address_ipv6);
     87         prefix_length = sizeof(in6_addr) * 8;
     88         break;
     89       }
     90 
     91       default:
     92         LOG(WARNING) << "Skipping address with unknown family: "
     93                      << pp::NetAddressPrivate::GetFamily(addresses[0]);
     94         continue;
     95     }
     96 
     97     talk_base::Network* network = new talk_base::Network(
     98         list.GetName(i), list.GetDisplayName(i), address, prefix_length);
     99     network->AddIP(address);
    100     networks.push_back(network);
    101   }
    102 
    103   bool changed = false;
    104   MergeNetworkList(networks, &changed);
    105   if (changed)
    106     SignalNetworksChanged();
    107 }
    108 
    109 void PepperNetworkManager::SendNetworksChangedSignal() {
    110   SignalNetworksChanged();
    111 }
    112 
    113 }  // namespace remoting
    114