зеркало из https://github.com/mozilla/gecko-dev.git
Bug 964270 - Part 1: Enable networkstats alarms for networks not available. r=gene
This commit is contained in:
Родитель
19aa728f9e
Коммит
e7bcd95714
|
@ -29,6 +29,15 @@ const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
|
|||
const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
||||
const NET_TYPE_MOBILE = Ci.nsINetworkInterface.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
|
||||
|
||||
|
@ -89,7 +98,8 @@ this.NetworkStatsService = {
|
|||
let netId = this.getNetworkId('0', NET_TYPE_WIFI);
|
||||
this._networks[netId] = { network: { id: '0',
|
||||
type: NET_TYPE_WIFI },
|
||||
interfaceName: null };
|
||||
interfaceName: null,
|
||||
status: NETWORK_STATUS_STANDBY };
|
||||
|
||||
this.messages = ["NetworkStats:Get",
|
||||
"NetworkStats:Clear",
|
||||
|
@ -278,6 +288,7 @@ this.NetworkStatsService = {
|
|||
type: aNetwork.type };
|
||||
}
|
||||
|
||||
this._networks[netId].status = NETWORK_STATUS_READY;
|
||||
this._networks[netId].interfaceName = aNetwork.name;
|
||||
return netId;
|
||||
},
|
||||
|
@ -286,6 +297,46 @@ this.NetworkStatsService = {
|
|||
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);
|
||||
}
|
||||
|
||||
aCallback(null);
|
||||
});
|
||||
},
|
||||
|
||||
getAvailableNetworks: function getAvailableNetworks(mm, msg) {
|
||||
let self = this;
|
||||
let rilNetworks = this.getRilNetworks();
|
||||
|
@ -368,91 +419,55 @@ this.NetworkStatsService = {
|
|||
let start = new Date(msg.start);
|
||||
let end = new Date(msg.end);
|
||||
|
||||
// Check if the network is currently active. If yes, we need to update
|
||||
// the cached stats first before retrieving stats from the DB.
|
||||
if (this._networks[netId]) {
|
||||
this.updateStats(netId, function onStatsUpdated(aResult, aMessage) {
|
||||
debug("getstats for network " + network.id + " of type " + network.type);
|
||||
debug("appId: " + appId + " from appManifestURL: " + appManifestURL);
|
||||
|
||||
self.updateCachedStats(function onStatsUpdated(aResult, aMessage) {
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, appId, serviceType, network, start, end, appManifestURL);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the network is available in the DB. If yes, we also
|
||||
// retrieve the stats for it from the DB.
|
||||
this._db.isNetworkAvailable(network, function(aError, aResult) {
|
||||
let toFind = false;
|
||||
if (aResult) {
|
||||
toFind = true;
|
||||
} else if (!aError) {
|
||||
// Network is not found in the database without any errors.
|
||||
// Check if network is valid but has not established a connection yet.
|
||||
let rilNetworks = self.getRilNetworks();
|
||||
if (rilNetworks[netId]) {
|
||||
// find will not get data for network from the database but will format the
|
||||
// result object in order to make NetworkStatsManager be able to construct a
|
||||
// nsIDOMMozNetworkStats object.
|
||||
toFind = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (toFind) {
|
||||
// If network is not active, there is no need to update stats before finding.
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, appId, serviceType, network, start, end, appManifestURL);
|
||||
this.validateNetwork(network, function onValidateNetwork(aNetId) {
|
||||
if (!aNetId) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: "Invalid connectionType", result: null });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aError) {
|
||||
aError = "Invalid connectionType";
|
||||
// If network is currently active we need to update the cached stats first before
|
||||
// retrieving stats from the DB.
|
||||
if (self._networks[aNetId].status == NETWORK_STATUS_READY) {
|
||||
self.updateStats(aNetId, function onStatsUpdated(aResult, aMessage) {
|
||||
debug("getstats for network " + network.id + " of type " + network.type);
|
||||
debug("appId: " + appId + " from appManifestURL: " + appManifestURL);
|
||||
|
||||
self.updateCachedStats(function onStatsUpdated(aResult, aMessage) {
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, appId, serviceType, network, start, end, appManifestURL);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: null });
|
||||
// Network not active, so no need to update
|
||||
self._db.find(function onStatsFound(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
}, appId, serviceType, network, start, end, appManifestURL);
|
||||
});
|
||||
},
|
||||
|
||||
clearInterfaceStats: function clearInterfaceStats(mm, msg) {
|
||||
let self = this;
|
||||
let network = msg.network;
|
||||
let netId = this.getNetworkId(network.id, network.type);
|
||||
|
||||
debug("clear stats for network " + network.id + " of type " + network.type);
|
||||
|
||||
if (!this._networks[netId]) {
|
||||
// Check if network is valid but has not established a connection yet. If it is not
|
||||
// found in RIL networks, it can be a SIM network used in the past having sample
|
||||
// in the database.
|
||||
let rilNetworks = this.getRilNetworks();
|
||||
if (!rilNetworks[netId]) {
|
||||
// Check if it is available in the DB.
|
||||
this._db.isNetworkAvailable(network, function(aError, aResult) {
|
||||
if (aResult) {
|
||||
this._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: "Invalid networkType", result: null });
|
||||
});
|
||||
this.validateNetwork(network, function onValidateNetwork(aNetId) {
|
||||
if (!aNetId) {
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: "Invalid connectionType", result: null });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
self._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -478,7 +493,7 @@ this.NetworkStatsService = {
|
|||
this.updateCachedStats();
|
||||
|
||||
let elements = [];
|
||||
let lastElement;
|
||||
let lastElement = null;
|
||||
|
||||
// For each connectionType create an object containning the type
|
||||
// and the 'queueIndex', the 'queueIndex' is an integer representing
|
||||
|
@ -487,14 +502,27 @@ this.NetworkStatsService = {
|
|||
// 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: []});
|
||||
elements.push({ netId: lastElement.netId, callbacks: [] });
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -800,21 +828,29 @@ this.NetworkStatsService = {
|
|||
},
|
||||
|
||||
getAlarms: function getAlarms(mm, msg) {
|
||||
let self = this;
|
||||
let network = msg.data.network;
|
||||
let manifestURL = msg.data.manifestURL;
|
||||
|
||||
let netId = null;
|
||||
if (network) {
|
||||
netId = this.getNetworkId(network.id, network.type);
|
||||
if (!this._networks[netId]) {
|
||||
mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
|
||||
{ id: msg.id, error: "InvalidInterface", result: null });
|
||||
return;
|
||||
}
|
||||
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(netId, manifestURL, function onCompleted(error, result) {
|
||||
this._db.getAlarms(aNetId, aManifestURL, function onCompleted(error, result) {
|
||||
if (error) {
|
||||
mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
|
||||
{ id: msg.id, error: error, result: result });
|
||||
|
@ -884,48 +920,49 @@ this.NetworkStatsService = {
|
|||
return;
|
||||
}
|
||||
|
||||
let netId = this.getNetworkId(network.id, network.type);
|
||||
if (!this._networks[netId]) {
|
||||
mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
|
||||
{ id: msg.id, error: "InvalidiConnectionType", result: null });
|
||||
return;
|
||||
}
|
||||
|
||||
let newAlarm = {
|
||||
id: null,
|
||||
networkId: netId,
|
||||
threshold: threshold,
|
||||
absoluteThreshold: null,
|
||||
startTime: options.startTime,
|
||||
data: options.data,
|
||||
pageURL: options.pageURL,
|
||||
manifestURL: options.manifestURL
|
||||
};
|
||||
|
||||
let self = this;
|
||||
this._updateThreshold(newAlarm, function onUpdate(error, _threshold) {
|
||||
if (error) {
|
||||
this.validateNetwork(network, function onValidateNetwork(aNetId) {
|
||||
if (!aNetId) {
|
||||
mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
|
||||
{ id: msg.id, error: error, result: null });
|
||||
{ id: msg.id, error: "InvalidiConnectionType", result: null });
|
||||
return;
|
||||
}
|
||||
|
||||
newAlarm.absoluteThreshold = _threshold.absoluteThreshold;
|
||||
self._db.addAlarm(newAlarm, function addSuccessCb(error, newId) {
|
||||
let newAlarm = {
|
||||
id: null,
|
||||
networkId: aNetId,
|
||||
threshold: threshold,
|
||||
absoluteThreshold: null,
|
||||
startTime: options.startTime,
|
||||
data: options.data,
|
||||
pageURL: options.pageURL,
|
||||
manifestURL: options.manifestURL
|
||||
};
|
||||
|
||||
self._updateThreshold(newAlarm, function onUpdate(error, _threshold) {
|
||||
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);
|
||||
newAlarm.absoluteThreshold = _threshold.absoluteThreshold;
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -933,8 +970,9 @@ this.NetworkStatsService = {
|
|||
|
||||
_setAlarm: function _setAlarm(aAlarm, aCallback) {
|
||||
let currentAlarm = this._currentAlarms[aAlarm.networkId];
|
||||
if (Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
|
||||
aAlarm.absoluteThreshold > currentAlarm.alarm.absoluteThreshold) {
|
||||
if ((Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
|
||||
aAlarm.absoluteThreshold > currentAlarm.alarm.absoluteThreshold) ||
|
||||
this._networks[aAlarm.networkId].status != NETWORK_STATUS_READY) {
|
||||
aCallback(null, true);
|
||||
return;
|
||||
}
|
||||
|
@ -985,6 +1023,14 @@ this.NetworkStatsService = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
// There are no stats for the network of the alarm, set them to default 0 in
|
||||
// order to be able to calculate the offset, systemThreshold and
|
||||
// absoluteThreshold.
|
||||
result = { rxTotalBytes: 0, txTotalBytes: 0,
|
||||
rxSystemBytes: 0, txSystemBytes: 0 };
|
||||
}
|
||||
|
||||
let offset = aAlarm.threshold - result.rxTotalBytes - result.txTotalBytes;
|
||||
|
||||
// Alarm set to a threshold lower than current rx/tx bytes.
|
||||
|
|
Загрузка…
Ссылка в новой задаче