pepper_network_manager.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/webrtc/base/socketaddress.h"
16
17namespace remoting {
18
19PepperNetworkManager::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
31PepperNetworkManager::~PepperNetworkManager() {
32  DCHECK(!start_count_);
33}
34
35void 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
45void PepperNetworkManager::StopUpdating() {
46  DCHECK_GT(start_count_, 0);
47  --start_count_;
48}
49
50void 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 rtc::Network.
67  std::vector<rtc::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      rtc::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      rtc::Network* network = new rtc::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
100void PepperNetworkManager::SendNetworksChangedSignal() {
101  SignalNetworksChanged();
102}
103
104}  // namespace remoting
105