1// Copyright 2013 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 <stdio.h>
6#include <string.h>
7#include <sstream>
8
9#include "ppapi/cpp/instance.h"
10#include "ppapi/cpp/module.h"
11#include "ppapi/cpp/net_address.h"
12#include "ppapi/cpp/network_list.h"
13#include "ppapi/cpp/network_monitor.h"
14#include "ppapi/cpp/var.h"
15#include "ppapi/cpp/var_array.h"
16#include "ppapi/cpp/var_dictionary.h"
17#include "ppapi/utility/completion_callback_factory.h"
18
19#ifdef WIN32
20#undef PostMessage
21// Allow 'this' in initializer list
22#pragma warning(disable : 4355)
23#endif
24
25class NetworkMonitorInstance : public pp::Instance {
26 public:
27  explicit NetworkMonitorInstance(PP_Instance instance)
28      : pp::Instance(instance),
29        callback_factory_(this),
30        network_monitor_(this) {}
31
32  virtual ~NetworkMonitorInstance() {}
33  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
34
35 private:
36  virtual void OnUpdateNetworkList(int32_t result,
37                                   pp::NetworkList network_list);
38  static std::string GetNetworkStateAsString(PP_NetworkList_State state);
39  static std::string GetNetworkTypeAsString(PP_NetworkList_Type type);
40  static std::string GetNetAddressAsString(pp::NetAddress address);
41
42  pp::CompletionCallbackFactory<NetworkMonitorInstance> callback_factory_;
43  pp::NetworkMonitor network_monitor_;
44};
45
46bool NetworkMonitorInstance::Init(uint32_t argc,
47                                  const char* argn[],
48                                  const char* argv[]) {
49  // Start listing for network updates.
50  int32_t result = network_monitor_.UpdateNetworkList(
51      callback_factory_.NewCallbackWithOutput(
52          &NetworkMonitorInstance::OnUpdateNetworkList));
53  if (result != PP_OK_COMPLETIONPENDING) {
54    std::ostringstream status;
55    status << "UpdateNetworkList failed: " << result;
56    PostMessage(status.str());
57  }
58
59  return true;
60}
61
62void NetworkMonitorInstance::OnUpdateNetworkList(int32_t result,
63                                                 pp::NetworkList network_list) {
64  // Send the new network list to JavaScript.
65  if (result < 0) {
66    std::ostringstream status;
67    status << "UpdateNetworkList failed: " << result;
68    PostMessage(status.str());
69    return;
70  }
71
72  pp::VarArray var_network_list;
73  uint32_t count = network_list.GetCount();
74  for (uint32_t i = 0; i < count; ++i) {
75    pp::VarDictionary var_network;
76    var_network.Set("displayName", network_list.GetDisplayName(i));
77    var_network.Set("name", network_list.GetName(i));
78    var_network.Set("state", GetNetworkStateAsString(network_list.GetState(i)));
79    var_network.Set("type", GetNetworkTypeAsString(network_list.GetType(i)));
80    var_network.Set("MTU", static_cast<int32_t>(network_list.GetMTU(i)));
81
82    pp::VarArray var_ip_addresses;
83    std::vector<pp::NetAddress> ip_addresses;
84    result = network_list.GetIpAddresses(i, &ip_addresses);
85    if (result == PP_OK) {
86      for (size_t i = 0; i < ip_addresses.size(); ++i) {
87        var_ip_addresses.Set(i, GetNetAddressAsString(ip_addresses[i]));
88      }
89    } else {
90      // Call to GetIpAddresses failed, just give an empty list.
91    }
92
93    var_network.Set("ipAddresses", var_ip_addresses);
94    var_network_list.Set(i, var_network);
95  }
96
97  PostMessage(var_network_list);
98}
99
100// static
101std::string NetworkMonitorInstance::GetNetworkStateAsString(
102    PP_NetworkList_State state) {
103  switch (state) {
104    case PP_NETWORKLIST_STATE_UP:
105      return "up";
106
107    case PP_NETWORKLIST_STATE_DOWN:
108      return "down";
109
110    default:
111      return "invalid";
112  }
113}
114
115// static
116std::string NetworkMonitorInstance::GetNetworkTypeAsString(
117    PP_NetworkList_Type type) {
118  switch (type) {
119    case PP_NETWORKLIST_TYPE_ETHERNET:
120      return "ethernet";
121
122    case PP_NETWORKLIST_TYPE_WIFI:
123      return "wifi";
124
125    case PP_NETWORKLIST_TYPE_CELLULAR:
126      return "cellular";
127
128    case PP_NETWORKLIST_TYPE_UNKNOWN:
129      return "unknown";
130
131    default:
132      return "invalid";
133  }
134}
135
136// static
137std::string NetworkMonitorInstance::GetNetAddressAsString(
138    pp::NetAddress address) {
139  bool include_port = true;
140  return address.DescribeAsString(include_port).AsString();
141}
142
143class NetworkMonitorModule : public pp::Module {
144 public:
145  NetworkMonitorModule() : pp::Module() {}
146  virtual ~NetworkMonitorModule() {}
147
148  virtual pp::Instance* CreateInstance(PP_Instance instance) {
149    return new NetworkMonitorInstance(instance);
150  }
151};
152
153namespace pp {
154Module* CreateModule() { return new NetworkMonitorModule(); }
155}  // namespace pp
156