15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdio.h>
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string.h>
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <sstream>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/instance.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/module.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/net_address.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/network_list.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/network_monitor.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/var.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/var_array.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/var_dictionary.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef WIN32
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#undef PostMessage
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Allow 'this' in initializer list
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma warning(disable : 4355)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NetworkMonitorInstance : public pp::Instance {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit NetworkMonitorInstance(PP_Instance instance)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : pp::Instance(instance),
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback_factory_(this),
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        network_monitor_(this) {}
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~NetworkMonitorInstance() {}
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnUpdateNetworkList(int32_t result,
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   pp::NetworkList network_list);
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static std::string GetNetworkStateAsString(PP_NetworkList_State state);
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static std::string GetNetworkTypeAsString(PP_NetworkList_Type type);
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static std::string GetNetAddressAsString(pp::NetAddress address);
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallbackFactory<NetworkMonitorInstance> callback_factory_;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::NetworkMonitor network_monitor_;
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NetworkMonitorInstance::Init(uint32_t argc,
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  const char* argn[],
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  const char* argv[]) {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Start listing for network updates.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32_t result = network_monitor_.UpdateNetworkList(
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallbackWithOutput(
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &NetworkMonitorInstance::OnUpdateNetworkList));
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != PP_OK_COMPLETIONPENDING) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::ostringstream status;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    status << "UpdateNetworkList failed: " << result;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PostMessage(status.str());
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NetworkMonitorInstance::OnUpdateNetworkList(int32_t result,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 pp::NetworkList network_list) {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Send the new network list to JavaScript.
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result < 0) {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::ostringstream status;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    status << "UpdateNetworkList failed: " << result;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PostMessage(status.str());
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::VarArray var_network_list;
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t count = network_list.GetCount();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (uint32_t i = 0; i < count; ++i) {
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::VarDictionary var_network;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("displayName", network_list.GetDisplayName(i));
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("name", network_list.GetName(i));
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("state", GetNetworkStateAsString(network_list.GetState(i)));
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("type", GetNetworkTypeAsString(network_list.GetType(i)));
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("MTU", static_cast<int32_t>(network_list.GetMTU(i)));
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::VarArray var_ip_addresses;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<pp::NetAddress> ip_addresses;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = network_list.GetIpAddresses(i, &ip_addresses);
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result == PP_OK) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (size_t i = 0; i < ip_addresses.size(); ++i) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        var_ip_addresses.Set(i, GetNetAddressAsString(ip_addresses[i]));
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Call to GetIpAddresses failed, just give an empty list.
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network.Set("ipAddresses", var_ip_addresses);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_network_list.Set(i, var_network);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PostMessage(var_network_list);
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string NetworkMonitorInstance::GetNetworkStateAsString(
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_NetworkList_State state) {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (state) {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_STATE_UP:
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "up";
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_STATE_DOWN:
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "down";
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "invalid";
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string NetworkMonitorInstance::GetNetworkTypeAsString(
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_NetworkList_Type type) {
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (type) {
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_TYPE_ETHERNET:
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "ethernet";
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_TYPE_WIFI:
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "wifi";
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_TYPE_CELLULAR:
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "cellular";
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_NETWORKLIST_TYPE_UNKNOWN:
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "unknown";
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "invalid";
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string NetworkMonitorInstance::GetNetAddressAsString(
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::NetAddress address) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool include_port = true;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return address.DescribeAsString(include_port).AsString();
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NetworkMonitorModule : public pp::Module {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NetworkMonitorModule() : pp::Module() {}
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~NetworkMonitorModule() {}
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return new NetworkMonitorInstance(instance);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace pp {
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Module* CreateModule() { return new NetworkMonitorModule(); }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace pp
156