summaryrefslogtreecommitdiffstats
path: root/dom/network
diff options
context:
space:
mode:
Diffstat (limited to 'dom/network')
-rw-r--r--dom/network/EthernetManager.js655
-rw-r--r--dom/network/EthernetManager.manifest2
-rw-r--r--dom/network/NetUtils.cpp200
-rw-r--r--dom/network/NetUtils.h75
-rw-r--r--dom/network/NetworkStatsDB.jsm1285
-rw-r--r--dom/network/NetworkStatsManager.js388
-rw-r--r--dom/network/NetworkStatsManager.manifest14
-rw-r--r--dom/network/NetworkStatsService.jsm1171
-rw-r--r--dom/network/NetworkStatsServiceProxy.js90
-rw-r--r--dom/network/NetworkStatsServiceProxy.manifest2
-rw-r--r--dom/network/interfaces/moz.build6
-rw-r--r--dom/network/interfaces/nsIEthernetManager.idl137
-rw-r--r--dom/network/interfaces/nsINetworkStatsServiceProxy.idl64
-rw-r--r--dom/network/moz.build22
14 files changed, 0 insertions, 4111 deletions
diff --git a/dom/network/EthernetManager.js b/dom/network/EthernetManager.js
deleted file mode 100644
index 4b11e5666..000000000
--- a/dom/network/EthernetManager.js
+++ /dev/null
@@ -1,655 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const TOPIC_INTERFACE_STATE_CHANGED = "network-interface-state-changed";
-
-const ETHERNET_NETWORK_IFACE_PREFIX = "eth";
-const DEFAULT_ETHERNET_NETWORK_IFACE = "eth0";
-
-const INTERFACE_IPADDR_NULL = "0.0.0.0";
-const INTERFACE_GATEWAY_NULL = "0.0.0.0";
-const INTERFACE_PREFIX_NULL = 0;
-const INTERFACE_MACADDR_NULL = "00:00:00:00:00:00";
-
-const NETWORK_INTERFACE_UP = "up";
-const NETWORK_INTERFACE_DOWN = "down";
-
-const IP_MODE_DHCP = "dhcp";
-const IP_MODE_STATIC = "static";
-
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-let debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- EthernetManager: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-// nsINetworkInterface
-
-function EthernetInterface(attr) {
- this.info.state = attr.state;
- this.info.type = attr.type;
- this.info.name = attr.name;
- this.info.ipMode = attr.ipMode;
- this.info.ips = [attr.ip];
- this.info.prefixLengths = [attr.prefixLength];
- this.info.gateways = [attr.gateway];
- this.info.dnses = attr.dnses;
- this.httpProxyHost = "";
- this.httpProxyPort = 0;
-}
-EthernetInterface.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- updateConfig: function(config) {
- debug("Interface " + this.info.name + " updateConfig " + JSON.stringify(config));
- this.info.state = (config.state != undefined) ?
- config.state : this.info.state;
- this.info.ips = (config.ip != undefined) ? [config.ip] : this.info.ips;
- this.info.prefixLengths = (config.prefixLength != undefined) ?
- [config.prefixLength] : this.info.prefixLengths;
- this.info.gateways = (config.gateway != undefined) ?
- [config.gateway] : this.info.gateways;
- this.info.dnses = (config.dnses != undefined) ? config.dnses : this.info.dnses;
- this.httpProxyHost = (config.httpProxyHost != undefined) ?
- config.httpProxyHost : this.httpProxyHost;
- this.httpProxyPort = (config.httpProxyPort != undefined) ?
- config.httpProxyPort : this.httpProxyPort;
- this.info.ipMode = (config.ipMode != undefined) ?
- config.ipMode : this.info.ipMode;
- },
-
- info: {
- getAddresses: function(ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function(count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function(count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
- }
-};
-
-// nsIEthernetManager
-
-/*
- * Network state transition diagram
- *
- * ---------- enable --------- connect ----------- disconnect --------------
- * | Disabled | -----> | Enabled | -------> | Connected | <----------> | Disconnected |
- * ---------- --------- ----------- connect --------------
- * ^ | | |
- * | disable | | |
- * -----------------------------------------------------------------------
- */
-
-function EthernetManager() {
- debug("EthernetManager start");
-
- // Interface list.
- this.ethernetInterfaces = {};
-
- // Used to memorize last connection information.
- this.lastStaticConfig = {};
-
- Services.obs.addObserver(this, "xpcom-shutdown", false);
-}
-
-EthernetManager.prototype = {
- classID: Components.ID("a96441dd-36b3-4f7f-963b-2c032e28a039"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIEthernetManager]),
-
- ethernetInterfaces: null,
- lastStaticConfig: null,
-
- observer: function(subject, topic, data) {
- switch (topic) {
- case "xpcom-shutdown":
- debug("xpcom-shutdown");
-
- this._shutdown();
-
- Services.obs.removeObserver(this, "xpcom-shutdown");
- break;
- }
- },
-
- _shutdown: function() {
- debug("Shuting down");
- (function onRemove(ifnameList) {
- if (!ifnameList.length) {
- return;
- }
-
- let ifname = ifnameList.shift();
- this.removeInterface(ifname, { notify: onRemove.bind(this, ifnameList) });
- }).call(this, Object.keys(this.ethernetInterfaces));
- },
-
- get interfaceList() {
- return Object.keys(this.ethernetInterfaces);
- },
-
- scan: function(callback) {
- debug("Scan");
-
- gNetworkService.getInterfaces(function(success, list) {
- let ethList = [];
-
- if (!success) {
- if (callback) {
- callback.notify(ethList);
- }
- return;
- }
-
- for (let i = 0; i < list.length; i++) {
- debug("Found interface " + list[i]);
- if (!list[i].startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- continue;
- }
- ethList.push(list[i]);
- }
-
- if (callback) {
- callback.notify(ethList);
- }
- });
- },
-
- addInterface: function(ifname, callback) {
- debug("Add interface " + ifname);
-
- if (!ifname || !ifname.startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- if (this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(true, "Interface already exists.");
- }
- return;
- }
-
- gNetworkService.getInterfaceConfig(ifname, function(success, result) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd error.");
- }
- return;
- }
-
- // Since the operation may still succeed with an invalid interface name,
- // check the mac address as well.
- if (result.macAddr == INTERFACE_MACADDR_NULL) {
- if (callback) {
- callback.notify(false, "Interface not found.");
- }
- return;
- }
-
- this.ethernetInterfaces[ifname] = new EthernetInterface({
- state: result.link == NETWORK_INTERFACE_UP ?
- Ci.nsINetworkInfo.NETWORK_STATE_DISABLED :
- Ci.nsINetworkInfo.NETWORK_STATE_ENABLED,
- name: ifname,
- type: Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET,
- ip: result.ip,
- prefixLength: result.prefix,
- ipMode: IP_MODE_DHCP
- });
-
- // Register the interface to NetworkManager.
- gNetworkManager.registerNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Add interface " + ifname + " succeeded with " +
- JSON.stringify(this.ethernetInterfaces[ifname]));
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- removeInterface: function(ifname, callback) {
- debug("Remove interface " + ifname);
-
- if (!ifname || !ifname.startsWith(ETHERNET_NETWORK_IFACE_PREFIX)) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- if (!this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(true, "Interface does not exist.");
- }
- return;
- }
-
- // Make sure interface is disable before removing.
- this.disable(ifname, { notify: function(success, message) {
- // Unregister the interface from NetworkManager and also remove it from
- // the interface list.
- gNetworkManager.unregisterNetworkInterface(this.ethernetInterfaces[ifname]);
- delete this.ethernetInterfaces[ifname];
-
- debug("Remove interface " + ifname + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this)});
- },
-
- updateInterfaceConfig: function(ifname, config, callback) {
- debug("Update interface config with " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- if (!config) {
- if (callback) {
- callback.notify(false, "No config to update.");
- }
- return;
- }
-
- // Network state can not be modified externally.
- if (config.state) {
- delete config.state;
- }
-
- let currentIpMode = iface.info.ipMode;
-
- // Update config.
- this.ethernetInterfaces[iface.info.name].updateConfig(config);
-
- // Do not automatically re-connect if the interface is not in connected
- // state.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "ok");
- }
- return;
- }
-
- let newIpMode = this.ethernetInterfaces[iface.info.name].info.ipMode;
-
- if (newIpMode == IP_MODE_STATIC) {
- this._setStaticIP(iface.info.name, callback);
- return;
- }
- if ((currentIpMode == IP_MODE_STATIC) && (newIpMode == IP_MODE_DHCP)) {
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
-
- // Clear the current network settings before do dhcp request, otherwise
- // dhcp settings could fail.
- this.disconnect(iface.info.name, { notify: function(success, message) {
- if (!success) {
- if (callback) {
- callback.notify("Disconnect failed.");
- }
- return;
- }
- this._runDhcp(iface.info.name, callback);
- }.bind(this) });
- return;
- }
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- enable: function(ifname, callback) {
- debug("Enable interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can be only enabled in the state of disabled.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_DISABLED) {
- if (callback) {
- callback.notify(true, "Interface already enabled.");
- }
- return;
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_ENABLED
- });
-
- debug("Enable interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- disable: function(ifname, callback) {
- debug("Disable interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_DISABLED) {
- if (callback) {
- callback.notify(true, "Interface already disabled.");
- }
- return;
- }
-
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_DOWN };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_DISABLED
- });
-
- debug("Disable interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- connect: function(ifname, callback) {
- debug("Connect interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can only be connected in the state of enabled or
- // disconnected.
- if (iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_DISABLED ||
- iface.info.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "Interface " + ifname + " is not available or "
- + " already connected.");
- }
- return;
- }
-
- if (iface.info.ipMode == IP_MODE_DHCP) {
- this._runDhcp(iface.info.name, callback);
- return;
- }
-
- if (iface.info.ipMode == IP_MODE_STATIC) {
- if (this._checkConfigNull(iface) && this.lastStaticConfig[iface.info.name]) {
- debug("Connect with lastStaticConfig " +
- JSON.stringify(this.lastStaticConfig[iface.info.name]));
- this.ethernetInterfaces[iface.info.name].updateConfig(
- this.lastStaticConfig[iface.info.name]);
- }
- this._setStaticIP(iface.info.name, callback);
- return;
- }
-
- if (callback) {
- callback.notify(false, "IP mode is wrong or not set.");
- }
- }.bind(this));
- },
-
- disconnect: function(ifname, callback) {
- debug("Disconnect interface " + ifname);
-
- this._ensureIfname(ifname, callback, function(iface) {
- // Interface can be only disconnected in the state of connected.
- if (iface.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- if (callback) {
- callback.notify(true, "Interface is already disconnected");
- }
- return;
- }
-
- let config = { ifname: iface.info.name,
- ip: INTERFACE_IPADDR_NULL,
- prefix: INTERFACE_PREFIX_NULL,
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd error.");
- }
- return;
- }
-
- // Stop dhcp daemon.
- gNetworkService.stopDhcp(iface.info.name, function(success) {
- if (success) {
- debug("DHCP for " + iface.info.name + " stopped.");
- }
- });
-
- this.ethernetInterfaces[iface.info.name].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- ip: INTERFACE_IPADDR_NULL,
- prefixLength: INTERFACE_PREFIX_NULL,
- gateway: INTERFACE_GATEWAY_NULL
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Disconnect interface " + iface.info.name + " succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- }.bind(this));
- },
-
- _checkConfigNull: function(iface) {
- let ips = {};
- let prefixLengths = {};
- let gateways = iface.info.getGateways();
- iface.info.getAddresses(ips, prefixLengths);
-
- if (ips.value[0] == INTERFACE_IPADDR_NULL &&
- prefixLengths.value[0] == INTERFACE_PREFIX_NULL &&
- gateways[0] == INTERFACE_GATEWAY_NULL) {
- return true;
- }
-
- return false;
- },
-
- _ensureIfname: function(ifname, callback, func) {
- // If no given ifname, use the default one.
- if (!ifname) {
- ifname = DEFAULT_ETHERNET_NETWORK_IFACE;
- }
-
- let iface = this.ethernetInterfaces[ifname];
- if (!iface) {
- if (callback) {
- callback.notify(true, "Interface " + ifname + " is not available.");
- }
- return;
- }
-
- func.call(this, iface);
- },
-
- _runDhcp: function(ifname, callback) {
- debug("runDhcp with " + ifname);
-
- if (!this.ethernetInterfaces[ifname]) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- gNetworkService.dhcpRequest(ifname, function(success, result) {
- if (!success) {
- if (callback) {
- callback.notify(false, "DHCP failed.");
- }
- return;
- }
-
- debug("DHCP succeeded with " + JSON.stringify(result));
-
- // Clear last static network information when connecting with dhcp mode.
- if (this.lastStaticConfig[ifname]) {
- this.lastStaticConfig[ifname] = null;
- }
-
- this.ethernetInterfaces[ifname].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- ip: result.ipaddr_str,
- gateway: result.gateway_str,
- prefixLength: result.prefixLength,
- dnses: [result.dns1_str, result.dns2_str]
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Connect interface " + ifname + " with DHCP succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-
- _setStaticIP: function(ifname, callback) {
- let iface = this.ethernetInterfaces[ifname];
- if (!iface) {
- if (callback) {
- callback.notify(false, "Invalid interface.");
- }
- return;
- }
-
- let ips = {};
- let prefixLengths = {};
- iface.info.getAddresses(ips, prefixLengths);
-
- let config = { ifname: iface.info.name,
- ip: ips.value[0],
- prefix: prefixLengths.value[0],
- link: NETWORK_INTERFACE_UP };
- gNetworkService.setInterfaceConfig(config, function(success) {
- if (!success) {
- if (callback) {
- callback.notify(false, "Netd Error.");
- }
- return;
- }
-
- // Keep the lastest static network information.
- let ips = {};
- let prefixLengths = {};
- let gateways = iface.info.getGateways();
- iface.info.getAddresses(ips, prefixLengths);
-
- this.lastStaticConfig[iface.info.name] = {
- ip: ips.value[0],
- prefixLength: prefixLengths.value[0],
- gateway: gateways[0]
- };
-
- this.ethernetInterfaces[ifname].updateConfig({
- state: Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- });
-
- gNetworkManager.updateNetworkInterface(this.ethernetInterfaces[ifname]);
-
- debug("Connect interface " + ifname + " with static ip succeeded.");
-
- if (callback) {
- callback.notify(true, "ok");
- }
- }.bind(this));
- },
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EthernetManager]);
diff --git a/dom/network/EthernetManager.manifest b/dom/network/EthernetManager.manifest
deleted file mode 100644
index d25a069e1..000000000
--- a/dom/network/EthernetManager.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {a96441dd-36b3-4f7f-963b-2c032e28a039} EthernetManager.js
-contract @mozilla.org/ethernetManager;1 {a96441dd-36b3-4f7f-963b-2c032e28a039}
diff --git a/dom/network/NetUtils.cpp b/dom/network/NetUtils.cpp
deleted file mode 100644
index 78c5be802..000000000
--- a/dom/network/NetUtils.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetUtils.h"
-#include <dlfcn.h>
-#include <errno.h>
-#include "prinit.h"
-#include "mozilla/Assertions.h"
-#include "nsDebug.h"
-#include "SystemProperty.h"
-
-using mozilla::system::Property;
-
-static void* sNetUtilsLib;
-static PRCallOnceType sInitNetUtilsLib;
-
-static PRStatus
-InitNetUtilsLib()
-{
- sNetUtilsLib = dlopen("/system/lib/libnetutils.so", RTLD_LAZY);
- // We might fail to open the hardware lib. That's OK.
- return PR_SUCCESS;
-}
-
-static void*
-GetNetUtilsLibHandle()
-{
- PR_CallOnce(&sInitNetUtilsLib, InitNetUtilsLib);
- return sNetUtilsLib;
-}
-
-// static
-void*
-NetUtils::GetSharedLibrary()
-{
- void* netLib = GetNetUtilsLibHandle();
- if (!netLib) {
- NS_WARNING("No /system/lib/libnetutils.so");
- }
- return netLib;
-}
-
-// static
-int32_t
-NetUtils::SdkVersion()
-{
- char propVersion[Property::VALUE_MAX_LENGTH];
- Property::Get("ro.build.version.sdk", propVersion, "0");
- int32_t version = strtol(propVersion, nullptr, 10);
- return version;
-}
-
-DEFINE_DLFUNC(ifc_enable, int32_t, const char*)
-DEFINE_DLFUNC(ifc_disable, int32_t, const char*)
-DEFINE_DLFUNC(ifc_configure, int32_t, const char*, in_addr_t, uint32_t,
- in_addr_t, in_addr_t, in_addr_t)
-DEFINE_DLFUNC(ifc_reset_connections, int32_t, const char*, const int32_t)
-DEFINE_DLFUNC(ifc_set_default_route, int32_t, const char*, in_addr_t)
-DEFINE_DLFUNC(ifc_add_route, int32_t, const char*, const char*, uint32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_route, int32_t, const char*, const char*, uint32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_host_routes, int32_t, const char*)
-DEFINE_DLFUNC(ifc_remove_default_route, int32_t, const char*)
-DEFINE_DLFUNC(dhcp_stop, int32_t, const char*)
-
-NetUtils::NetUtils()
-{
-}
-
-int32_t NetUtils::do_ifc_enable(const char *ifname)
-{
- USE_DLFUNC(ifc_enable)
- return ifc_enable(ifname);
-}
-
-int32_t NetUtils::do_ifc_disable(const char *ifname)
-{
- USE_DLFUNC(ifc_disable)
- return ifc_disable(ifname);
-}
-
-int32_t NetUtils::do_ifc_configure(const char *ifname,
- in_addr_t address,
- uint32_t prefixLength,
- in_addr_t gateway,
- in_addr_t dns1,
- in_addr_t dns2)
-{
- USE_DLFUNC(ifc_configure)
- int32_t ret = ifc_configure(ifname, address, prefixLength, gateway, dns1, dns2);
- return ret;
-}
-
-int32_t NetUtils::do_ifc_reset_connections(const char *ifname,
- const int32_t resetMask)
-{
- USE_DLFUNC(ifc_reset_connections)
- return ifc_reset_connections(ifname, resetMask);
-}
-
-int32_t NetUtils::do_ifc_set_default_route(const char *ifname,
- in_addr_t gateway)
-{
- USE_DLFUNC(ifc_set_default_route)
- return ifc_set_default_route(ifname, gateway);
-}
-
-int32_t NetUtils::do_ifc_add_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway)
-{
- USE_DLFUNC(ifc_add_route)
- return ifc_add_route(ifname, dst, prefixLength, gateway);
-}
-
-int32_t NetUtils::do_ifc_remove_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway)
-{
- USE_DLFUNC(ifc_remove_route)
- return ifc_remove_route(ifname, dst, prefixLength, gateway);
-}
-
-int32_t NetUtils::do_ifc_remove_host_routes(const char *ifname)
-{
- USE_DLFUNC(ifc_remove_host_routes)
- return ifc_remove_host_routes(ifname);
-}
-
-int32_t NetUtils::do_ifc_remove_default_route(const char *ifname)
-{
- USE_DLFUNC(ifc_remove_default_route)
- return ifc_remove_default_route(ifname);
-}
-
-int32_t NetUtils::do_dhcp_stop(const char *ifname)
-{
- USE_DLFUNC(dhcp_stop)
- return dhcp_stop(ifname);
-}
-
-int32_t NetUtils::do_dhcp_do_request(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char* vendorinfo)
-{
- int32_t ret = -1;
- uint32_t sdkVersion = SdkVersion();
-
- if (sdkVersion == 15) {
- // ICS
- // http://androidxref.com/4.0.4/xref/system/core/libnetutils/dhcp_utils.c#149
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char*, char*, char*, uint32_t*)
- USE_DLFUNC(dhcp_do_request)
- vendorinfo[0] = '\0';
-
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2,
- server, lease);
- } else if (sdkVersion == 16 || sdkVersion == 17) {
- // JB 4.1 and 4.2
- // http://androidxref.com/4.1.2/xref/system/core/libnetutils/dhcp_utils.c#175
- // http://androidxref.com/4.2.2_r1/xref/system/core/include/netutils/dhcp.h#26
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char*, char*, char*, uint32_t*, char*)
- USE_DLFUNC(dhcp_do_request)
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2,
- server, lease, vendorinfo);
- } else if (sdkVersion == 18) {
- // JB 4.3
- // http://androidxref.com/4.3_r2.1/xref/system/core/libnetutils/dhcp_utils.c#181
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char**, char*, uint32_t*, char*, char*)
- USE_DLFUNC(dhcp_do_request)
- char *dns[3] = {dns1, dns2, nullptr};
- char domains[Property::VALUE_MAX_LENGTH];
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns,
- server, lease, vendorinfo, domains);
- } else if (sdkVersion >= 19) {
- // KitKat 4.4.X
- // http://androidxref.com/4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#18
- // Lollipop 5.0
- //http://androidxref.com/5.0.0_r2/xref/system/core/libnetutils/dhcp_utils.c#186
- DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*, uint32_t*, char**, char*, uint32_t*, char*, char*, char*)
- USE_DLFUNC(dhcp_do_request)
- char *dns[3] = {dns1, dns2, nullptr};
- char domains[Property::VALUE_MAX_LENGTH];
- char mtu[Property::VALUE_MAX_LENGTH];
- ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorinfo, domains, mtu);
- } else {
- NS_WARNING("Unable to perform do_dhcp_request: unsupported sdk version!");
- }
- return ret;
-}
diff --git a/dom/network/NetUtils.h b/dom/network/NetUtils.h
deleted file mode 100644
index 4af365406..000000000
--- a/dom/network/NetUtils.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Abstraction on top of the network support from libnetutils that we
- * use to set up network connections.
- */
-
-#ifndef NetUtils_h
-#define NetUtils_h
-
-#include "arpa/inet.h"
-
-// Copied from ifc.h
-#define RESET_IPV4_ADDRESSES 0x01
-#define RESET_IPV6_ADDRESSES 0x02
-#define RESET_ALL_ADDRESSES (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
-
-// Implements netutils functions. No need for an abstract class here since we
-// only have a one sdk specific method (dhcp_do_request)
-class NetUtils
-{
-public:
- static void* GetSharedLibrary();
-
- NetUtils();
-
- int32_t do_ifc_enable(const char *ifname);
- int32_t do_ifc_disable(const char *ifname);
- int32_t do_ifc_configure(const char *ifname,
- in_addr_t address,
- uint32_t prefixLength,
- in_addr_t gateway,
- in_addr_t dns1,
- in_addr_t dns2);
- int32_t do_ifc_reset_connections(const char *ifname, const int32_t resetMask);
- int32_t do_ifc_set_default_route(const char *ifname, in_addr_t gateway);
- int32_t do_ifc_add_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway);
- int32_t do_ifc_remove_route(const char *ifname,
- const char *dst,
- uint32_t prefixLength,
- const char *gateway);
- int32_t do_ifc_remove_host_routes(const char *ifname);
- int32_t do_ifc_remove_default_route(const char *ifname);
- int32_t do_dhcp_stop(const char *ifname);
- int32_t do_dhcp_do_request(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char* vendorinfo);
-
- static int32_t SdkVersion();
-};
-
-// Defines a function type with the right arguments and return type.
-#define DEFINE_DLFUNC(name, ret, args...) typedef ret (*FUNC##name)(args);
-
-// Set up a dlsymed function ready to use.
-#define USE_DLFUNC(name) \
- FUNC##name name = (FUNC##name) dlsym(GetSharedLibrary(), #name); \
- if (!name) { \
- MOZ_CRASH("Symbol not found in shared library : " #name); \
- }
-
-#endif // NetUtils_h
diff --git a/dom/network/NetworkStatsDB.jsm b/dom/network/NetworkStatsDB.jsm
deleted file mode 100644
index aa74d40ad..000000000
--- a/dom/network/NetworkStatsDB.jsm
+++ /dev/null
@@ -1,1285 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ['NetworkStatsDB'];
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsDB: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
-Cu.importGlobalProperties(["indexedDB"]);
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
- "@mozilla.org/AppsService;1",
- "nsIAppsService");
-
-const DB_NAME = "net_stats";
-const DB_VERSION = 9;
-const DEPRECATED_STATS_STORE_NAME =
- [
- "net_stats_v2", // existed only in DB version 2
- "net_stats", // existed in DB version 1 and 3 to 5
- "net_stats_store", // existed in DB version 6 to 8
- ];
-const STATS_STORE_NAME = "net_stats_store_v3"; // since DB version 9
-const ALARMS_STORE_NAME = "net_alarm";
-
-// Constant defining the maximum values allowed per interface. If more, older
-// will be erased.
-const VALUES_MAX_LENGTH = 6 * 30;
-
-// Constant defining the rate of the samples. Daily.
-const SAMPLE_RATE = 1000 * 60 * 60 * 24;
-
-this.NetworkStatsDB = function NetworkStatsDB() {
- if (DEBUG) {
- debug("Constructor");
- }
- this.initDBHelper(DB_NAME, DB_VERSION, [STATS_STORE_NAME, ALARMS_STORE_NAME]);
-}
-
-NetworkStatsDB.prototype = {
- __proto__: IndexedDBHelper.prototype,
-
- dbNewTxn: function dbNewTxn(store_name, txn_type, callback, txnCb) {
- function successCb(result) {
- txnCb(null, result);
- }
- function errorCb(error) {
- txnCb(error, null);
- }
- return this.newTxn(txn_type, store_name, callback, successCb, errorCb);
- },
-
- /**
- * The onupgradeneeded handler of the IDBOpenDBRequest.
- * This function is called in IndexedDBHelper open() method.
- *
- * @param {IDBTransaction} aTransaction
- * {IDBDatabase} aDb
- * {64-bit integer} aOldVersion The version number on local storage.
- * {64-bit integer} aNewVersion The version number to be upgraded to.
- *
- * @note Be careful with the database upgrade pattern.
- * Because IndexedDB operations are performed asynchronously, we must
- * apply a recursive approach instead of an iterative approach while
- * upgrading versions.
- */
- upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
- if (DEBUG) {
- debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
- }
- let db = aDb;
- let objectStore;
-
- // An array of upgrade functions for each version.
- let upgradeSteps = [
- function upgrade0to1() {
- if (DEBUG) debug("Upgrade 0 to 1: Create object stores and indexes.");
-
- // Create the initial database schema.
- objectStore = db.createObjectStore(DEPRECATED_STATS_STORE_NAME[1],
- { keyPath: ["connectionType", "timestamp"] });
- objectStore.createIndex("connectionType", "connectionType", { unique: false });
- objectStore.createIndex("timestamp", "timestamp", { unique: false });
- objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
- objectStore.createIndex("txBytes", "txBytes", { unique: false });
- objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
- objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade1to2() {
- if (DEBUG) debug("Upgrade 1 to 2: Do nothing.");
- upgradeNextVersion();
- },
-
- function upgrade2to3() {
- if (DEBUG) debug("Upgrade 2 to 3: Add keyPath appId to object store.");
-
- // In order to support per-app traffic data storage, the original
- // objectStore needs to be replaced by a new objectStore with new
- // key path ("appId") and new index ("appId").
- // Also, since now networks are identified by their
- // [networkId, networkType] not just by their connectionType,
- // to modify the keyPath is mandatory to delete the object store
- // and create it again. Old data is going to be deleted because the
- // networkId for each sample can not be set.
-
- // In version 1.2 objectStore name was 'net_stats_v2', to avoid errors when
- // upgrading from 1.2 to 1.3 objectStore name should be checked.
- let stores = db.objectStoreNames;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[0];
- let storeName = DEPRECATED_STATS_STORE_NAME[1];
- if(stores.contains(deprecatedName)) {
- // Delete the obsolete stats store.
- db.deleteObjectStore(deprecatedName);
- } else {
- // Re-create stats object store without copying records.
- db.deleteObjectStore(storeName);
- }
-
- objectStore = db.createObjectStore(storeName, { keyPath: ["appId", "network", "timestamp"] });
- objectStore.createIndex("appId", "appId", { unique: false });
- objectStore.createIndex("network", "network", { unique: false });
- objectStore.createIndex("networkType", "networkType", { unique: false });
- objectStore.createIndex("timestamp", "timestamp", { unique: false });
- objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
- objectStore.createIndex("txBytes", "txBytes", { unique: false });
- objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
- objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade3to4() {
- if (DEBUG) debug("Upgrade 3 to 4: Delete redundant indexes.");
-
- // Delete redundant indexes (leave "network" only).
- objectStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[1]);
- if (objectStore.indexNames.contains("appId")) {
- objectStore.deleteIndex("appId");
- }
- if (objectStore.indexNames.contains("networkType")) {
- objectStore.deleteIndex("networkType");
- }
- if (objectStore.indexNames.contains("timestamp")) {
- objectStore.deleteIndex("timestamp");
- }
- if (objectStore.indexNames.contains("rxBytes")) {
- objectStore.deleteIndex("rxBytes");
- }
- if (objectStore.indexNames.contains("txBytes")) {
- objectStore.deleteIndex("txBytes");
- }
- if (objectStore.indexNames.contains("rxTotalBytes")) {
- objectStore.deleteIndex("rxTotalBytes");
- }
- if (objectStore.indexNames.contains("txTotalBytes")) {
- objectStore.deleteIndex("txTotalBytes");
- }
-
- upgradeNextVersion();
- },
-
- function upgrade4to5() {
- if (DEBUG) debug("Upgrade 4 to 5: Create object store for alarms.");
-
- // In order to manage alarms, it is necessary to use a global counter
- // (totalBytes) that will increase regardless of the system reboot.
- objectStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[1]);
-
- // Now, systemBytes will hold the old totalBytes and totalBytes will
- // keep the increasing counter. |counters| will keep the track of
- // accumulated values.
- let counters = {};
-
- objectStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor){
- // upgrade4to5 completed now.
- upgradeNextVersion();
- return;
- }
-
- cursor.value.rxSystemBytes = cursor.value.rxTotalBytes;
- cursor.value.txSystemBytes = cursor.value.txTotalBytes;
-
- if (cursor.value.appId == 0) {
- let netId = cursor.value.network[0] + '' + cursor.value.network[1];
- if (!counters[netId]) {
- counters[netId] = {
- rxCounter: 0,
- txCounter: 0,
- lastRx: 0,
- lastTx: 0
- };
- }
-
- let rxDiff = cursor.value.rxSystemBytes - counters[netId].lastRx;
- let txDiff = cursor.value.txSystemBytes - counters[netId].lastTx;
- if (rxDiff < 0 || txDiff < 0) {
- // System reboot between samples, so take the current one.
- rxDiff = cursor.value.rxSystemBytes;
- txDiff = cursor.value.txSystemBytes;
- }
-
- counters[netId].rxCounter += rxDiff;
- counters[netId].txCounter += txDiff;
- cursor.value.rxTotalBytes = counters[netId].rxCounter;
- cursor.value.txTotalBytes = counters[netId].txCounter;
-
- counters[netId].lastRx = cursor.value.rxSystemBytes;
- counters[netId].lastTx = cursor.value.txSystemBytes;
- } else {
- cursor.value.rxTotalBytes = cursor.value.rxSystemBytes;
- cursor.value.txTotalBytes = cursor.value.txSystemBytes;
- }
-
- cursor.update(cursor.value);
- cursor.continue();
- };
-
- // Create object store for alarms.
- objectStore = db.createObjectStore(ALARMS_STORE_NAME, { keyPath: "id", autoIncrement: true });
- objectStore.createIndex("alarm", ['networkId','threshold'], { unique: false });
- objectStore.createIndex("manifestURL", "manifestURL", { unique: false });
- },
-
- function upgrade5to6() {
- if (DEBUG) debug("Upgrade 5 to 6: Add keyPath serviceType to object store.");
-
- // In contrast to "per-app" traffic data, "system-only" traffic data
- // refers to data which can not be identified by any applications.
- // To further support "system-only" data storage, the data can be
- // saved by service type (e.g., Tethering, OTA). Thus it's needed to
- // have a new key ("serviceType") for the ojectStore.
- let newObjectStore;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[1];
- newObjectStore = db.createObjectStore(DEPRECATED_STATS_STORE_NAME[2],
- { keyPath: ["appId", "serviceType", "network", "timestamp"] });
- newObjectStore.createIndex("network", "network", { unique: false });
-
- // Copy the data from the original objectStore to the new objectStore.
- objectStore = aTransaction.objectStore(deprecatedName);
- objectStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- db.deleteObjectStore(deprecatedName);
- // upgrade5to6 completed now.
- upgradeNextVersion();
- return;
- }
-
- let newStats = cursor.value;
- newStats.serviceType = "";
- newObjectStore.put(newStats);
- cursor.continue();
- };
- },
-
- function upgrade6to7() {
- if (DEBUG) debug("Upgrade 6 to 7: Replace alarm threshold by relativeThreshold.");
-
- // Replace threshold attribute of alarm index by relativeThreshold in alarms DB.
- // Now alarms are indexed by relativeThreshold, which is the threshold relative
- // to current system stats.
- let alarmsStore = aTransaction.objectStore(ALARMS_STORE_NAME);
-
- // Delete "alarm" index.
- if (alarmsStore.indexNames.contains("alarm")) {
- alarmsStore.deleteIndex("alarm");
- }
-
- // Create new "alarm" index.
- alarmsStore.createIndex("alarm", ['networkId','relativeThreshold'], { unique: false });
-
- // Populate new "alarm" index attributes.
- alarmsStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- upgrade6to7_updateTotalBytes();
- return;
- }
-
- cursor.value.relativeThreshold = cursor.value.threshold;
- cursor.value.absoluteThreshold = cursor.value.threshold;
- delete cursor.value.threshold;
-
- cursor.update(cursor.value);
- cursor.continue();
- }
-
- function upgrade6to7_updateTotalBytes() {
- if (DEBUG) debug("Upgrade 6 to 7: Update TotalBytes.");
- // Previous versions save accumulative totalBytes, increasing although the system
- // reboots or resets stats. But is necessary to reset the total counters when reset
- // through 'clearInterfaceStats'.
- let statsStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[2]);
- let networks = [];
-
- // Find networks stored in the database.
- statsStore.index("network").openKeyCursor(null, "nextunique").onsuccess = function(event) {
- let cursor = event.target.result;
-
- // Store each network into an array.
- if (cursor) {
- networks.push(cursor.key);
- cursor.continue();
- return;
- }
-
- // Start to deal with each network.
- let pending = networks.length;
-
- if (pending === 0) {
- // Found no records of network. upgrade6to7 completed now.
- upgradeNextVersion();
- return;
- }
-
- networks.forEach(function(network) {
- let lowerFilter = [0, "", network, 0];
- let upperFilter = [0, "", network, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- // Find number of samples for a given network.
- statsStore.count(range).onsuccess = function(event) {
- let recordCount = event.target.result;
-
- // If there are more samples than the max allowed, there is no way to know
- // when does reset take place.
- if (recordCount === 0 || recordCount >= VALUES_MAX_LENGTH) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
-
- let last = null;
- // Reset detected if the first sample totalCounters are different than bytes
- // counters. If so, the total counters should be recalculated.
- statsStore.openCursor(range).onsuccess = function(event) {
- let cursor = event.target.result;
- if (!cursor) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
- if (!last) {
- if (cursor.value.rxTotalBytes == cursor.value.rxBytes &&
- cursor.value.txTotalBytes == cursor.value.txBytes) {
- pending--;
- if (pending === 0) {
- upgradeNextVersion();
- }
- return;
- }
-
- cursor.value.rxTotalBytes = cursor.value.rxBytes;
- cursor.value.txTotalBytes = cursor.value.txBytes;
- cursor.update(cursor.value);
- last = cursor.value;
- cursor.continue();
- return;
- }
-
- // Recalculate the total counter for last / current sample
- cursor.value.rxTotalBytes = last.rxTotalBytes + cursor.value.rxBytes;
- cursor.value.txTotalBytes = last.txTotalBytes + cursor.value.txBytes;
- cursor.update(cursor.value);
- last = cursor.value;
- cursor.continue();
- }
- }
- }, this); // end of networks.forEach()
- }; // end of statsStore.index("network").openKeyCursor().onsuccess callback
- } // end of function upgrade6to7_updateTotalBytes
- },
-
- function upgrade7to8() {
- if (DEBUG) debug("Upgrade 7 to 8: Create index serviceType.");
-
- // Create index for 'ServiceType' in order to make it retrievable.
- let statsStore = aTransaction.objectStore(DEPRECATED_STATS_STORE_NAME[2]);
- statsStore.createIndex("serviceType", "serviceType", { unique: false });
-
- upgradeNextVersion();
- },
-
- function upgrade8to9() {
- if (DEBUG) debug("Upgrade 8 to 9: Add keyPath isInBrowser to " +
- "network stats object store");
-
- // Since B2G v2.0, there is no stand-alone browser app anymore.
- // The browser app is a mozbrowser iframe element owned by system app.
- // In order to separate traffic generated from system and browser, we
- // have to add a new attribute |isInBrowser| as keyPath.
- // Refer to bug 1070944 for more detail.
- let newObjectStore;
- let deprecatedName = DEPRECATED_STATS_STORE_NAME[2];
- newObjectStore = db.createObjectStore(STATS_STORE_NAME,
- { keyPath: ["appId", "isInBrowser", "serviceType",
- "network", "timestamp"] });
- newObjectStore.createIndex("network", "network", { unique: false });
- newObjectStore.createIndex("serviceType", "serviceType", { unique: false });
-
- // Copy records from the current object store to the new one.
- objectStore = aTransaction.objectStore(deprecatedName);
- objectStore.openCursor().onsuccess = function (event) {
- let cursor = event.target.result;
- if (!cursor) {
- db.deleteObjectStore(deprecatedName);
- // upgrade8to9 completed now.
- return;
- }
- let newStats = cursor.value;
- // Augment records by adding the new isInBrowser attribute.
- // Notes:
- // 1. Key value cannot be boolean type. Use 1/0 instead of true/false.
- // 2. Most traffic of system app should come from its browser iframe,
- // thus assign isInBrowser as 1 for system app.
- let manifestURL = appsService.getManifestURLByLocalId(newStats.appId);
- if (manifestURL && manifestURL.search(/app:\/\/system\./) === 0) {
- newStats.isInBrowser = 1;
- } else {
- newStats.isInBrowser = 0;
- }
- newObjectStore.put(newStats);
- cursor.continue();
- };
- }
- ];
-
- let index = aOldVersion;
- let outer = this;
-
- function upgradeNextVersion() {
- if (index == aNewVersion) {
- debug("Upgrade finished.");
- return;
- }
-
- try {
- var i = index++;
- if (DEBUG) debug("Upgrade step: " + i + "\n");
- upgradeSteps[i].call(outer);
- } catch (ex) {
- dump("Caught exception " + ex);
- throw ex;
- return;
- }
- }
-
- if (aNewVersion > upgradeSteps.length) {
- debug("No migration steps for the new version!");
- aTransaction.abort();
- return;
- }
-
- upgradeNextVersion();
- },
-
- importData: function importData(aStats) {
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser ? 1 : 0,
- serviceType: aStats.serviceType,
- network: [aStats.networkId, aStats.networkType],
- timestamp: aStats.timestamp,
- rxBytes: aStats.rxBytes,
- txBytes: aStats.txBytes,
- rxSystemBytes: aStats.rxSystemBytes,
- txSystemBytes: aStats.txSystemBytes,
- rxTotalBytes: aStats.rxTotalBytes,
- txTotalBytes: aStats.txTotalBytes };
-
- return stats;
- },
-
- exportData: function exportData(aStats) {
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser ? true : false,
- serviceType: aStats.serviceType,
- networkId: aStats.network[0],
- networkType: aStats.network[1],
- timestamp: aStats.timestamp,
- rxBytes: aStats.rxBytes,
- txBytes: aStats.txBytes,
- rxTotalBytes: aStats.rxTotalBytes,
- txTotalBytes: aStats.txTotalBytes };
-
- return stats;
- },
-
- normalizeDate: function normalizeDate(aDate) {
- // Convert to UTC according to timezone and
- // filter timestamp to get SAMPLE_RATE precission
- let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000;
- timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE;
- return timestamp;
- },
-
- saveStats: function saveStats(aStats, aResultCb) {
- let isAccumulative = aStats.isAccumulative;
- let timestamp = this.normalizeDate(aStats.date);
-
- let stats = { appId: aStats.appId,
- isInBrowser: aStats.isInBrowser,
- serviceType: aStats.serviceType,
- networkId: aStats.networkId,
- networkType: aStats.networkType,
- timestamp: timestamp,
- rxBytes: isAccumulative ? 0 : aStats.rxBytes,
- txBytes: isAccumulative ? 0 : aStats.txBytes,
- rxSystemBytes: isAccumulative ? aStats.rxBytes : 0,
- txSystemBytes: isAccumulative ? aStats.txBytes : 0,
- rxTotalBytes: isAccumulative ? aStats.rxBytes : 0,
- txTotalBytes: isAccumulative ? aStats.txBytes : 0 };
-
- stats = this.importData(stats);
-
- this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
- if (DEBUG) {
- debug("Filtered time: " + new Date(timestamp));
- debug("New stats: " + JSON.stringify(stats));
- }
-
- let lowerFilter = [stats.appId, stats.isInBrowser, stats.serviceType,
- stats.network, 0];
- let upperFilter = [stats.appId, stats.isInBrowser, stats.serviceType,
- stats.network, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- let request = aStore.openCursor(range, 'prev');
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor) {
- // Empty, so save first element.
-
- if (!isAccumulative) {
- this._saveStats(aTxn, aStore, stats);
- return;
- }
-
- // There could be a time delay between the point when the network
- // interface comes up and the point when the database is initialized.
- // In this short interval some traffic data are generated but are not
- // registered by the first sample.
- stats.rxBytes = stats.rxTotalBytes;
- stats.txBytes = stats.txTotalBytes;
-
- // However, if the interface is not switched on after the database is
- // initialized (dual sim use case) stats should be set to 0.
- let req = aStore.index("network").openKeyCursor(null, "nextunique");
- req.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.key[1] == stats.network[1]) {
- stats.rxBytes = 0;
- stats.txBytes = 0;
- this._saveStats(aTxn, aStore, stats);
- return;
- }
-
- cursor.continue();
- return;
- }
-
- this._saveStats(aTxn, aStore, stats);
- }.bind(this);
-
- return;
- }
-
- // There are old samples
- if (DEBUG) {
- debug("Last value " + JSON.stringify(cursor.value));
- }
-
- // Remove stats previous to now - VALUE_MAX_LENGTH
- this._removeOldStats(aTxn, aStore, stats.appId, stats.isInBrowser,
- stats.serviceType, stats.network, stats.timestamp);
-
- // Process stats before save
- this._processSamplesDiff(aTxn, aStore, cursor, stats, isAccumulative);
- }.bind(this);
- }.bind(this), aResultCb);
- },
-
- /*
- * This function check that stats are saved in the database following the sample rate.
- * In this way is easier to find elements when stats are requested.
- */
- _processSamplesDiff: function _processSamplesDiff(aTxn,
- aStore,
- aLastSampleCursor,
- aNewSample,
- aIsAccumulative) {
- let lastSample = aLastSampleCursor.value;
-
- // Get difference between last and new sample.
- let diff = (aNewSample.timestamp - lastSample.timestamp) / SAMPLE_RATE;
- if (diff % 1) {
- // diff is decimal, so some error happened because samples are stored as a multiple
- // of SAMPLE_RATE
- aTxn.abort();
- throw new Error("Error processing samples");
- }
-
- if (DEBUG) {
- debug("New: " + aNewSample.timestamp + " - Last: " +
- lastSample.timestamp + " - diff: " + diff);
- }
-
- // If the incoming data has a accumulation feature, the new
- // |txBytes|/|rxBytes| is assigend by differnces between the new
- // |txTotalBytes|/|rxTotalBytes| and the last |txTotalBytes|/|rxTotalBytes|.
- // Else, if incoming data is non-accumulative, the |txBytes|/|rxBytes|
- // is the new |txBytes|/|rxBytes|.
- let rxDiff = 0;
- let txDiff = 0;
- if (aIsAccumulative) {
- rxDiff = aNewSample.rxSystemBytes - lastSample.rxSystemBytes;
- txDiff = aNewSample.txSystemBytes - lastSample.txSystemBytes;
- if (rxDiff < 0 || txDiff < 0) {
- rxDiff = aNewSample.rxSystemBytes;
- txDiff = aNewSample.txSystemBytes;
- }
- aNewSample.rxBytes = rxDiff;
- aNewSample.txBytes = txDiff;
-
- aNewSample.rxTotalBytes = lastSample.rxTotalBytes + rxDiff;
- aNewSample.txTotalBytes = lastSample.txTotalBytes + txDiff;
- } else {
- rxDiff = aNewSample.rxBytes;
- txDiff = aNewSample.txBytes;
- }
-
- if (diff == 1) {
- // New element.
-
- // If the incoming data is non-accumulative, the new
- // |rxTotalBytes|/|txTotalBytes| needs to be updated by adding new
- // |rxBytes|/|txBytes| to the last |rxTotalBytes|/|txTotalBytes|.
- if (!aIsAccumulative) {
- aNewSample.rxTotalBytes = aNewSample.rxBytes + lastSample.rxTotalBytes;
- aNewSample.txTotalBytes = aNewSample.txBytes + lastSample.txTotalBytes;
- }
-
- this._saveStats(aTxn, aStore, aNewSample);
- return;
- }
- if (diff > 1) {
- // Some samples lost. Device off during one or more samplerate periods.
- // Time or timezone changed
- // Add lost samples with 0 bytes and the actual one.
- if (diff > VALUES_MAX_LENGTH) {
- diff = VALUES_MAX_LENGTH;
- }
-
- let data = [];
- for (let i = diff - 2; i >= 0; i--) {
- let time = aNewSample.timestamp - SAMPLE_RATE * (i + 1);
- let sample = { appId: aNewSample.appId,
- isInBrowser: aNewSample.isInBrowser,
- serviceType: aNewSample.serviceType,
- network: aNewSample.network,
- timestamp: time,
- rxBytes: 0,
- txBytes: 0,
- rxSystemBytes: lastSample.rxSystemBytes,
- txSystemBytes: lastSample.txSystemBytes,
- rxTotalBytes: lastSample.rxTotalBytes,
- txTotalBytes: lastSample.txTotalBytes };
-
- data.push(sample);
- }
-
- data.push(aNewSample);
- this._saveStats(aTxn, aStore, data);
- return;
- }
- if (diff == 0 || diff < 0) {
- // New element received before samplerate period. It means that device has
- // been restarted (or clock / timezone change).
- // Update element. If diff < 0, clock or timezone changed back. Place data
- // in the last sample.
-
- // Old |rxTotalBytes|/|txTotalBytes| needs to get updated by adding the
- // last |rxTotalBytes|/|txTotalBytes|.
- lastSample.rxBytes += rxDiff;
- lastSample.txBytes += txDiff;
- lastSample.rxSystemBytes = aNewSample.rxSystemBytes;
- lastSample.txSystemBytes = aNewSample.txSystemBytes;
- lastSample.rxTotalBytes += rxDiff;
- lastSample.txTotalBytes += txDiff;
-
- if (DEBUG) {
- debug("Update: " + JSON.stringify(lastSample));
- }
- let req = aLastSampleCursor.update(lastSample);
- }
- },
-
- _saveStats: function _saveStats(aTxn, aStore, aNetworkStats) {
- if (DEBUG) {
- debug("_saveStats: " + JSON.stringify(aNetworkStats));
- }
-
- if (Array.isArray(aNetworkStats)) {
- let len = aNetworkStats.length - 1;
- for (let i = 0; i <= len; i++) {
- aStore.put(aNetworkStats[i]);
- }
- } else {
- aStore.put(aNetworkStats);
- }
- },
-
- _removeOldStats: function _removeOldStats(aTxn, aStore, aAppId, aIsInBrowser,
- aServiceType, aNetwork, aDate) {
- // Callback function to remove old items when new ones are added.
- let filterDate = aDate - (SAMPLE_RATE * VALUES_MAX_LENGTH - 1);
- let lowerFilter = [aAppId, aIsInBrowser, aServiceType, aNetwork, 0];
- let upperFilter = [aAppId, aIsInBrowser, aServiceType, aNetwork, filterDate];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
- let lastSample = null;
- let self = this;
-
- aStore.openCursor(range).onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- lastSample = cursor.value;
- cursor.delete();
- cursor.continue();
- return;
- }
-
- // If all samples for a network are removed, an empty sample
- // has to be saved to keep the totalBytes in order to compute
- // future samples because system counters are not set to 0.
- // Thus, if there are no samples left, the last sample removed
- // will be saved again after setting its bytes to 0.
- let request = aStore.index("network").openCursor(aNetwork);
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor && lastSample != null) {
- let timestamp = new Date();
- timestamp = self.normalizeDate(timestamp);
- lastSample.timestamp = timestamp;
- lastSample.rxBytes = 0;
- lastSample.txBytes = 0;
- self._saveStats(aTxn, aStore, lastSample);
- }
- };
- };
- },
-
- clearInterfaceStats: function clearInterfaceStats(aNetwork, aResultCb) {
- let network = [aNetwork.network.id, aNetwork.network.type];
- let self = this;
-
- // Clear and save an empty sample to keep sync with system counters
- this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
- let sample = null;
- let request = aStore.index("network").openCursor(network, "prev");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (!sample && cursor.value.appId == 0) {
- sample = cursor.value;
- }
-
- cursor.delete();
- cursor.continue();
- return;
- }
-
- if (sample) {
- let timestamp = new Date();
- timestamp = self.normalizeDate(timestamp);
- sample.timestamp = timestamp;
- sample.appId = 0;
- sample.isInBrowser = 0;
- sample.serviceType = "";
- sample.rxBytes = 0;
- sample.txBytes = 0;
- sample.rxTotalBytes = 0;
- sample.txTotalBytes = 0;
-
- self._saveStats(aTxn, aStore, sample);
- }
- };
- }, this._resetAlarms.bind(this, aNetwork.networkId, aResultCb));
- },
-
- clearStats: function clearStats(aNetworks, aResultCb) {
- let index = 0;
- let stats = [];
- let self = this;
-
- let callback = function(aError, aResult) {
- index++;
-
- if (!aError && index < aNetworks.length) {
- self.clearInterfaceStats(aNetworks[index], callback);
- return;
- }
-
- aResultCb(aError, aResult);
- };
-
- if (!aNetworks[index]) {
- aResultCb(null, true);
- return;
- }
- this.clearInterfaceStats(aNetworks[index], callback);
- },
-
- getCurrentStats: function getCurrentStats(aNetwork, aDate, aResultCb) {
- if (DEBUG) {
- debug("Get current stats for " + JSON.stringify(aNetwork) + " since " + aDate);
- }
-
- let network = [aNetwork.id, aNetwork.type];
- if (aDate) {
- this._getCurrentStatsFromDate(network, aDate, aResultCb);
- return;
- }
-
- this._getCurrentStats(network, aResultCb);
- },
-
- _getCurrentStats: function _getCurrentStats(aNetwork, aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
- let request = null;
- let upperFilter = [0, 1, "", aNetwork, Date.now()];
- let range = IDBKeyRange.upperBound(upperFilter, false);
- let result = { rxBytes: 0, txBytes: 0,
- rxTotalBytes: 0, txTotalBytes: 0 };
-
- request = store.openCursor(range, "prev");
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
- result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
- }
-
- txn.result = result;
- };
- }.bind(this), aResultCb);
- },
-
- _getCurrentStatsFromDate: function _getCurrentStatsFromDate(aNetwork, aDate, aResultCb) {
- aDate = new Date(aDate);
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
- let request = null;
- let start = this.normalizeDate(aDate);
- let upperFilter = [0, 1, "", aNetwork, Date.now()];
- let range = IDBKeyRange.upperBound(upperFilter, false);
- let result = { rxBytes: 0, txBytes: 0,
- rxTotalBytes: 0, txTotalBytes: 0 };
-
- request = store.openCursor(range, "prev");
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
- result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
- }
-
- let timestamp = cursor.value.timestamp;
- let range = IDBKeyRange.lowerBound(lowerFilter, false);
- request = store.openCursor(range);
-
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.value.timestamp == timestamp) {
- // There is one sample only.
- result.rxBytes = cursor.value.rxBytes;
- result.txBytes = cursor.value.txBytes;
- } else {
- result.rxBytes -= cursor.value.rxTotalBytes;
- result.txBytes -= cursor.value.txTotalBytes;
- }
- }
-
- txn.result = result;
- };
- };
- }.bind(this), aResultCb);
- },
-
- find: function find(aResultCb, aAppId, aBrowsingTrafficOnly, aServiceType,
- aNetwork, aStart, aEnd, aAppManifestURL) {
- let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
- let start = this.normalizeDate(aStart);
- let end = this.normalizeDate(aEnd);
-
- if (DEBUG) {
- debug("Find samples for appId: " + aAppId +
- " browsingTrafficOnly: " + aBrowsingTrafficOnly +
- " serviceType: " + aServiceType +
- " network: " + JSON.stringify(aNetwork) + " from " + start +
- " until " + end);
- debug("Start time: " + new Date(start));
- debug("End time: " + new Date(end));
- }
-
- // Find samples of browsing traffic (isInBrowser = 1) first since they are
- // needed no matter browsingTrafficOnly is true or false.
- // We have to make two queries to database because we cannot filter correct
- // records by a single query that sets ranges for two keys (isInBrowser and
- // timestamp). We think it is because the keyPath contains an array
- // (network) so such query does not work.
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- let network = [aNetwork.id, aNetwork.type];
- let lowerFilter = [aAppId, 1, aServiceType, network, start];
- let upperFilter = [aAppId, 1, aServiceType, network, end];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
-
- let data = [];
-
- if (!aTxn.result) {
- aTxn.result = {};
- }
- aTxn.result.appManifestURL = aAppManifestURL;
- aTxn.result.browsingTrafficOnly = aBrowsingTrafficOnly;
- aTxn.result.serviceType = aServiceType;
- aTxn.result.network = aNetwork;
- aTxn.result.start = aStart;
- aTxn.result.end = aEnd;
-
- let request = aStore.openCursor(range).onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor){
- // We use rxTotalBytes/txTotalBytes instead of rxBytes/txBytes for
- // the first (oldest) sample. The rx/txTotalBytes fields record
- // accumulative usage amount, which means even if old samples were
- // expired and removed from the Database, we can still obtain the
- // correct network usage.
- if (data.length == 0) {
- data.push({ rxBytes: cursor.value.rxTotalBytes,
- txBytes: cursor.value.txTotalBytes,
- date: new Date(cursor.value.timestamp + offset) });
- } else {
- data.push({ rxBytes: cursor.value.rxBytes,
- txBytes: cursor.value.txBytes,
- date: new Date(cursor.value.timestamp + offset) });
- }
- cursor.continue();
- return;
- }
-
- if (aBrowsingTrafficOnly) {
- this.fillResultSamples(start + offset, end + offset, data);
- aTxn.result.data = data;
- return;
- }
-
- // Find samples of app traffic (isInBrowser = 0) as well if
- // browsingTrafficOnly is false.
- lowerFilter = [aAppId, 0, aServiceType, network, start];
- upperFilter = [aAppId, 0, aServiceType, network, end];
- range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
- request = aStore.openCursor(range).onsuccess = function(event) {
- cursor = event.target.result;
- if (cursor) {
- var date = new Date(cursor.value.timestamp + offset);
- var foundData = data.find(function (element, index, array) {
- if (element.date.getTime() !== date.getTime()) {
- return false;
- }
- return element;
- }, date);
-
- if (foundData) {
- foundData.rxBytes += cursor.value.rxBytes;
- foundData.txBytes += cursor.value.txBytes;
- } else {
- // We use rxTotalBytes/txTotalBytes instead of rxBytes/txBytes
- // for the first (oldest) sample. The rx/txTotalBytes fields
- // record accumulative usage amount, which means even if old
- // samples were expired and removed from the Database, we can
- // still obtain the correct network usage.
- if (data.length == 0) {
- data.push({ rxBytes: cursor.value.rxTotalBytes,
- txBytes: cursor.value.txTotalBytes,
- date: new Date(cursor.value.timestamp + offset) });
- } else {
- data.push({ rxBytes: cursor.value.rxBytes,
- txBytes: cursor.value.txBytes,
- date: new Date(cursor.value.timestamp + offset) });
- }
- }
- cursor.continue();
- return;
- }
- this.fillResultSamples(start + offset, end + offset, data);
- aTxn.result.data = data;
- }.bind(this); // openCursor(range).onsuccess() callback
- }.bind(this); // openCursor(range).onsuccess() callback
- }.bind(this), aResultCb);
- },
-
- /*
- * Fill data array (samples from database) with empty samples to match
- * requested start / end dates.
- */
- fillResultSamples: function fillResultSamples(aStart, aEnd, aData) {
- if (aData.length == 0) {
- aData.push({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aStart) });
- }
-
- while (aStart < aData[0].date.getTime()) {
- aData.unshift({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aData[0].date.getTime() - SAMPLE_RATE) });
- }
-
- while (aEnd > aData[aData.length - 1].date.getTime()) {
- aData.push({ rxBytes: undefined,
- txBytes: undefined,
- date: new Date(aData[aData.length - 1].date.getTime() + SAMPLE_RATE) });
- }
- },
-
- getAvailableNetworks: function getAvailableNetworks(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = [];
- }
-
- let request = aStore.index("network").openKeyCursor(null, "nextunique");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- aTxn.result.push({ id: cursor.key[0],
- type: cursor.key[1] });
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- },
-
- isNetworkAvailable: function isNetworkAvailable(aNetwork, aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = false;
- }
-
- let network = [aNetwork.id, aNetwork.type];
- let request = aStore.index("network").openKeyCursor(IDBKeyRange.only(network));
- request.onsuccess = function onsuccess(event) {
- if (event.target.result) {
- aTxn.result = true;
- }
- };
- }, aResultCb);
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- if (!aTxn.result) {
- aTxn.result = [];
- }
-
- let request = aStore.index("serviceType").openKeyCursor(null, "nextunique");
- request.onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor && cursor.key != "") {
- aTxn.result.push({ serviceType: cursor.key });
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- },
-
- get sampleRate () {
- return SAMPLE_RATE;
- },
-
- get maxStorageSamples () {
- return VALUES_MAX_LENGTH;
- },
-
- logAllRecords: function logAllRecords(aResultCb) {
- this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
- aStore.mozGetAll().onsuccess = function onsuccess(event) {
- aTxn.result = event.target.result;
- };
- }, aResultCb);
- },
-
- alarmToRecord: function alarmToRecord(aAlarm) {
- let record = { networkId: aAlarm.networkId,
- absoluteThreshold: aAlarm.absoluteThreshold,
- relativeThreshold: aAlarm.relativeThreshold,
- startTime: aAlarm.startTime,
- data: aAlarm.data,
- manifestURL: aAlarm.manifestURL,
- pageURL: aAlarm.pageURL };
-
- if (aAlarm.id) {
- record.id = aAlarm.id;
- }
-
- return record;
- },
-
- recordToAlarm: function recordToalarm(aRecord) {
- let alarm = { networkId: aRecord.networkId,
- absoluteThreshold: aRecord.absoluteThreshold,
- relativeThreshold: aRecord.relativeThreshold,
- startTime: aRecord.startTime,
- data: aRecord.data,
- manifestURL: aRecord.manifestURL,
- pageURL: aRecord.pageURL };
-
- if (aRecord.id) {
- alarm.id = aRecord.id;
- }
-
- return alarm;
- },
-
- addAlarm: function addAlarm(aAlarm, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Going to add " + JSON.stringify(aAlarm));
- }
-
- let record = this.alarmToRecord(aAlarm);
- store.put(record).onsuccess = function setResult(aEvent) {
- txn.result = aEvent.target.result;
- if (DEBUG) {
- debug("Request successful. New record ID: " + txn.result);
- }
- };
- }.bind(this), aResultCb);
- },
-
- getFirstAlarm: function getFirstAlarm(aNetworkId, aResultCb) {
- let self = this;
-
- this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
- if (DEBUG) {
- debug("Get first alarm for network " + aNetworkId);
- }
-
- let lowerFilter = [aNetworkId, 0];
- let upperFilter = [aNetworkId, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter);
-
- store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- txn.result = null;
- if (cursor) {
- txn.result = self.recordToAlarm(cursor.value);
- }
- };
- }, aResultCb);
- },
-
- removeAlarm: function removeAlarm(aAlarmId, aManifestURL, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Remove alarm " + aAlarmId);
- }
-
- store.get(aAlarmId).onsuccess = function onsuccess(event) {
- let record = event.target.result;
- txn.result = false;
- if (!record || (aManifestURL && record.manifestURL != aManifestURL)) {
- return;
- }
-
- store.delete(aAlarmId);
- txn.result = true;
- }
- }, aResultCb);
- },
-
- removeAlarms: function removeAlarms(aManifestURL, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Remove alarms of " + aManifestURL);
- }
-
- store.index("manifestURL").openCursor(aManifestURL)
- .onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- cursor.delete();
- cursor.continue();
- }
- }
- }, aResultCb);
- },
-
- updateAlarm: function updateAlarm(aAlarm, aResultCb) {
- let self = this;
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Update alarm " + aAlarm.id);
- }
-
- let record = self.alarmToRecord(aAlarm);
- store.openCursor(record.id).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- txn.result = false;
- if (cursor) {
- cursor.update(record);
- txn.result = true;
- }
- }
- }, aResultCb);
- },
-
- getAlarms: function getAlarms(aNetworkId, aManifestURL, aResultCb) {
- let self = this;
- this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
- if (DEBUG) {
- debug("Get alarms for " + aManifestURL);
- }
-
- txn.result = [];
- store.index("manifestURL").openCursor(aManifestURL)
- .onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (!cursor) {
- return;
- }
-
- if (!aNetworkId || cursor.value.networkId == aNetworkId) {
- txn.result.push(self.recordToAlarm(cursor.value));
- }
-
- cursor.continue();
- }
- }, aResultCb);
- },
-
- _resetAlarms: function _resetAlarms(aNetworkId, aResultCb) {
- this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
- if (DEBUG) {
- debug("Reset alarms for network " + aNetworkId);
- }
-
- let lowerFilter = [aNetworkId, 0];
- let upperFilter = [aNetworkId, ""];
- let range = IDBKeyRange.bound(lowerFilter, upperFilter);
-
- store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
- let cursor = event.target.result;
- if (cursor) {
- if (cursor.value.startTime) {
- cursor.value.relativeThreshold = cursor.value.threshold;
- cursor.update(cursor.value);
- }
- cursor.continue();
- return;
- }
- };
- }, aResultCb);
- }
-};
diff --git a/dom/network/NetworkStatsManager.js b/dom/network/NetworkStatsManager.js
deleted file mode 100644
index b963aba2b..000000000
--- a/dom/network/NetworkStatsManager.js
+++ /dev/null
@@ -1,388 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsManager: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-// Ensure NetworkStatsService and NetworkStatsDB are loaded in the parent process
-// to receive messages from the child processes.
-var appInfo = Cc["@mozilla.org/xre/app-info;1"];
-var isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
- .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-if (isParentProcess) {
- Cu.import("resource://gre/modules/NetworkStatsService.jsm");
-}
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsISyncMessageSender");
-
-// NetworkStatsData
-const nsIClassInfo = Ci.nsIClassInfo;
-const NETWORKSTATSDATA_CID = Components.ID("{3b16fe17-5583-483a-b486-b64a3243221c}");
-
-function NetworkStatsData(aWindow, aData) {
- this.rxBytes = aData.rxBytes;
- this.txBytes = aData.txBytes;
- this.date = new aWindow.Date(aData.date.getTime());
-}
-
-NetworkStatsData.prototype = {
- classID : NETWORKSTATSDATA_CID,
-
- QueryInterface : XPCOMUtils.generateQI([])
-};
-
-// NetworkStatsInterface
-const NETWORKSTATSINTERFACE_CONTRACTID = "@mozilla.org/networkstatsinterface;1";
-const NETWORKSTATSINTERFACE_CID = Components.ID("{f540615b-d803-43ff-8200-2a9d145a5645}");
-
-function NetworkStatsInterface() {
- if (DEBUG) {
- debug("NetworkStatsInterface Constructor");
- }
-}
-
-NetworkStatsInterface.prototype = {
- __init: function(aNetwork) {
- this.type = aNetwork.type;
- this.id = aNetwork.id;
- },
-
- classID : NETWORKSTATSINTERFACE_CID,
-
- contractID: NETWORKSTATSINTERFACE_CONTRACTID,
- QueryInterface : XPCOMUtils.generateQI([])
-}
-
-// NetworkStats
-const NETWORKSTATS_CID = Components.ID("{28904f59-8497-4ac0-904f-2af14b7fd3de}");
-
-function NetworkStats(aWindow, aStats) {
- if (DEBUG) {
- debug("NetworkStats Constructor");
- }
- this.appManifestURL = aStats.appManifestURL || null;
- this.browsingTrafficOnly = aStats.browsingTrafficOnly || false;
- this.serviceType = aStats.serviceType || null;
- this.network = new aWindow.MozNetworkStatsInterface(aStats.network);
- this.start = aStats.start ? new aWindow.Date(aStats.start.getTime()) : null;
- this.end = aStats.end ? new aWindow.Date(aStats.end.getTime()) : null;
-
- let samples = this.data = new aWindow.Array();
- for (let i = 0; i < aStats.data.length; i++) {
- samples.push(aWindow.MozNetworkStatsData._create(
- aWindow, new NetworkStatsData(aWindow, aStats.data[i])));
- }
-}
-
-NetworkStats.prototype = {
- classID : NETWORKSTATS_CID,
-
- QueryInterface : XPCOMUtils.generateQI()
-}
-
-// NetworkStatsAlarm
-const NETWORKSTATSALARM_CID = Components.ID("{a93ea13e-409c-4189-9b1e-95fff220be55}");
-
-function NetworkStatsAlarm(aWindow, aAlarm) {
- this.alarmId = aAlarm.id;
- this.network = new aWindow.MozNetworkStatsInterface(aAlarm.network);
- this.threshold = aAlarm.threshold;
- this.data = aAlarm.data;
-}
-
-NetworkStatsAlarm.prototype = {
- classID : NETWORKSTATSALARM_CID,
-
- QueryInterface : XPCOMUtils.generateQI([])
-};
-
-// NetworkStatsManager
-
-const NETWORKSTATSMANAGER_CONTRACTID = "@mozilla.org/networkStatsManager;1";
-const NETWORKSTATSMANAGER_CID = Components.ID("{ceb874cd-cc1a-4e65-b404-cc2d3e42425f}");
-
-function NetworkStatsManager() {
- if (DEBUG) {
- debug("Constructor");
- }
-}
-
-NetworkStatsManager.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- getSamples: function getSamples(aNetwork, aStart, aEnd, aOptions) {
- if (aStart > aEnd) {
- throw Components.results.NS_ERROR_INVALID_ARG;
- }
-
- // appManifestURL is used to query network statistics by app;
- // serviceType is used to query network statistics by system service.
- // It is illegal to specify both of them at the same time.
- if (aOptions.appManifestURL && aOptions.serviceType) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
- // browsingTrafficOnly is meaningful only when querying by app.
- if (!aOptions.appManifestURL && aOptions.browsingTrafficOnly) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
-
- let appManifestURL = aOptions.appManifestURL;
- let serviceType = aOptions.serviceType;
- let browsingTrafficOnly = aOptions.browsingTrafficOnly;
-
- // TODO Bug 929410 Date object cannot correctly pass through cpmm/ppmm IPC
- // This is just a work-around by passing timestamp numbers.
- aStart = aStart.getTime();
- aEnd = aEnd.getTime();
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:Get",
- { network: aNetwork.toJSON(),
- start: aStart,
- end: aEnd,
- appManifestURL: appManifestURL,
- browsingTrafficOnly: browsingTrafficOnly,
- serviceType: serviceType,
- id: this.getRequestId(request) });
- return request;
- },
-
- clearStats: function clearStats(aNetwork) {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:Clear",
- { network: aNetwork.toJSON(),
- id: this.getRequestId(request) });
- return request;
- },
-
- clearAllStats: function clearAllStats() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:ClearAll",
- {id: this.getRequestId(request)});
- return request;
- },
-
- addAlarm: function addAlarm(aNetwork, aThreshold, aOptions) {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:SetAlarm",
- {id: this.getRequestId(request),
- data: {network: aNetwork.toJSON(),
- threshold: aThreshold,
- startTime: aOptions.startTime,
- data: aOptions.data,
- manifestURL: this.manifestURL,
- pageURL: this.pageURL}});
- return request;
- },
-
- getAllAlarms: function getAllAlarms(aNetwork) {
- let network = null;
- if (aNetwork) {
- network = aNetwork.toJSON();
- }
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAlarms",
- {id: this.getRequestId(request),
- data: {network: network,
- manifestURL: this.manifestURL}});
- return request;
- },
-
- removeAlarms: function removeAlarms(aAlarmId) {
- if (aAlarmId == 0) {
- aAlarmId = -1;
- }
-
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:RemoveAlarms",
- {id: this.getRequestId(request),
- data: {alarmId: aAlarmId,
- manifestURL: this.manifestURL}});
-
- return request;
- },
-
- getAvailableNetworks: function getAvailableNetworks() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAvailableNetworks",
- { id: this.getRequestId(request) });
- return request;
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes() {
- let request = this.createRequest();
- cpmm.sendAsyncMessage("NetworkStats:GetAvailableServiceTypes",
- { id: this.getRequestId(request) });
- return request;
- },
-
- get sampleRate() {
- return cpmm.sendSyncMessage("NetworkStats:SampleRate")[0];
- },
-
- get maxStorageAge() {
- return cpmm.sendSyncMessage("NetworkStats:MaxStorageAge")[0];
- },
-
- receiveMessage: function(aMessage) {
- if (DEBUG) {
- debug("NetworkStatsmanager::receiveMessage: " + aMessage.name);
- }
-
- let msg = aMessage.json;
- let req = this.takeRequest(msg.id);
- if (!req) {
- if (DEBUG) {
- debug("No request stored with id " + msg.id);
- }
- return;
- }
-
- switch (aMessage.name) {
- case "NetworkStats:Get:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let result = this._window.MozNetworkStats._create(
- this._window, new NetworkStats(this._window, msg.result));
- if (DEBUG) {
- debug("result: " + JSON.stringify(result));
- }
- Services.DOMRequest.fireSuccess(req, result);
- break;
-
- case "NetworkStats:GetAvailableNetworks:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let networks = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- let network = new this._window.MozNetworkStatsInterface(msg.result[i]);
- networks.push(network);
- }
-
- Services.DOMRequest.fireSuccess(req, networks);
- break;
-
- case "NetworkStats:GetAvailableServiceTypes:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let serviceTypes = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- serviceTypes.push(msg.result[i]);
- }
-
- Services.DOMRequest.fireSuccess(req, serviceTypes);
- break;
-
- case "NetworkStats:Clear:Return":
- case "NetworkStats:ClearAll:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- Services.DOMRequest.fireSuccess(req, true);
- break;
-
- case "NetworkStats:SetAlarm:Return":
- case "NetworkStats:RemoveAlarms:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- Services.DOMRequest.fireSuccess(req, msg.result);
- break;
-
- case "NetworkStats:GetAlarms:Return":
- if (msg.error) {
- Services.DOMRequest.fireError(req, msg.error);
- return;
- }
-
- let alarms = new this._window.Array();
- for (let i = 0; i < msg.result.length; i++) {
- // The WebIDL type of data is any, so we should manually clone it
- // into the content window.
- if ("data" in msg.result[i]) {
- msg.result[i].data = Cu.cloneInto(msg.result[i].data, this._window);
- }
- let alarm = new NetworkStatsAlarm(this._window, msg.result[i]);
- alarms.push(this._window.MozNetworkStatsAlarm._create(this._window, alarm));
- }
-
- Services.DOMRequest.fireSuccess(req, alarms);
- break;
-
- default:
- if (DEBUG) {
- debug("Wrong message: " + aMessage.name);
- }
- }
- },
-
- init: function(aWindow) {
- let principal = aWindow.document.nodePrincipal;
-
- this.initDOMRequestHelper(aWindow, ["NetworkStats:Get:Return",
- "NetworkStats:GetAvailableNetworks:Return",
- "NetworkStats:GetAvailableServiceTypes:Return",
- "NetworkStats:Clear:Return",
- "NetworkStats:ClearAll:Return",
- "NetworkStats:SetAlarm:Return",
- "NetworkStats:GetAlarms:Return",
- "NetworkStats:RemoveAlarms:Return"]);
-
- // Init app properties.
- let appsService = Cc["@mozilla.org/AppsService;1"]
- .getService(Ci.nsIAppsService);
-
- this.manifestURL = appsService.getManifestURLByLocalId(principal.appId);
-
- let isApp = !!this.manifestURL.length;
- if (isApp) {
- this.pageURL = principal.URI.spec;
- }
-
- this.window = aWindow;
- },
-
- // Called from DOMRequestIpcHelper
- uninit: function uninit() {
- if (DEBUG) {
- debug("uninit call");
- }
- },
-
- classID : NETWORKSTATSMANAGER_CID,
- contractID : NETWORKSTATSMANAGER_CONTRACTID,
- QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsAlarm,
- NetworkStatsData,
- NetworkStatsInterface,
- NetworkStats,
- NetworkStatsManager]);
diff --git a/dom/network/NetworkStatsManager.manifest b/dom/network/NetworkStatsManager.manifest
deleted file mode 100644
index 8e8700910..000000000
--- a/dom/network/NetworkStatsManager.manifest
+++ /dev/null
@@ -1,14 +0,0 @@
-component {3b16fe17-5583-483a-b486-b64a3243221c} NetworkStatsManager.js
-contract @mozilla.org/networkStatsdata;1 {3b16fe17-5583-483a-b486-b64a3243221c}
-
-component {28904f59-8497-4ac0-904f-2af14b7fd3de} NetworkStatsManager.js
-contract @mozilla.org/networkStats;1 {28904f59-8497-4ac0-904f-2af14b7fd3de}
-
-component {f540615b-d803-43ff-8200-2a9d145a5645} NetworkStatsManager.js
-contract @mozilla.org/networkstatsinterface;1 {f540615b-d803-43ff-8200-2a9d145a5645}
-
-component {a93ea13e-409c-4189-9b1e-95fff220be55} NetworkStatsManager.js
-contract @mozilla.org/networkstatsalarm;1 {a93ea13e-409c-4189-9b1e-95fff220be55}
-
-component {ceb874cd-cc1a-4e65-b404-cc2d3e42425f} NetworkStatsManager.js
-contract @mozilla.org/networkStatsManager;1 {ceb874cd-cc1a-4e65-b404-cc2d3e42425f}
diff --git a/dom/network/NetworkStatsService.jsm b/dom/network/NetworkStatsService.jsm
deleted file mode 100644
index 4b6d69498..000000000
--- a/dom/network/NetworkStatsService.jsm
+++ /dev/null
@@ -1,1171 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) {
- if (DEBUG) {
- dump("-*- NetworkStatsService: " + s + "\n");
- }
-}
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["NetworkStatsService"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetworkStatsDB.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
-
-const NET_NETWORKSTATSSERVICE_CONTRACTID = "@mozilla.org/network/netstatsservice;1";
-const NET_NETWORKSTATSSERVICE_CID = Components.ID("{18725604-e9ac-488a-8aa0-2471e7f6c0a4}");
-
-const TOPIC_BANDWIDTH_CONTROL = "netd-bandwidth-control"
-
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const NET_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NET_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-
-// Networks have different status that NetworkStats API needs to be aware of.
-// Network is present and ready, so NetworkManager provides the whole info.
-const NETWORK_STATUS_READY = 0;
-// Network is present but hasn't established a connection yet (e.g. SIM that has not
-// enabled 3G since boot).
-const NETWORK_STATUS_STANDBY = 1;
-// Network is not present, but stored in database by the previous connections.
-const NETWORK_STATUS_AWAY = 2;
-
-// The maximum traffic amount can be saved in the |cachedStats|.
-const MAX_CACHED_TRAFFIC = 500 * 1000 * 1000; // 500 MB
-
-const QUEUE_TYPE_UPDATE_STATS = 0;
-const QUEUE_TYPE_UPDATE_CACHE = 1;
-const QUEUE_TYPE_WRITE_CACHE = 2;
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageListenerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gRil",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
-XPCOMUtils.defineLazyServiceGetter(this, "networkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
- "@mozilla.org/AppsService;1",
- "nsIAppsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "messenger",
- "@mozilla.org/system-message-internal;1",
- "nsISystemMessagesInternal");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-this.NetworkStatsService = {
- init: function() {
- debug("Service started");
-
- Services.obs.addObserver(this, "xpcom-shutdown", false);
- Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
- Services.obs.addObserver(this, TOPIC_BANDWIDTH_CONTROL, false);
- Services.obs.addObserver(this, "profile-after-change", false);
-
- this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- // Object to store network interfaces, each network interface is composed
- // by a network object (network type and network Id) and a interfaceName
- // that contains the name of the physical interface (wlan0, rmnet0, etc.).
- // The network type can be 0 for wifi or 1 for mobile. On the other hand,
- // the network id is '0' for wifi or the iccid for mobile (SIM).
- // Each networkInterface is placed in the _networks object by the index of
- // 'networkId + networkType'.
- //
- // _networks object allows to map available network interfaces at low level
- // (wlan0, rmnet0, etc.) to a network. It's not mandatory to have a
- // networkInterface per network but can't exist a networkInterface not
- // being mapped to a network.
-
- this._networks = Object.create(null);
-
- // There is no way to know a priori if wifi connection is available,
- // just when the wifi driver is loaded, but it is unloaded when
- // wifi is switched off. So wifi connection is hardcoded
- let netId = this.getNetworkId('0', NET_TYPE_WIFI);
- this._networks[netId] = { network: { id: '0',
- type: NET_TYPE_WIFI },
- interfaceName: null,
- status: NETWORK_STATUS_STANDBY };
-
- this.messages = ["NetworkStats:Get",
- "NetworkStats:Clear",
- "NetworkStats:ClearAll",
- "NetworkStats:SetAlarm",
- "NetworkStats:GetAlarms",
- "NetworkStats:RemoveAlarms",
- "NetworkStats:GetAvailableNetworks",
- "NetworkStats:GetAvailableServiceTypes",
- "NetworkStats:SampleRate",
- "NetworkStats:MaxStorageAge"];
-
- this.messages.forEach(function(aMsgName) {
- ppmm.addMessageListener(aMsgName, this);
- }, this);
-
- this._db = new NetworkStatsDB();
-
- // Stats for all interfaces are updated periodically
- this.timer.initWithCallback(this, this._db.sampleRate,
- Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
-
- // Stats not from netd are firstly stored in the cached.
- this.cachedStats = Object.create(null);
- this.cachedStatsDate = new Date();
-
- this.updateQueue = [];
- this.isQueueRunning = false;
-
- this._currentAlarms = {};
- this.initAlarms();
- },
-
- receiveMessage: function(aMessage) {
- if (!aMessage.target.assertPermission("networkstats-manage")) {
- return;
- }
-
- debug("receiveMessage " + aMessage.name);
-
- let mm = aMessage.target;
- let msg = aMessage.json;
-
- switch (aMessage.name) {
- case "NetworkStats:Get":
- this.getSamples(mm, msg);
- break;
- case "NetworkStats:Clear":
- this.clearInterfaceStats(mm, msg);
- break;
- case "NetworkStats:ClearAll":
- this.clearDB(mm, msg);
- break;
- case "NetworkStats:SetAlarm":
- this.setAlarm(mm, msg);
- break;
- case "NetworkStats:GetAlarms":
- this.getAlarms(mm, msg);
- break;
- case "NetworkStats:RemoveAlarms":
- this.removeAlarms(mm, msg);
- break;
- case "NetworkStats:GetAvailableNetworks":
- this.getAvailableNetworks(mm, msg);
- break;
- case "NetworkStats:GetAvailableServiceTypes":
- this.getAvailableServiceTypes(mm, msg);
- break;
- case "NetworkStats:SampleRate":
- // This message is sync.
- return this._db.sampleRate;
- case "NetworkStats:MaxStorageAge":
- // This message is sync.
- return this._db.maxStorageSamples * this._db.sampleRate;
- }
- },
-
- observe: function observe(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_CONNECTION_STATE_CHANGED:
-
- // If new interface is registered (notified from NetworkService),
- // the stats are updated for the new interface without waiting to
- // complete the updating period.
-
- let networkInfo = aSubject.QueryInterface(Ci.nsINetworkInfo);
- debug("Network " + networkInfo.name + " of type " + networkInfo.type + " status change");
-
- let netId = this.convertNetworkInfo(networkInfo);
- if (!netId) {
- break;
- }
-
- this._updateCurrentAlarm(netId);
-
- debug("NetId: " + netId);
- this.updateStats(netId);
- break;
-
- case TOPIC_BANDWIDTH_CONTROL:
- debug("Bandwidth message from netd: " + JSON.stringify(aData));
-
- let interfaceName = aData.substring(aData.lastIndexOf(" ") + 1);
- for (let networkId in this._networks) {
- if (interfaceName == this._networks[networkId].interfaceName) {
- let currentAlarm = this._currentAlarms[networkId];
- if (Object.getOwnPropertyNames(currentAlarm).length !== 0) {
- this._fireAlarm(currentAlarm.alarm);
- }
- break;
- }
- }
- break;
-
- case "xpcom-shutdown":
- debug("Service shutdown");
-
- this.messages.forEach(function(aMsgName) {
- ppmm.removeMessageListener(aMsgName, this);
- }, this);
-
- Services.obs.removeObserver(this, "xpcom-shutdown");
- Services.obs.removeObserver(this, "profile-after-change");
- Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
- Services.obs.removeObserver(this, TOPIC_BANDWIDTH_CONTROL);
-
- this.timer.cancel();
- this.timer = null;
-
- // Update stats before shutdown
- this.updateAllStats();
- break;
- }
- },
-
- /*
- * nsITimerCallback
- * Timer triggers the update of all stats
- */
- notify: function(aTimer) {
- this.updateAllStats();
- },
-
- /*
- * nsINetworkStatsService
- */
- getRilNetworks: function() {
- let networks = {};
- let numRadioInterfaces = gRil.numRadioInterfaces;
- for (let i = 0; i < numRadioInterfaces; i++) {
- let icc = gIccService.getIccByServiceId(i);
- let radioInterface = gRil.getRadioInterface(i);
- if (icc && icc.iccInfo) {
- let netId = this.getNetworkId(icc.iccInfo.iccid,
- NET_TYPE_MOBILE);
- networks[netId] = { id : icc.iccInfo.iccid,
- type: NET_TYPE_MOBILE };
- }
- }
- return networks;
- },
-
- convertNetworkInfo: function(aNetworkInfo) {
- if (aNetworkInfo.type != NET_TYPE_MOBILE &&
- aNetworkInfo.type != NET_TYPE_WIFI) {
- return null;
- }
-
- let id = '0';
- if (aNetworkInfo.type == NET_TYPE_MOBILE) {
- if (!(aNetworkInfo instanceof Ci.nsIRilNetworkInfo)) {
- debug("Error! Mobile network should be an nsIRilNetworkInfo!");
- return null;
- }
-
- let rilNetwork = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- id = rilNetwork.iccId;
- }
-
- let netId = this.getNetworkId(id, aNetworkInfo.type);
-
- if (!this._networks[netId]) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = { id: id,
- type: aNetworkInfo.type };
- }
-
- this._networks[netId].status = NETWORK_STATUS_READY;
- this._networks[netId].interfaceName = aNetworkInfo.name;
- return netId;
- },
-
- getNetworkId: function getNetworkId(aIccId, aNetworkType) {
- return aIccId + '' + aNetworkType;
- },
-
- /* Function to ensure that one network is valid. The network is valid if its status is
- * NETWORK_STATUS_READY, NETWORK_STATUS_STANDBY or NETWORK_STATUS_AWAY.
- *
- * The result is |netId| or null in case of a non-valid network
- * aCallback is signatured as |function(netId)|.
- */
- validateNetwork: function validateNetwork(aNetwork, aCallback) {
- let netId = this.getNetworkId(aNetwork.id, aNetwork.type);
-
- if (this._networks[netId]) {
- aCallback(netId);
- return;
- }
-
- // Check if network is valid (RIL entry) but has not established a connection yet.
- // If so add to networks list with empty interfaceName.
- let rilNetworks = this.getRilNetworks();
- if (rilNetworks[netId]) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = rilNetworks[netId];
- this._networks[netId].status = NETWORK_STATUS_STANDBY;
- this._currentAlarms[netId] = Object.create(null);
- aCallback(netId);
- return;
- }
-
- // Check if network is available in the DB.
- this._db.isNetworkAvailable(aNetwork, function(aError, aResult) {
- if (aResult) {
- this._networks[netId] = Object.create(null);
- this._networks[netId].network = aNetwork;
- this._networks[netId].status = NETWORK_STATUS_AWAY;
- this._currentAlarms[netId] = Object.create(null);
- aCallback(netId);
- return;
- }
-
- aCallback(null);
- }.bind(this));
- },
-
- getAvailableNetworks: function getAvailableNetworks(mm, msg) {
- let self = this;
- let rilNetworks = this.getRilNetworks();
- this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
-
- // Also return the networks that are valid but have not
- // established connections yet.
- for (let netId in rilNetworks) {
- let found = false;
- for (let i = 0; i < aResult.length; i++) {
- if (netId == self.getNetworkId(aResult[i].id, aResult[i].type)) {
- found = true;
- break;
- }
- }
- if (!found) {
- aResult.push(rilNetworks[netId]);
- }
- }
-
- mm.sendAsyncMessage("NetworkStats:GetAvailableNetworks:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- },
-
- getAvailableServiceTypes: function getAvailableServiceTypes(mm, msg) {
- this._db.getAvailableServiceTypes(function onGetServiceTypes(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:GetAvailableServiceTypes:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- },
-
- initAlarms: function initAlarms() {
- debug("Init usage alarms");
- let self = this;
-
- for (let netId in this._networks) {
- this._currentAlarms[netId] = Object.create(null);
-
- this._db.getFirstAlarm(netId, function getResult(error, result) {
- if (!error && result) {
- self._setAlarm(result, function onSet(error, success) {
- if (error == "InvalidStateError") {
- self._fireAlarm(result);
- }
- });
- }
- });
- }
- },
-
- /*
- * Function called from manager to get stats from database.
- * In order to return updated stats, first is performed a call to
- * updateAllStats function, which will get last stats from netd
- * and update the database.
- * Then, depending on the request (stats per appId or total stats)
- * it retrieve them from database and return to the manager.
- */
- getSamples: function getSamples(mm, msg) {
- let network = msg.network;
- let netId = this.getNetworkId(network.id, network.type);
-
- let appId = 0;
- let appManifestURL = msg.appManifestURL;
- if (appManifestURL) {
- appId = appsService.getAppLocalIdByManifestURL(appManifestURL);
-
- if (!appId) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id,
- error: "Invalid appManifestURL", result: null });
- return;
- }
- }
-
- let browsingTrafficOnly = msg.browsingTrafficOnly || false;
- let serviceType = msg.serviceType || "";
-
- let start = new Date(msg.start);
- let end = new Date(msg.end);
-
- let callback = (function (aError, aResult) {
- this._db.find(function onStatsFound(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: aError, result: aResult });
- }, appId, browsingTrafficOnly, serviceType, network, start, end, appManifestURL);
- }).bind(this);
-
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: "Invalid connectionType", result: null });
- return;
- }
-
- // If network is currently active we need to update the cached stats first before
- // retrieving stats from the DB.
- if (this._networks[aNetId].status == NETWORK_STATUS_READY) {
- debug("getstats for network " + network.id + " of type " + network.type);
- debug("appId: " + appId + " from appManifestURL: " + appManifestURL);
- debug("browsingTrafficOnly: " + browsingTrafficOnly);
- debug("serviceType: " + serviceType);
-
- if (appId || serviceType) {
- this.updateCachedStats(callback);
- return;
- }
-
- this.updateStats(aNetId, function onStatsUpdated(aResult, aMessage) {
- this.updateCachedStats(callback);
- }.bind(this));
- return;
- }
-
- // Network not active, so no need to update
- this._db.find(function onStatsFound(aError, aResult) {
- mm.sendAsyncMessage("NetworkStats:Get:Return",
- { id: msg.id, error: aError, result: aResult });
- }, appId, browsingTrafficOnly, serviceType, network, start, end, appManifestURL);
- }.bind(this));
- },
-
- clearInterfaceStats: function clearInterfaceStats(mm, msg) {
- let self = this;
- let network = msg.network;
-
- debug("clear stats for network " + network.id + " of type " + network.type);
-
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: "Invalid connectionType", result: null });
- return;
- }
-
- network = {network: network, networkId: aNetId};
- self.updateStats(aNetId, function onUpdate(aResult, aMessage) {
- if (!aResult) {
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: aMessage, result: null });
- return;
- }
-
- self._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
- self._updateCurrentAlarm(aNetId);
- mm.sendAsyncMessage("NetworkStats:Clear:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- });
- });
- },
-
- clearDB: function clearDB(mm, msg) {
- let self = this;
- this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
- if (aError) {
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aError, result: aResult });
- return;
- }
-
- let networks = aResult;
- networks.forEach(function(network, index) {
- networks[index] = {network: network, networkId: self.getNetworkId(network.id, network.type)};
- }, self);
-
- self.updateAllStats(function onUpdate(aResult, aMessage){
- if (!aResult) {
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aMessage, result: null });
- return;
- }
-
- self._db.clearStats(networks, function onDBCleared(aError, aResult) {
- networks.forEach(function(network, index) {
- self._updateCurrentAlarm(network.networkId);
- }, self);
- mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
- { id: msg.id, error: aError, result: aResult });
- });
- });
- });
- },
-
- updateAllStats: function updateAllStats(aCallback) {
- let elements = [];
- let lastElement = null;
- let callback = (function (success, message) {
- this.updateCachedStats(aCallback);
- }).bind(this);
-
- // For each connectionType create an object containning the type
- // and the 'queueIndex', the 'queueIndex' is an integer representing
- // the index of a connection type in the global queue array. So, if
- // the connection type is already in the queue it is not appended again,
- // else it is pushed in 'elements' array, which later will be pushed to
- // the queue array.
- for (let netId in this._networks) {
- if (this._networks[netId].status != NETWORK_STATUS_READY) {
- continue;
- }
-
- lastElement = { netId: netId,
- queueIndex: this.updateQueueIndex(netId) };
-
- if (lastElement.queueIndex == -1) {
- elements.push({ netId: lastElement.netId,
- callbacks: [],
- queueType: QUEUE_TYPE_UPDATE_STATS });
- }
- }
-
- if (!lastElement) {
- // No elements need to be updated, probably because status is different than
- // NETWORK_STATUS_READY.
- if (aCallback) {
- aCallback(true, "OK");
- }
- return;
- }
-
- if (elements.length > 0) {
- // If length of elements is greater than 0, callback is set to
- // the last element.
- elements[elements.length - 1].callbacks.push(callback);
- this.updateQueue = this.updateQueue.concat(elements);
- } else {
- // Else, it means that all connection types are already in the queue to
- // be updated, so callback for this request is added to
- // the element in the main queue with the index of the last 'lastElement'.
- // But before is checked that element is still in the queue because it can
- // be processed while generating 'elements' array.
- let element = this.updateQueue[lastElement.queueIndex];
- if (aCallback &&
- (!element || element.netId != lastElement.netId)) {
- aCallback();
- return;
- }
-
- this.updateQueue[lastElement.queueIndex].callbacks.push(callback);
- }
-
- // Call the function that process the elements of the queue.
- this.processQueue();
-
- if (DEBUG) {
- this.logAllRecords();
- }
- },
-
- updateStats: function updateStats(aNetId, aCallback) {
- // Check if the connection is in the main queue, push a new element
- // if it is not being processed or add a callback if it is.
- let index = this.updateQueueIndex(aNetId);
- if (index == -1) {
- this.updateQueue.push({ netId: aNetId,
- callbacks: [aCallback],
- queueType: QUEUE_TYPE_UPDATE_STATS });
- } else {
- this.updateQueue[index].callbacks.push(aCallback);
- return;
- }
-
- // Call the function that process the elements of the queue.
- this.processQueue();
- },
-
- /*
- * Find if a connection is in the main queue array and return its
- * index, if it is not in the array return -1.
- */
- updateQueueIndex: function updateQueueIndex(aNetId) {
- return this.updateQueue.map(function(e) { return e.netId; }).indexOf(aNetId);
- },
-
- /*
- * Function responsible of process all requests in the queue.
- */
- processQueue: function processQueue(aResult, aMessage) {
- // If aResult is not undefined, the caller of the function is the result
- // of processing an element, so remove that element and call the callbacks
- // it has.
- let self = this;
-
- if (aResult != undefined) {
- let item = this.updateQueue.shift();
- for (let callback of item.callbacks) {
- if (callback) {
- callback(aResult, aMessage);
- }
- }
- } else {
- // The caller is a function that has pushed new elements to the queue,
- // if isQueueRunning is false it means there is no processing currently
- // being done, so start.
- if (this.isQueueRunning) {
- return;
- } else {
- this.isQueueRunning = true;
- }
- }
-
- // Check length to determine if queue is empty and stop processing.
- if (this.updateQueue.length < 1) {
- this.isQueueRunning = false;
- return;
- }
-
- // Process the next item as soon as possible.
- setTimeout(function () {
- self.run(self.updateQueue[0]);
- }, 0);
- },
-
- run: function run(item) {
- switch (item.queueType) {
- case QUEUE_TYPE_UPDATE_STATS:
- this.update(item.netId, this.processQueue.bind(this));
- break;
- case QUEUE_TYPE_UPDATE_CACHE:
- this.updateCache(this.processQueue.bind(this));
- break;
- case QUEUE_TYPE_WRITE_CACHE:
- this.writeCache(item.stats, this.processQueue.bind(this));
- break;
- }
- },
-
- update: function update(aNetId, aCallback) {
- // Check if connection type is valid.
- if (!this._networks[aNetId]) {
- if (aCallback) {
- aCallback(false, "Invalid network " + aNetId);
- }
- return;
- }
-
- let interfaceName = this._networks[aNetId].interfaceName;
- debug("Update stats for " + interfaceName);
-
- // Request stats to NetworkService, which will get stats from netd, passing
- // 'networkStatsAvailable' as a callback.
- if (interfaceName) {
- networkService.getNetworkInterfaceStats(interfaceName,
- this.networkStatsAvailable.bind(this, aCallback, aNetId));
- return;
- }
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- },
-
- /*
- * Callback of request stats. Store stats in database.
- */
- networkStatsAvailable: function networkStatsAvailable(aCallback, aNetId,
- aResult, aRxBytes,
- aTxBytes, aTimestamp) {
- if (!aResult) {
- if (aCallback) {
- aCallback(false, "Netd IPC error");
- }
- return;
- }
-
- let stats = { appId: 0,
- isInBrowser: false,
- serviceType: "",
- networkId: this._networks[aNetId].network.id,
- networkType: this._networks[aNetId].network.type,
- date: new Date(aTimestamp),
- rxBytes: aTxBytes,
- txBytes: aRxBytes,
- isAccumulative: true };
-
- debug("Update stats for: " + JSON.stringify(stats));
-
- this._db.saveStats(stats, function onSavedStats(aError, aResult) {
- if (aCallback) {
- if (aError) {
- aCallback(false, aError);
- return;
- }
-
- aCallback(true, "OK");
- }
- });
- },
-
- /*
- * Function responsible for receiving stats which are not from netd.
- */
- saveStats: function saveStats(aAppId, aIsInIsolatedMozBrowser, aServiceType,
- aNetworkInfo, aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback) {
- let netId = this.convertNetworkInfo(aNetworkInfo);
- if (!netId) {
- if (aCallback) {
- aCallback(false, "Invalid network type");
- }
- return;
- }
-
- // Check if |aConnectionType|, |aAppId| and |aServiceType| are valid.
- // There are two invalid cases for the combination of |aAppId| and
- // |aServiceType|:
- // a. Both |aAppId| is non-zero and |aServiceType| is non-empty.
- // b. Both |aAppId| is zero and |aServiceType| is empty.
- if (!this._networks[netId] || (aAppId && aServiceType) ||
- (!aAppId && !aServiceType)) {
- debug("Invalid network interface, appId or serviceType");
- return;
- }
-
- let stats = { appId: aAppId,
- isInBrowser: aIsInIsolatedMozBrowser,
- serviceType: aServiceType,
- networkId: this._networks[netId].network.id,
- networkType: this._networks[netId].network.type,
- date: new Date(aTimeStamp),
- rxBytes: aRxBytes,
- txBytes: aTxBytes,
- isAccumulative: aIsAccumulative };
-
- this.updateQueue.push({ stats: stats,
- callbacks: [aCallback],
- queueType: QUEUE_TYPE_WRITE_CACHE });
-
- this.processQueue();
- },
-
- /*
- *
- */
- writeCache: function writeCache(aStats, aCallback) {
- debug("saveStats: " + aStats.appId + " " + aStats.isInBrowser + " " +
- aStats.serviceType + " " + aStats.networkId + " " +
- aStats.networkType + " " + aStats.date + " " +
- aStats.rxBytes + " " + aStats.txBytes);
-
- // Generate an unique key from |appId|, |isInBrowser|, |serviceType| and
- // |netId|, which is used to retrieve data in |cachedStats|.
- let netId = this.getNetworkId(aStats.networkId, aStats.networkType);
- let key = aStats.appId + "" + aStats.isInBrowser + "" +
- aStats.serviceType + "" + netId;
-
- // |cachedStats| only keeps the data with the same date.
- // If the incoming date is different from |cachedStatsDate|,
- // both |cachedStats| and |cachedStatsDate| will get updated.
- let diff = (this._db.normalizeDate(aStats.date) -
- this._db.normalizeDate(this.cachedStatsDate)) /
- this._db.sampleRate;
- if (diff != 0) {
- this.updateCache(function onUpdated(success, message) {
- this.cachedStatsDate = aStats.date;
- this.cachedStats[key] = aStats;
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- }.bind(this));
- return;
- }
-
- // Try to find the matched row in the cached by |appId| and |connectionType|.
- // If not found, save the incoming data into the cached.
- let cachedStats = this.cachedStats[key];
- if (!cachedStats) {
- this.cachedStats[key] = aStats;
- if (aCallback) {
- aCallback(true, "ok");
- }
- return;
- }
-
- // Find matched row, accumulate the traffic amount.
- cachedStats.rxBytes += aStats.rxBytes;
- cachedStats.txBytes += aStats.txBytes;
-
- // If new rxBytes or txBytes exceeds MAX_CACHED_TRAFFIC
- // the corresponding row will be saved to indexedDB.
- // Then, the row will be removed from the cached.
- if (cachedStats.rxBytes > MAX_CACHED_TRAFFIC ||
- cachedStats.txBytes > MAX_CACHED_TRAFFIC) {
- this._db.saveStats(cachedStats, function (error, result) {
- debug("Application stats inserted in indexedDB");
- if (aCallback) {
- aCallback(true, "ok");
- }
- });
- delete this.cachedStats[key];
- return;
- }
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- },
-
- updateCachedStats: function updateCachedStats(aCallback) {
- this.updateQueue.push({ callbacks: [aCallback],
- queueType: QUEUE_TYPE_UPDATE_CACHE });
-
- this.processQueue();
- },
-
- updateCache: function updateCache(aCallback) {
- debug("updateCache: " + this.cachedStatsDate);
-
- let stats = Object.keys(this.cachedStats);
- if (stats.length == 0) {
- // |cachedStats| is empty, no need to update.
- if (aCallback) {
- aCallback(true, "no need to update");
- }
- return;
- }
-
- let index = 0;
- this._db.saveStats(this.cachedStats[stats[index]],
- function onSavedStats(error, result) {
- debug("Application stats inserted in indexedDB");
-
- // Clean up the |cachedStats| after updating.
- if (index == stats.length - 1) {
- this.cachedStats = Object.create(null);
-
- if (aCallback) {
- aCallback(true, "ok");
- }
- return;
- }
-
- // Update is not finished, keep updating.
- index += 1;
- this._db.saveStats(this.cachedStats[stats[index]],
- onSavedStats.bind(this, error, result));
- }.bind(this));
- },
-
- get maxCachedTraffic () {
- return MAX_CACHED_TRAFFIC;
- },
-
- logAllRecords: function logAllRecords() {
- this._db.logAllRecords(function onResult(aError, aResult) {
- if (aError) {
- debug("Error: " + aError);
- return;
- }
-
- debug("===== LOG =====");
- debug("There are " + aResult.length + " items");
- debug(JSON.stringify(aResult));
- });
- },
-
- getAlarms: function getAlarms(mm, msg) {
- let self = this;
- let network = msg.data.network;
- let manifestURL = msg.data.manifestURL;
-
- if (network) {
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: "InvalidInterface", result: null });
- return;
- }
-
- self._getAlarms(mm, msg, aNetId, manifestURL);
- });
- return;
- }
-
- this._getAlarms(mm, msg, null, manifestURL);
- },
-
- _getAlarms: function _getAlarms(mm, msg, aNetId, aManifestURL) {
- let self = this;
- this._db.getAlarms(aNetId, aManifestURL, function onCompleted(error, result) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: error, result: result });
- return;
- }
-
- let alarms = []
- // NetworkStatsManager must return the network instead of the networkId.
- for (let i = 0; i < result.length; i++) {
- let alarm = result[i];
- alarms.push({ id: alarm.id,
- network: self._networks[alarm.networkId].network,
- threshold: alarm.absoluteThreshold,
- data: alarm.data });
- }
-
- mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
- { id: msg.id, error: null, result: alarms });
- });
- },
-
- removeAlarms: function removeAlarms(mm, msg) {
- let alarmId = msg.data.alarmId;
- let manifestURL = msg.data.manifestURL;
-
- let self = this;
- let callback = function onRemove(error, result) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
- { id: msg.id, error: error, result: result });
- return;
- }
-
- for (let i in self._currentAlarms) {
- let currentAlarm = self._currentAlarms[i].alarm;
- if (currentAlarm && ((alarmId == currentAlarm.id) ||
- (alarmId == -1 && currentAlarm.manifestURL == manifestURL))) {
-
- self._updateCurrentAlarm(currentAlarm.networkId);
- }
- }
-
- mm.sendAsyncMessage("NetworkStats:RemoveAlarms:Return",
- { id: msg.id, error: error, result: true });
- };
-
- if (alarmId == -1) {
- this._db.removeAlarms(manifestURL, callback);
- } else {
- this._db.removeAlarm(alarmId, manifestURL, callback);
- }
- },
-
- /*
- * Function called from manager to set an alarm.
- */
- setAlarm: function setAlarm(mm, msg) {
- let options = msg.data;
- let network = options.network;
- let threshold = options.threshold;
-
- debug("Set alarm at " + threshold + " for " + JSON.stringify(network));
-
- if (threshold < 0) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: "InvalidThresholdValue", result: null });
- return;
- }
-
- let self = this;
- this.validateNetwork(network, function onValidateNetwork(aNetId) {
- if (!aNetId) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: "InvalidiConnectionType", result: null });
- return;
- }
-
- let newAlarm = {
- id: null,
- networkId: aNetId,
- absoluteThreshold: threshold,
- relativeThreshold: null,
- startTime: options.startTime,
- data: options.data,
- pageURL: options.pageURL,
- manifestURL: options.manifestURL
- };
-
- self._getAlarmQuota(newAlarm, function onUpdate(error, quota) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: null });
- return;
- }
-
- self._db.addAlarm(newAlarm, function addSuccessCb(error, newId) {
- if (error) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: null });
- return;
- }
-
- newAlarm.id = newId;
- self._setAlarm(newAlarm, function onSet(error, success) {
- mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
- { id: msg.id, error: error, result: newId });
-
- if (error == "InvalidStateError") {
- self._fireAlarm(newAlarm);
- }
- });
- });
- });
- });
- },
-
- _setAlarm: function _setAlarm(aAlarm, aCallback) {
- let currentAlarm = this._currentAlarms[aAlarm.networkId];
- if ((Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
- aAlarm.relativeThreshold > currentAlarm.alarm.relativeThreshold) ||
- this._networks[aAlarm.networkId].status != NETWORK_STATUS_READY) {
- aCallback(null, true);
- return;
- }
-
- let self = this;
-
- this._getAlarmQuota(aAlarm, function onUpdate(aError, aQuota) {
- if (aError) {
- aCallback(aError, null);
- return;
- }
-
- let callback = function onAlarmSet(aError) {
- if (aError) {
- debug("Set alarm error: " + aError);
- aCallback("netdError", null);
- return;
- }
-
- self._currentAlarms[aAlarm.networkId].alarm = aAlarm;
-
- aCallback(null, true);
- };
-
- debug("Set alarm " + JSON.stringify(aAlarm));
- let interfaceName = self._networks[aAlarm.networkId].interfaceName;
- if (interfaceName) {
- networkService.setNetworkInterfaceAlarm(interfaceName,
- aQuota,
- callback);
- return;
- }
-
- aCallback(null, true);
- });
- },
-
- _getAlarmQuota: function _getAlarmQuota(aAlarm, aCallback) {
- let self = this;
- this.updateStats(aAlarm.networkId, function onStatsUpdated(aResult, aMessage) {
- self._db.getCurrentStats(self._networks[aAlarm.networkId].network,
- aAlarm.startTime,
- function onStatsFound(error, result) {
- if (error) {
- debug("Error getting stats for " +
- JSON.stringify(self._networks[aAlarm.networkId]) + ": " + error);
- aCallback(error, result);
- return;
- }
-
- let quota = aAlarm.absoluteThreshold - result.rxBytes - result.txBytes;
-
- // Alarm set to a threshold lower than current rx/tx bytes.
- if (quota <= 0) {
- aCallback("InvalidStateError", null);
- return;
- }
-
- aAlarm.relativeThreshold = aAlarm.startTime
- ? result.rxTotalBytes + result.txTotalBytes + quota
- : aAlarm.absoluteThreshold;
-
- aCallback(null, quota);
- });
- });
- },
-
- _fireAlarm: function _fireAlarm(aAlarm) {
- debug("Fire alarm");
-
- let self = this;
- this._db.removeAlarm(aAlarm.id, null, function onRemove(aError, aResult){
- if (!aError && !aResult) {
- return;
- }
-
- self._fireSystemMessage(aAlarm);
- self._updateCurrentAlarm(aAlarm.networkId);
- });
- },
-
- _updateCurrentAlarm: function _updateCurrentAlarm(aNetworkId) {
- this._currentAlarms[aNetworkId] = Object.create(null);
-
- let self = this;
- this._db.getFirstAlarm(aNetworkId, function onGet(error, result){
- if (error) {
- debug("Error getting the first alarm");
- return;
- }
-
- if (!result) {
- let interfaceName = self._networks[aNetworkId].interfaceName;
- networkService.setNetworkInterfaceAlarm(interfaceName, -1,
- function onComplete(){});
- return;
- }
-
- self._setAlarm(result, function onSet(error, success){
- if (error == "InvalidStateError") {
- self._fireAlarm(result);
- return;
- }
- });
- });
- },
-
- _fireSystemMessage: function _fireSystemMessage(aAlarm) {
- debug("Fire system message: " + JSON.stringify(aAlarm));
-
- let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
- let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
-
- let alarm = { "id": aAlarm.id,
- "threshold": aAlarm.absoluteThreshold,
- "data": aAlarm.data };
- messenger.sendMessage("networkstats-alarm", alarm, pageURI, manifestURI);
- }
-};
-
-NetworkStatsService.init();
diff --git a/dom/network/NetworkStatsServiceProxy.js b/dom/network/NetworkStatsServiceProxy.js
deleted file mode 100644
index f3df4344d..000000000
--- a/dom/network/NetworkStatsServiceProxy.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const DEBUG = false;
-function debug(s) { dump("-*- NetworkStatsServiceProxy: " + s + "\n"); }
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["NetworkStatsServiceProxy"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/NetworkStatsService.jsm");
-
-const NETWORKSTATSSERVICEPROXY_CONTRACTID = "@mozilla.org/networkstatsServiceProxy;1";
-const NETWORKSTATSSERVICEPROXY_CID = Components.ID("98fd8f69-784e-4626-aa59-56d6436a3c24");
-const nsINetworkStatsServiceProxy = Ci.nsINetworkStatsServiceProxy;
-
-function NetworkStatsServiceProxy() {
- if (DEBUG) {
- debug("Proxy started");
- }
-}
-
-NetworkStatsServiceProxy.prototype = {
- /*
- * Function called in the protocol layer (HTTP, FTP, WebSocket ...etc)
- * to pass the per-app stats to NetworkStatsService.
- */
- saveAppStats: function saveAppStats(aAppId, aIsInIsolatedMozBrowser, aNetworkInfo, aTimeStamp,
- aRxBytes, aTxBytes, aIsAccumulative,
- aCallback) {
- if (!aNetworkInfo) {
- if (DEBUG) {
- debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
- }
- return;
- }
-
- if (DEBUG) {
- debug("saveAppStats: " + aAppId + " " + aIsInIsolatedMozBrowser + " " +
- aNetworkInfo.type + " " + aTimeStamp + " " +
- aRxBytes + " " + aTxBytes + " " + aIsAccumulative);
- }
-
- if (aCallback) {
- aCallback = aCallback.notify;
- }
-
- NetworkStatsService.saveStats(aAppId, aIsInIsolatedMozBrowser, "", aNetworkInfo,
- aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback);
- },
-
- /*
- * Function called in the points of different system services
- * to pass the per-service stats to NetworkStatsService.
- */
- saveServiceStats: function saveServiceStats(aServiceType, aNetworkInfo,
- aTimeStamp, aRxBytes, aTxBytes,
- aIsAccumulative, aCallback) {
- if (!aNetworkInfo) {
- if (DEBUG) {
- debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
- }
- return;
- }
-
- if (DEBUG) {
- debug("saveServiceStats: " + aServiceType + " " + aNetworkInfo.type + " " +
- aTimeStamp + " " + aRxBytes + " " + aTxBytes + " " +
- aIsAccumulative);
- }
-
- if (aCallback) {
- aCallback = aCallback.notify;
- }
-
- NetworkStatsService.saveStats(0, false, aServiceType , aNetworkInfo, aTimeStamp,
- aRxBytes, aTxBytes, aIsAccumulative,
- aCallback);
- },
-
- classID : NETWORKSTATSSERVICEPROXY_CID,
- QueryInterface : XPCOMUtils.generateQI([nsINetworkStatsServiceProxy]),
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsServiceProxy]);
diff --git a/dom/network/NetworkStatsServiceProxy.manifest b/dom/network/NetworkStatsServiceProxy.manifest
deleted file mode 100644
index 24f09f088..000000000
--- a/dom/network/NetworkStatsServiceProxy.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {98fd8f69-784e-4626-aa59-56d6436a3c24} NetworkStatsServiceProxy.js
-contract @mozilla.org/networkstatsServiceProxy;1 {98fd8f69-784e-4626-aa59-56d6436a3c24}
diff --git a/dom/network/interfaces/moz.build b/dom/network/interfaces/moz.build
index add687542..ad2e56bd6 100644
--- a/dom/network/interfaces/moz.build
+++ b/dom/network/interfaces/moz.build
@@ -10,10 +10,4 @@ XPIDL_SOURCES += [
'nsIUDPSocketChild.idl',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- XPIDL_SOURCES += [
- 'nsIEthernetManager.idl',
- 'nsINetworkStatsServiceProxy.idl',
- ]
-
XPIDL_MODULE = 'dom_network'
diff --git a/dom/network/interfaces/nsIEthernetManager.idl b/dom/network/interfaces/nsIEthernetManager.idl
deleted file mode 100644
index 2b92dc88f..000000000
--- a/dom/network/interfaces/nsIEthernetManager.idl
+++ /dev/null
@@ -1,137 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, function, uuid(2a3ad56c-edc0-439f-8aae-900b331ddf49)]
-interface nsIEthernetManagerCallback : nsISupports
-{
- /**
- * Callback function used to report the success of different operations.
- *
- * @param success
- * Boolean value indicates the success of an operation.
- * @prarm message
- * Message reported in the end of operation.
- */
- void notify(in boolean success, in DOMString message);
-};
-
-[scriptable, function, uuid(1746e7dd-92d4-43fa-8ef4-bc13d0b60353)]
-interface nsIEthernetManagerScanCallback : nsISupports
-{
- /**
- * Callback function used to report the result of scan function.
- *
- * @param list
- * List of available ethernet interfaces.
- */
- void notify(in jsval list);
-};
-
-/**
- * An internal idl provides control to ethernet interfaces.
- */
-[scriptable, uuid(81750c87-bb3b-4724-b955-834eafa53fd1)]
-interface nsIEthernetManager : nsISupports
-{
- /**
- * List of exisiting interface name.
- */
- readonly attribute jsval interfaceList;
-
- /**
- * Scan available ethernet interfaces on device.
- *
- * @param callback
- * Callback function.
- */
- void scan(in nsIEthernetManagerScanCallback callback);
-
- /**
- * Add a new interface to the interface list.
- *
- * @param ifname
- * Interface name. Should be the form of "eth*".
- * @param callback
- * Callback function.
- */
- void addInterface(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Remove an existing interface from the interface list.
- *
- * @param ifname
- * Interface name.
- * @param Callback
- * Callback function.
- */
- void removeInterface(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Update a conifg of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param config
- * .ip: IP address.
- * .prefixLength: Mask length.
- * .gateway: Gateway.
- * .dnses: DNS addresses.
- * .httpProxyHost: HTTP proxy host.
- * .httpProxyPort: HTTP proxy port.
- * .ipMode: IP mode, can be 'dhcp' or 'static'.
- * @param callback
- * Callback function.
- */
- void updateInterfaceConfig(in DOMString ifname,
- in jsval config,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Enable networking of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void enable(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Disable networking of an existing interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void disable(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Make an existing interface connect to network.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void connect(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-
- /**
- * Disconnect a connected interface in the interface list.
- *
- * @param ifname
- * Interface name.
- * @param callback
- * Callback function.
- */
- void disconnect(in DOMString ifname,
- in nsIEthernetManagerCallback callback);
-};
diff --git a/dom/network/interfaces/nsINetworkStatsServiceProxy.idl b/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
deleted file mode 100644
index cd6765c68..000000000
--- a/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
-* License, v. 2.0. If a copy of the MPL was not distributed with this file,
-* You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-
-[scriptable, function, uuid(5f821529-1d80-4ab5-a933-4e1b3585b6bc)]
-interface nsINetworkStatsServiceProxyCallback : nsISupports
-{
- /*
- * @param aResult callback result with boolean value
- * @param aMessage message
- */
- void notify(in boolean aResult, in jsval aMessage);
-};
-
-[scriptable, uuid(f4f3e901-e102-499d-9d37-dc9951f52df7)]
-interface nsINetworkStatsServiceProxy : nsISupports
-{
- /*
- * An interface used to record per-app traffic data.
- * @param aAppId app id
- * @param aIsInIsolatedMozBrowser
- * true if the frame is an isolated mozbrowser element. <iframe
- * mozbrowser mozapp> and <xul:browser> are not considered to be
- * mozbrowser elements. <iframe mozbrowser noisolation> does not count
- * as isolated since isolation is disabled. Isolation can only be
- * disabled if the containing document is chrome.
- * @param aNetworkInterface network
- * @param aTimeStamp time stamp
- * @param aRxBytes received data amount
- * @param aTxBytes transmitted data amount
- * @param aIsAccumulative is stats accumulative
- * @param aCallback an optional callback
- */
- void saveAppStats(in unsigned long aAppId,
- in boolean aIsInIsolatedMozBrowser,
- in nsINetworkInfo aNetworkInfo,
- in unsigned long long aTimeStamp,
- in unsigned long long aRxBytes,
- in unsigned long long aTxBytes,
- in boolean aIsAccumulative,
- [optional] in nsINetworkStatsServiceProxyCallback aCallback);
-
- /*
- * An interface used to record per-system service traffic data.
- * @param aServiceType system service type
- * @param aNetworkInterface network
- * @param aTimeStamp time stamp
- * @param aRxBytes received data amount
- * @param aTxBytes transmitted data amount
- * @param aIsAccumulative is stats accumulative
- * @param aCallback an optional callback
- */
- void saveServiceStats(in string aServiceType,
- in nsINetworkInfo aNetworkInfo,
- in unsigned long long aTimeStamp,
- in unsigned long long aRxBytes,
- in unsigned long long aTxBytes,
- in boolean aIsAccumulative,
- [optional] in nsINetworkStatsServiceProxyCallback aCallback);
-};
diff --git a/dom/network/moz.build b/dom/network/moz.build
index 63e5c75c0..ffb90d116 100644
--- a/dom/network/moz.build
+++ b/dom/network/moz.build
@@ -40,28 +40,6 @@ UNIFIED_SOURCES += [
'UDPSocketParent.cpp',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- EXTRA_JS_MODULES += [
- 'NetworkStatsDB.jsm',
- 'NetworkStatsService.jsm',
- ]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- EXTRA_COMPONENTS += [
- 'EthernetManager.js',
- 'EthernetManager.manifest',
- 'NetworkStatsManager.js',
- 'NetworkStatsManager.manifest',
- 'NetworkStatsServiceProxy.js',
- 'NetworkStatsServiceProxy.manifest',
- ]
- EXPORTS.mozilla.dom.network += [
- 'NetUtils.h',
- ]
- UNIFIED_SOURCES += [
- 'NetUtils.cpp',
- ]
-
IPDL_SOURCES += [
'PTCPServerSocket.ipdl',
'PTCPSocket.ipdl',