зеркало из https://github.com/mozilla/gecko-dev.git
Merge b2g-inbound to m-c.
This commit is contained in:
Коммит
e837de97ec
2
CLOBBER
2
CLOBBER
|
@ -18,4 +18,4 @@
|
|||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 915735 requires clobber
|
||||
Bug 933585 - clobber required on windows
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "d10e0357c63bb565db8bdd3c23f062bfb9e21315",
|
||||
"revision": "63d432c3395f95c0ba19578487b796c1707042bd",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ pref("layers.componentalpha.enabled", false);
|
|||
pref("apz.touch_start_tolerance", "0.1"); // dpi * tolerance = pixel threshold
|
||||
pref("apz.pan_repaint_interval", 50); // prefer 20 fps
|
||||
pref("apz.fling_repaint_interval", 50); // prefer 20 fps
|
||||
pref("apz.fling_friction", "0.002");
|
||||
pref("apz.fling_stopped_threshold", "0.2");
|
||||
|
||||
// 0 = free, 1 = standard, 2 = sticky
|
||||
|
|
|
@ -78,7 +78,7 @@ SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength)
|
|||
aRetBuf[2] = aPacketLength & 0x00FF;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ParseHeaders(const uint8_t* aHeaderStart,
|
||||
int aTotalLength,
|
||||
ObexHeaderSet* aRetHandlerSet)
|
||||
|
@ -88,7 +88,7 @@ ParseHeaders(const uint8_t* aHeaderStart,
|
|||
while (ptr - aHeaderStart < aTotalLength) {
|
||||
ObexHeaderId headerId = (ObexHeaderId)*ptr++;
|
||||
|
||||
int contentLength = 0;
|
||||
uint16_t contentLength = 0;
|
||||
uint8_t highByte, lowByte;
|
||||
|
||||
// Defined in 2.1 OBEX Headers, IrOBEX 1.2
|
||||
|
@ -101,7 +101,7 @@ ParseHeaders(const uint8_t* aHeaderStart,
|
|||
// byte sequence, length prefixed with 2 byte unsigned integer.
|
||||
highByte = *ptr++;
|
||||
lowByte = *ptr++;
|
||||
contentLength = (((int)highByte << 8) | lowByte) - 3;
|
||||
contentLength = (((uint16_t)highByte << 8) | lowByte) - 3;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
|
@ -115,10 +115,20 @@ ParseHeaders(const uint8_t* aHeaderStart,
|
|||
break;
|
||||
}
|
||||
|
||||
aRetHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, ptr));
|
||||
// Length check to prevent from memory pollusion.
|
||||
if (ptr + contentLength > aHeaderStart + aTotalLength) {
|
||||
// Severe error occurred. We can't even believe the received data, so
|
||||
// clear all headers.
|
||||
MOZ_ASSERT(false);
|
||||
aRetHandlerSet->ClearHeaders();
|
||||
return false;
|
||||
}
|
||||
|
||||
aRetHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, ptr));
|
||||
ptr += contentLength;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
|
|
@ -102,7 +102,8 @@ enum ObexResponseCode {
|
|||
DatabaseLocked = 0xE1,
|
||||
};
|
||||
|
||||
class ObexHeader {
|
||||
class ObexHeader
|
||||
{
|
||||
public:
|
||||
ObexHeader(ObexHeaderId aId, int aDataLength, const uint8_t* aData)
|
||||
: mId(aId)
|
||||
|
@ -122,11 +123,9 @@ public:
|
|||
nsAutoArrayPtr<uint8_t> mData;
|
||||
};
|
||||
|
||||
class ObexHeaderSet {
|
||||
class ObexHeaderSet
|
||||
{
|
||||
public:
|
||||
uint8_t mOpcode;
|
||||
nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
|
||||
|
||||
ObexHeaderSet(uint8_t aOpcode) : mOpcode(aOpcode)
|
||||
{
|
||||
}
|
||||
|
@ -241,6 +240,15 @@ public:
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClearHeaders()
|
||||
{
|
||||
mHeaders.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mOpcode;
|
||||
nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
|
||||
};
|
||||
|
||||
int AppendHeaderName(uint8_t* aRetBuf, const char* aName, int aLength);
|
||||
|
@ -249,7 +257,11 @@ int AppendHeaderEndOfBody(uint8_t* aRetBuf);
|
|||
int AppendHeaderLength(uint8_t* aRetBuf, int aObjectLength);
|
||||
int AppendHeaderConnectionId(uint8_t* aRetBuf, int aConnectionId);
|
||||
void SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength);
|
||||
void ParseHeaders(const uint8_t* aHeaderStart,
|
||||
|
||||
/**
|
||||
* @return true when the message was parsed without any error, false otherwise.
|
||||
*/
|
||||
bool ParseHeaders(const uint8_t* aHeaderStart,
|
||||
int aTotalLength,
|
||||
ObexHeaderSet* aRetHanderSet);
|
||||
|
||||
|
|
|
@ -803,25 +803,31 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
|||
// Section 3.3.1 "Connect", IrOBEX 1.2
|
||||
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
|
||||
// [Headers:var]
|
||||
ParseHeaders(&aMessage->mData[7],
|
||||
receivedLength - 7,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToConnect();
|
||||
AfterOppConnected();
|
||||
} else if (opCode == ObexRequestCode::Abort) {
|
||||
// Section 3.3.5 "Abort", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToDisconnectOrAbort();
|
||||
DeleteReceivedFile();
|
||||
} else if (opCode == ObexRequestCode::Disconnect) {
|
||||
// Section 3.3.2 "Disconnect", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToDisconnectOrAbort();
|
||||
AfterOppDisconnected();
|
||||
FileTransferComplete();
|
||||
|
@ -1197,7 +1203,7 @@ BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue)
|
|||
void
|
||||
BluetoothOppManager::ReplyError(uint8_t aError)
|
||||
{
|
||||
if (!mConnected) return;
|
||||
BT_LOGR("error: %d", aError);
|
||||
|
||||
// Section 3.2 "Response Format", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
|
|
|
@ -341,9 +341,12 @@ Call::IsActive()
|
|||
/**
|
||||
* BluetoothHfpManager
|
||||
*/
|
||||
BluetoothHfpManager::BluetoothHfpManager() : mPhoneType(PhoneType::NONE)
|
||||
, mController(nullptr)
|
||||
BluetoothHfpManager::BluetoothHfpManager() : mController(nullptr)
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
mPhoneType = PhoneType::NONE;
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -819,25 +819,31 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
|||
// Section 3.3.1 "Connect", IrOBEX 1.2
|
||||
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
|
||||
// [Headers:var]
|
||||
ParseHeaders(&aMessage->mData[7],
|
||||
receivedLength - 7,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToConnect();
|
||||
AfterOppConnected();
|
||||
} else if (opCode == ObexRequestCode::Abort) {
|
||||
// Section 3.3.5 "Abort", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToDisconnectOrAbort();
|
||||
DeleteReceivedFile();
|
||||
} else if (opCode == ObexRequestCode::Disconnect) {
|
||||
// Section 3.3.2 "Disconnect", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
if (!ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders)) {
|
||||
ReplyError(ObexResponseCode::BadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyToDisconnectOrAbort();
|
||||
AfterOppDisconnected();
|
||||
FileTransferComplete();
|
||||
|
@ -1213,7 +1219,7 @@ BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue)
|
|||
void
|
||||
BluetoothOppManager::ReplyError(uint8_t aError)
|
||||
{
|
||||
if (!mConnected) return;
|
||||
BT_LOGR("error: %d", aError);
|
||||
|
||||
// Section 3.2 "Response Format", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
|
|
|
@ -79,6 +79,7 @@ enum {
|
|||
CAMERA_PARAM_PICTURESIZE,
|
||||
CAMERA_PARAM_THUMBNAILSIZE,
|
||||
CAMERA_PARAM_THUMBNAILQUALITY,
|
||||
CAMERA_PARAM_SENSORANGLE,
|
||||
|
||||
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
|
||||
CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
|
||||
|
|
|
@ -268,6 +268,14 @@ CameraControlImpl::Get(uint32_t aKey, idl::CameraSize& aSize)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Get(uint32_t aKey, int32_t* aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue);
|
||||
*aValue = GetParameterInt32(aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<RecorderProfileManager>
|
||||
CameraControlImpl::GetRecorderProfileManager()
|
||||
{
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange);
|
||||
nsresult Set(uint32_t aKey, const idl::CameraSize& aSize);
|
||||
nsresult Get(uint32_t aKey, idl::CameraSize& aSize);
|
||||
nsresult Get(uint32_t aKey, int32_t* aValue);
|
||||
|
||||
nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
|
||||
{
|
||||
|
@ -92,6 +93,7 @@ public:
|
|||
virtual const char* GetParameter(const char* aKey) = 0;
|
||||
virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
|
||||
virtual double GetParameterDouble(uint32_t aKey) = 0;
|
||||
virtual int32_t GetParameterInt32(uint32_t aKey) = 0;
|
||||
virtual void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions) = 0;
|
||||
virtual void GetParameter(uint32_t aKey, idl::CameraSize& aSize) = 0;
|
||||
virtual void SetParameter(const char* aKey, const char* aValue) = 0;
|
||||
|
|
|
@ -285,6 +285,14 @@ nsDOMCameraControl::GetExposureCompensation(ErrorResult& aRv)
|
|||
return compensation;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsDOMCameraControl::SensorAngle()
|
||||
{
|
||||
int32_t angle;
|
||||
mCameraControl->Get(CAMERA_PARAM_SENSORANGLE, &angle);
|
||||
return angle;
|
||||
}
|
||||
|
||||
already_AddRefed<nsICameraShutterCallback>
|
||||
nsDOMCameraControl::GetOnShutter(ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
double GetFocusDistanceFar(ErrorResult& aRv);
|
||||
void SetExposureCompensation(const dom::Optional<double>& aCompensation, ErrorResult& aRv);
|
||||
double GetExposureCompensation(ErrorResult& aRv);
|
||||
int32_t SensorAngle();
|
||||
already_AddRefed<nsICameraShutterCallback> GetOnShutter(ErrorResult& aRv);
|
||||
void SetOnShutter(nsICameraShutterCallback* aCb, ErrorResult& aRv);
|
||||
already_AddRefed<nsICameraClosedCallback> GetOnClosed(ErrorResult& aRv);
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
const char* GetParameter(const char* aKey);
|
||||
const char* GetParameterConstChar(uint32_t aKey);
|
||||
double GetParameterDouble(uint32_t aKey);
|
||||
int32_t GetParameterInt32(uint32_t aKey);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
|
||||
void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
|
||||
void SetParameter(const char* aKey, const char* aValue);
|
||||
|
@ -101,6 +102,12 @@ nsFallbackCameraControl::GetParameterDouble(uint32_t aKey)
|
|||
return NAN;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsFallbackCameraControl::GetParameterInt32(uint32_t aKey)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsFallbackCameraControl::GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions)
|
||||
{
|
||||
|
|
|
@ -434,6 +434,25 @@ nsGonkCameraControl::GetParameterDouble(uint32_t aKey)
|
|||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsGonkCameraControl::GetParameterInt32(uint32_t aKey)
|
||||
{
|
||||
if (aKey == CAMERA_PARAM_SENSORANGLE) {
|
||||
if (!mCameraHw.get()) {
|
||||
return 0;
|
||||
}
|
||||
return mCameraHw->GetSensorOrientation();
|
||||
}
|
||||
|
||||
const char* key = getKeyText(aKey);
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RwAutoLockRead lock(mRwLock);
|
||||
return mParams.getInt(key);
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::GetParameter(uint32_t aKey,
|
||||
nsTArray<idl::CameraRegion>& aRegions)
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
const char* GetParameter(const char* aKey);
|
||||
const char* GetParameterConstChar(uint32_t aKey);
|
||||
double GetParameterDouble(uint32_t aKey);
|
||||
int32_t GetParameterInt32(uint32_t aKey);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraRegion>& aRegions);
|
||||
void GetParameter(uint32_t aKey, nsTArray<idl::CameraSize>& aSizes);
|
||||
void GetParameter(uint32_t aKey, idl::CameraSize& aSize);
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
virtual nsresult Get(nsICameraPreviewStateChange** aOnPreviewStateChange) = 0;
|
||||
virtual nsresult Set(uint32_t aKey, const idl::CameraSize& aSize) = 0;
|
||||
virtual nsresult Get(uint32_t aKey, idl::CameraSize& aSize) = 0;
|
||||
virtual nsresult Get(uint32_t aKey, int32_t* aValue) = 0;
|
||||
virtual nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
virtual nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
virtual nsresult GetVideoSizes(nsTArray<idl::CameraSize>& aVideoSizes) = 0;
|
||||
|
|
|
@ -62,6 +62,9 @@ this.SystemMessagePermissionsTable = {
|
|||
"settings": ["read", "write"]
|
||||
},
|
||||
"media-button": { },
|
||||
"networkstats-alarm": {
|
||||
"networkstats-manage": []
|
||||
},
|
||||
"notification": {
|
||||
"desktop-notification": []
|
||||
},
|
||||
|
|
|
@ -20,7 +20,22 @@ interface nsIDOMMozNetworkStatsInterface : nsISupports
|
|||
readonly attribute DOMString id;
|
||||
};
|
||||
|
||||
[scriptable, uuid(5f033d31-c9a2-4e2d-83aa-6a807f1e0c11)]
|
||||
dictionary NetworkStatsAlarmOptions
|
||||
{
|
||||
jsval startTime; // Date object
|
||||
jsval data;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c)]
|
||||
interface nsIDOMMozNetworkStatsAlarm : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long alarmId;
|
||||
readonly attribute nsIDOMMozNetworkStatsInterface network;
|
||||
readonly attribute long threshold;
|
||||
readonly attribute jsval data;
|
||||
};
|
||||
|
||||
[scriptable, uuid(50d109b8-0d7f-4208-81fe-5f07a759f159)]
|
||||
interface nsIDOMMozNetworkStatsManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -42,6 +57,41 @@ interface nsIDOMMozNetworkStatsManager : nsISupports
|
|||
in jsval end,
|
||||
[optional] in DOMString manifestURL);
|
||||
|
||||
/**
|
||||
* Install an alarm on a network. The network must be in the return of
|
||||
* getAvailableNetworks() otherwise an "InvalidNetwork" exception will
|
||||
* be raised.
|
||||
*
|
||||
* When total data usage reaches threshold bytes, a "networkstats-alarm"
|
||||
* system message is sent to the application, where the optional parameter
|
||||
* |data| must be a cloneable object.
|
||||
*
|
||||
* If success, the |result| field of the DOMRequest keeps the alarm Id.
|
||||
*/
|
||||
nsIDOMDOMRequest addAlarm(in nsIDOMMozNetworkStatsInterface network,
|
||||
in long threshold,
|
||||
[optional] in jsval options /* NetworkStatsAlarmOptions */);
|
||||
|
||||
/**
|
||||
* Obtain all alarms for those networks returned by getAvailableNetworks().
|
||||
* If a network is provided, only retrieves the alarms for that network.
|
||||
* The network must be one of those returned by getAvailebleNetworks() or an
|
||||
* "InvalidNetwork" exception will be raised.
|
||||
*
|
||||
* Each alarm object has the same fields as that in the system message:
|
||||
* - alarmId
|
||||
* - network
|
||||
* - threshold
|
||||
* - data
|
||||
*/
|
||||
nsIDOMDOMRequest getAllAlarms([optional] in nsIDOMMozNetworkStatsInterface network);
|
||||
|
||||
/**
|
||||
* Remove all network alarms. If an |alarmId| is provided, then only that
|
||||
* alarm is removed.
|
||||
*/
|
||||
nsIDOMDOMRequest removeAlarms([optional] in long alarmId);
|
||||
|
||||
/**
|
||||
* Remove all stats related with the provided network from DB.
|
||||
*/
|
||||
|
|
|
@ -16,8 +16,9 @@ Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
|||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const DB_NAME = "net_stats";
|
||||
const DB_VERSION = 4;
|
||||
const STORE_NAME = "net_stats";
|
||||
const DB_VERSION = 5;
|
||||
const STATS_STORE_NAME = "net_stats";
|
||||
const ALARMS_STORE_NAME = "net_alarm";
|
||||
|
||||
// Constant defining the maximum values allowed per interface. If more, older
|
||||
// will be erased.
|
||||
|
@ -30,20 +31,20 @@ this.NetworkStatsDB = function NetworkStatsDB() {
|
|||
if (DEBUG) {
|
||||
debug("Constructor");
|
||||
}
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME]);
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, [STATS_STORE_NAME, ALARMS_STORE_NAME]);
|
||||
}
|
||||
|
||||
NetworkStatsDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
dbNewTxn: function dbNewTxn(txn_type, callback, txnCb) {
|
||||
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);
|
||||
return this.newTxn(txn_type, store_name, callback, successCb, errorCb);
|
||||
},
|
||||
|
||||
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
|
@ -58,7 +59,7 @@ NetworkStatsDB.prototype = {
|
|||
* Create the initial database schema.
|
||||
*/
|
||||
|
||||
objectStore = db.createObjectStore(STORE_NAME, { keyPath: ["connectionType", "timestamp"] });
|
||||
objectStore = db.createObjectStore(STATS_STORE_NAME, { keyPath: ["connectionType", "timestamp"] });
|
||||
objectStore.createIndex("connectionType", "connectionType", { unique: false });
|
||||
objectStore.createIndex("timestamp", "timestamp", { unique: false });
|
||||
objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
|
||||
|
@ -77,9 +78,9 @@ NetworkStatsDB.prototype = {
|
|||
// 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.
|
||||
db.deleteObjectStore(STORE_NAME);
|
||||
db.deleteObjectStore(STATS_STORE_NAME);
|
||||
|
||||
objectStore = db.createObjectStore(STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
|
||||
objectStore = db.createObjectStore(STATS_STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
|
||||
objectStore.createIndex("appId", "appId", { unique: false });
|
||||
objectStore.createIndex("network", "network", { unique: false });
|
||||
objectStore.createIndex("networkType", "networkType", { unique: false });
|
||||
|
@ -94,7 +95,7 @@ NetworkStatsDB.prototype = {
|
|||
}
|
||||
} else if (currVersion == 3) {
|
||||
// Delete redundent indexes (leave "network" only).
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
objectStore = aTransaction.objectStore(STATS_STORE_NAME);
|
||||
if (objectStore.indexNames.contains("appId")) {
|
||||
objectStore.deleteIndex("appId");
|
||||
}
|
||||
|
@ -120,6 +121,68 @@ NetworkStatsDB.prototype = {
|
|||
if (DEBUG) {
|
||||
debug("Deleted redundent indexes for version 4");
|
||||
}
|
||||
} else if (currVersion == 4) {
|
||||
// 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(STATS_STORE_NAME);
|
||||
|
||||
// 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){
|
||||
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 });
|
||||
|
||||
if (DEBUG) {
|
||||
debug("Created alarms store for version 5");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -130,6 +193,8 @@ NetworkStatsDB.prototype = {
|
|||
timestamp: aStats.timestamp,
|
||||
rxBytes: aStats.rxBytes,
|
||||
txBytes: aStats.txBytes,
|
||||
rxSystemBytes: aStats.rxSystemBytes,
|
||||
txSystemBytes: aStats.txSystemBytes,
|
||||
rxTotalBytes: aStats.rxTotalBytes,
|
||||
txTotalBytes: aStats.txTotalBytes };
|
||||
|
||||
|
@ -166,12 +231,14 @@ NetworkStatsDB.prototype = {
|
|||
timestamp: timestamp,
|
||||
rxBytes: (aStats.appId == 0) ? 0 : aStats.rxBytes,
|
||||
txBytes: (aStats.appId == 0) ? 0 : aStats.txBytes,
|
||||
rxSystemBytes: (aStats.appId == 0) ? aStats.rxBytes : 0,
|
||||
txSystemBytes: (aStats.appId == 0) ? aStats.txBytes : 0,
|
||||
rxTotalBytes: (aStats.appId == 0) ? aStats.rxBytes : 0,
|
||||
txTotalBytes: (aStats.appId == 0) ? aStats.txBytes : 0 };
|
||||
|
||||
stats = this.importData(stats);
|
||||
|
||||
this.dbNewTxn("readwrite", function(aTxn, aStore) {
|
||||
this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
|
||||
if (DEBUG) {
|
||||
debug("Filtered time: " + new Date(timestamp));
|
||||
debug("New stats: " + JSON.stringify(stats));
|
||||
|
@ -241,21 +308,29 @@ NetworkStatsDB.prototype = {
|
|||
// |txTotalBytes|/|rxTotalBytes| and the last |txTotalBytes|/|rxTotalBytes|.
|
||||
// Else, the incoming data is per-app data (|newSample.appId| is not 0),
|
||||
// the |txBytes|/|rxBytes| is directly the new |txBytes|/|rxBytes|.
|
||||
let rxDiff = 0;
|
||||
let txDiff = 0;
|
||||
if (aNewSample.appId == 0) {
|
||||
let rxDiff = aNewSample.rxTotalBytes - lastSample.rxTotalBytes;
|
||||
let txDiff = aNewSample.txTotalBytes - lastSample.txTotalBytes;
|
||||
rxDiff = aNewSample.rxSystemBytes - lastSample.rxSystemBytes;
|
||||
txDiff = aNewSample.txSystemBytes - lastSample.txSystemBytes;
|
||||
if (rxDiff < 0 || txDiff < 0) {
|
||||
rxDiff = aNewSample.rxTotalBytes;
|
||||
txDiff = aNewSample.txTotalBytes;
|
||||
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 per-data data, new |rxTotalBytes|/|txTotalBytes|
|
||||
// If the incoming data is per-app data, new |rxTotalBytes|/|txTotalBytes|
|
||||
// needs to be obtained by adding new |rxBytes|/|txBytes| to last
|
||||
// |rxTotalBytes|/|txTotalBytes|.
|
||||
if (aNewSample.appId != 0) {
|
||||
|
@ -282,6 +357,8 @@ NetworkStatsDB.prototype = {
|
|||
timestamp: time,
|
||||
rxBytes: 0,
|
||||
txBytes: 0,
|
||||
rxSystemBytes: lastSample.rxSystemBytes,
|
||||
txSystemBytes: lastSample.txSystemBytes,
|
||||
rxTotalBytes: lastSample.rxTotalBytes,
|
||||
txTotalBytes: lastSample.txTotalBytes };
|
||||
|
||||
|
@ -293,27 +370,20 @@ NetworkStatsDB.prototype = {
|
|||
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.
|
||||
// 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.
|
||||
|
||||
// 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;
|
||||
|
||||
lastSample.rxBytes += aNewSample.rxBytes;
|
||||
lastSample.txBytes += aNewSample.txBytes;
|
||||
|
||||
// If incoming data is obtained from netd, last |rxTotalBytes|/|txTotalBytes|
|
||||
// needs to get updated by replacing the new |rxTotalBytes|/|txTotalBytes|.
|
||||
if (aNewSample.appId == 0) {
|
||||
lastSample.rxTotalBytes = aNewSample.rxTotalBytes;
|
||||
lastSample.txTotalBytes = aNewSample.txTotalBytes;
|
||||
} else {
|
||||
// Else, the incoming data is per-app data, old |rxTotalBytes|/
|
||||
// |txTotalBytes| needs to get updated by adding the new
|
||||
// |rxBytes|/|txBytes| to last |rxTotalBytes|/|txTotalBytes|.
|
||||
lastSample.rxTotalBytes += aNewSample.rxBytes;
|
||||
lastSample.txTotalBytes += aNewSample.txBytes;
|
||||
}
|
||||
if (DEBUG) {
|
||||
debug("Update: " + JSON.stringify(lastSample));
|
||||
}
|
||||
|
@ -379,7 +449,7 @@ NetworkStatsDB.prototype = {
|
|||
let self = this;
|
||||
|
||||
// Clear and save an empty sample to keep sync with system counters
|
||||
this.dbNewTxn("readwrite", function(aTxn, aStore) {
|
||||
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) {
|
||||
|
@ -431,6 +501,33 @@ NetworkStatsDB.prototype = {
|
|||
this.clearInterfaceStats(aNetworks[index], callback);
|
||||
},
|
||||
|
||||
getCurrentStats: function getCurrentStats(aNetwork, aDate, aResultCb) {
|
||||
if (DEBUG) {
|
||||
debug("Get current stats for " + JSON.stringify(aNetwork) + " since " + aDate);
|
||||
}
|
||||
|
||||
this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
|
||||
let request = null;
|
||||
let network = [aNetwork.id, aNetwork.type];
|
||||
if (aDate) {
|
||||
let start = this.normalizeDate(aDate);
|
||||
let lowerFilter = [0, network, start];
|
||||
let range = this.dbGlobal.IDBKeyRange.lowerBound(lowerFilter, false);
|
||||
request = store.openCursor(range);
|
||||
} else {
|
||||
request = store.index("network").openCursor(network, "prev");
|
||||
}
|
||||
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
txn.result = null;
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
txn.result = cursor.value;
|
||||
}
|
||||
};
|
||||
}.bind(this), aResultCb);
|
||||
},
|
||||
|
||||
find: function find(aResultCb, aNetwork, aStart, aEnd, aAppId, aManifestURL) {
|
||||
let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
|
||||
let start = this.normalizeDate(aStart);
|
||||
|
@ -443,7 +540,7 @@ NetworkStatsDB.prototype = {
|
|||
debug("End time: " + new Date(end));
|
||||
}
|
||||
|
||||
this.dbNewTxn("readonly", function(aTxn, aStore) {
|
||||
this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
|
||||
let network = [aNetwork.id, aNetwork.type];
|
||||
let lowerFilter = [aAppId, network, start];
|
||||
let upperFilter = [aAppId, network, end];
|
||||
|
@ -503,7 +600,7 @@ NetworkStatsDB.prototype = {
|
|||
},
|
||||
|
||||
getAvailableNetworks: function getAvailableNetworks(aResultCb) {
|
||||
this.dbNewTxn("readonly", function(aTxn, aStore) {
|
||||
this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
|
||||
if (!aTxn.result) {
|
||||
aTxn.result = [];
|
||||
}
|
||||
|
@ -522,7 +619,7 @@ NetworkStatsDB.prototype = {
|
|||
},
|
||||
|
||||
isNetworkAvailable: function isNetworkAvailable(aNetwork, aResultCb) {
|
||||
this.dbNewTxn("readonly", function(aTxn, aStore) {
|
||||
this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
|
||||
if (!aTxn.result) {
|
||||
aTxn.result = false;
|
||||
}
|
||||
|
@ -546,10 +643,159 @@ NetworkStatsDB.prototype = {
|
|||
},
|
||||
|
||||
logAllRecords: function logAllRecords(aResultCb) {
|
||||
this.dbNewTxn("readonly", function(aTxn, aStore) {
|
||||
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,
|
||||
threshold: aAlarm.threshold,
|
||||
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,
|
||||
threshold: aRecord.threshold,
|
||||
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) {
|
||||
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) {
|
||||
let alarm = { id: cursor.value.id,
|
||||
networkId: cursor.value.networkId,
|
||||
threshold: cursor.value.threshold,
|
||||
data: cursor.value.data };
|
||||
|
||||
txn.result.push(alarm);
|
||||
}
|
||||
|
||||
cursor.continue();
|
||||
}
|
||||
}, aResultCb);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
|||
// NetworkStatsData
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
const NETWORKSTATSDATA_CID = Components.ID("{3b16fe17-5583-483a-b486-b64a3243221c}");
|
||||
const nsIDOMMozNetworkStatsData = Components.interfaces.nsIDOMMozNetworkStatsData;
|
||||
const nsIDOMMozNetworkStatsData = Ci.nsIDOMMozNetworkStatsData;
|
||||
|
||||
function NetworkStatsData(aData) {
|
||||
this.rxBytes = aData.rxBytes;
|
||||
|
@ -58,7 +58,7 @@ NetworkStatsData.prototype = {
|
|||
// NetworkStatsInterface
|
||||
const NETWORKSTATSINTERFACE_CONTRACTID = "@mozilla.org/networkstatsinterface;1";
|
||||
const NETWORKSTATSINTERFACE_CID = Components.ID("{f540615b-d803-43ff-8200-2a9d145a5645}");
|
||||
const nsIDOMMozNetworkStatsInterface = Components.interfaces.nsIDOMMozNetworkStatsInterface;
|
||||
const nsIDOMMozNetworkStatsInterface = Ci.nsIDOMMozNetworkStatsInterface;
|
||||
|
||||
function NetworkStatsInterface(aNetwork) {
|
||||
if (DEBUG) {
|
||||
|
@ -87,7 +87,7 @@ NetworkStatsInterface.prototype = {
|
|||
// NetworkStats
|
||||
const NETWORKSTATS_CONTRACTID = "@mozilla.org/networkstats;1";
|
||||
const NETWORKSTATS_CID = Components.ID("{b6fc4b14-628d-4c99-bf4e-e4ed56916cbe}");
|
||||
const nsIDOMMozNetworkStats = Components.interfaces.nsIDOMMozNetworkStats;
|
||||
const nsIDOMMozNetworkStats = Ci.nsIDOMMozNetworkStats;
|
||||
|
||||
function NetworkStats(aWindow, aStats) {
|
||||
if (DEBUG) {
|
||||
|
@ -125,11 +125,40 @@ NetworkStats.prototype = {
|
|||
nsIDOMMozNetworkStatsInterface])
|
||||
}
|
||||
|
||||
// NetworkStatsAlarm
|
||||
const NETWORKSTATSALARM_CID = Components.ID("{063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c}");
|
||||
const nsIDOMMozNetworkStatsAlarm = Ci.nsIDOMMozNetworkStatsAlarm;
|
||||
|
||||
function NetworkStatsAlarm(aAlarm) {
|
||||
this.alarmId = aAlarm.id;
|
||||
this.network = new NetworkStatsInterface(aAlarm.network);
|
||||
this.threshold = aAlarm.threshold;
|
||||
this.data = aAlarm.data;
|
||||
}
|
||||
|
||||
NetworkStatsAlarm.prototype = {
|
||||
__exposedProps__: {
|
||||
alarmId: 'r',
|
||||
network: 'r',
|
||||
threshold: 'r',
|
||||
data: 'r',
|
||||
},
|
||||
|
||||
classID : NETWORKSTATSALARM_CID,
|
||||
classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSALARM_CID,
|
||||
contractID:"@mozilla.org/networkstatsalarm;1",
|
||||
classDescription: "NetworkStatsAlarm",
|
||||
interfaces: [nsIDOMMozNetworkStatsAlarm],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsAlarm])
|
||||
};
|
||||
|
||||
// NetworkStatsManager
|
||||
|
||||
const NETWORKSTATSMANAGER_CONTRACTID = "@mozilla.org/networkStatsManager;1";
|
||||
const NETWORKSTATSMANAGER_CID = Components.ID("{5f033d31-c9a2-4e2d-83aa-6a807f1e0c11}");
|
||||
const nsIDOMMozNetworkStatsManager = Components.interfaces.nsIDOMMozNetworkStatsManager;
|
||||
const NETWORKSTATSMANAGER_CID = Components.ID("{50d109b8-0d7f-4208-81fe-5f07a759f159}");
|
||||
const nsIDOMMozNetworkStatsManager = Ci.nsIDOMMozNetworkStatsManager;
|
||||
|
||||
function NetworkStatsManager() {
|
||||
if (DEBUG) {
|
||||
|
@ -189,6 +218,52 @@ NetworkStatsManager.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
addAlarm: function addAlarm(aNetwork, aThreshold, aOptions) {
|
||||
this.checkPrivileges();
|
||||
|
||||
if (!aOptions) {
|
||||
aOptions = Object.create(null);
|
||||
}
|
||||
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("NetworkStats:SetAlarm",
|
||||
{id: this.getRequestId(request),
|
||||
data: {network: aNetwork,
|
||||
threshold: aThreshold,
|
||||
startTime: aOptions.startTime,
|
||||
data: aOptions.data,
|
||||
manifestURL: this.manifestURL,
|
||||
pageURL: this.pageURL}});
|
||||
return request;
|
||||
},
|
||||
|
||||
getAllAlarms: function getAllAlarms(aNetwork) {
|
||||
this.checkPrivileges();
|
||||
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("NetworkStats:GetAlarms",
|
||||
{id: this.getRequestId(request),
|
||||
data: {network: aNetwork,
|
||||
manifestURL: this.manifestURL}});
|
||||
return request;
|
||||
},
|
||||
|
||||
removeAlarms: function removeAlarms(aAlarmId) {
|
||||
this.checkPrivileges();
|
||||
|
||||
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() {
|
||||
this.checkPrivileges();
|
||||
|
||||
|
@ -212,8 +287,8 @@ NetworkStatsManager.prototype = {
|
|||
if (DEBUG) {
|
||||
debug("NetworkStatsmanager::receiveMessage: " + aMessage.name);
|
||||
}
|
||||
let msg = aMessage.json;
|
||||
|
||||
let msg = aMessage.json;
|
||||
let req = this.takeRequest(msg.id);
|
||||
if (!req) {
|
||||
if (DEBUG) {
|
||||
|
@ -260,6 +335,30 @@ NetworkStatsManager.prototype = {
|
|||
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 = Cu.createArrayIn(this._window);
|
||||
for (let i = 0; i < msg.result.length; i++) {
|
||||
alarms.push(new NetworkStatsAlarm(msg.result[i]));
|
||||
}
|
||||
|
||||
Services.DOMRequest.fireSuccess(req, alarms);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (DEBUG) {
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
|
@ -293,7 +392,21 @@ NetworkStatsManager.prototype = {
|
|||
this.initDOMRequestHelper(aWindow, ["NetworkStats:Get:Return",
|
||||
"NetworkStats:GetAvailableNetworks:Return",
|
||||
"NetworkStats:Clear:Return",
|
||||
"NetworkStats:ClearAll: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;
|
||||
}
|
||||
},
|
||||
|
||||
// Called from DOMRequestIpcHelper
|
||||
|
@ -316,7 +429,8 @@ NetworkStatsManager.prototype = {
|
|||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsData,
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkStatsAlarm,
|
||||
NetworkStatsData,
|
||||
NetworkStatsInterface,
|
||||
NetworkStats,
|
||||
NetworkStatsManager]);
|
||||
|
|
|
@ -7,6 +7,9 @@ contract @mozilla.org/networkStats;1 {b6fc4b14-628d-4c99-bf4e-e4ed56916cbe}
|
|||
component {f540615b-d803-43ff-8200-2a9d145a5645} NetworkStatsManager.js
|
||||
contract @mozilla.org/networkstatsinterface;1 {f540615b-d803-43ff-8200-2a9d145a5645}
|
||||
|
||||
component {5f033d31-c9a2-4e2d-83aa-6a807f1e0c11} NetworkStatsManager.js
|
||||
contract @mozilla.org/networkStatsManager;1 {5f033d31-c9a2-4e2d-83aa-6a807f1e0c11}
|
||||
component {063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c} NetworkStatsManager.js
|
||||
contract @mozilla.org/networkstatsalarm;1 {063ebeb2-5c6e-47ae-bdcd-5e6ebdc7a68c}
|
||||
|
||||
component {50d109b8-0d7f-4208-81fe-5f07a759f159} NetworkStatsManager.js
|
||||
contract @mozilla.org/networkStatsManager;1 {50d109b8-0d7f-4208-81fe-5f07a759f159}
|
||||
category JavaScript-navigator-property mozNetworkStats @mozilla.org/networkStatsManager;1
|
||||
|
|
|
@ -22,6 +22,8 @@ Cu.import("resource://gre/modules/NetworkStatsDB.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_INTERFACE_REGISTERED = "network-interface-registered";
|
||||
const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
|
||||
const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
||||
|
@ -50,6 +52,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
|||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "messenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
this.NetworkStatsService = {
|
||||
init: function() {
|
||||
debug("Service started");
|
||||
|
@ -57,6 +63,7 @@ this.NetworkStatsService = {
|
|||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, false);
|
||||
Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, 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);
|
||||
|
@ -87,6 +94,9 @@ this.NetworkStatsService = {
|
|||
this.messages = ["NetworkStats:Get",
|
||||
"NetworkStats:Clear",
|
||||
"NetworkStats:ClearAll",
|
||||
"NetworkStats:SetAlarm",
|
||||
"NetworkStats:GetAlarms",
|
||||
"NetworkStats:RemoveAlarms",
|
||||
"NetworkStats:GetAvailableNetworks",
|
||||
"NetworkStats:SampleRate",
|
||||
"NetworkStats:MaxStorageAge"];
|
||||
|
@ -107,6 +117,9 @@ this.NetworkStatsService = {
|
|||
|
||||
this.updateQueue = [];
|
||||
this.isQueueRunning = false;
|
||||
|
||||
this._currentAlarms = {};
|
||||
this.initAlarms();
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
|
@ -129,6 +142,15 @@ this.NetworkStatsService = {
|
|||
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;
|
||||
|
@ -146,7 +168,7 @@ this.NetworkStatsService = {
|
|||
case TOPIC_INTERFACE_REGISTERED:
|
||||
case TOPIC_INTERFACE_UNREGISTERED:
|
||||
|
||||
// If new interface is registered (notified from NetworkManager),
|
||||
// If new interface is registered (notified from NetworkService),
|
||||
// the stats are updated for the new interface without waiting to
|
||||
// complete the updating period.
|
||||
|
||||
|
@ -158,9 +180,27 @@ this.NetworkStatsService = {
|
|||
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");
|
||||
|
||||
|
@ -172,6 +212,7 @@ this.NetworkStatsService = {
|
|||
Services.obs.removeObserver(this, "profile-after-change");
|
||||
Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
|
||||
Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
|
||||
Services.obs.removeObserver(this, TOPIC_BANDWIDTH_CONTROL);
|
||||
|
||||
this.timer.cancel();
|
||||
this.timer = null;
|
||||
|
@ -266,6 +307,25 @@ this.NetworkStatsService = {
|
|||
});
|
||||
},
|
||||
|
||||
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
|
||||
|
@ -482,8 +542,8 @@ this.NetworkStatsService = {
|
|||
}
|
||||
} 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 isQueueRunning is false it means there is no processing currently
|
||||
// being done, so start.
|
||||
if (this.isQueueRunning) {
|
||||
if(this.updateQueue.length > 1) {
|
||||
return;
|
||||
|
@ -515,7 +575,7 @@ this.NetworkStatsService = {
|
|||
let interfaceName = this._networks[aNetId].interfaceName;
|
||||
debug("Update stats for " + interfaceName);
|
||||
|
||||
// Request stats to NetworkManager, which will get stats from netd, passing
|
||||
// Request stats to NetworkService, which will get stats from netd, passing
|
||||
// 'networkStatsAvailable' as a callback.
|
||||
if (interfaceName) {
|
||||
networkService.getNetworkInterfaceStats(interfaceName,
|
||||
|
@ -706,6 +766,262 @@ this.NetworkStatsService = {
|
|||
debug(JSON.stringify(aResult));
|
||||
});
|
||||
},
|
||||
|
||||
getAlarms: function getAlarms(mm, msg) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
let self = this;
|
||||
this._db.getAlarms(netId, manifestURL, 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.threshold,
|
||||
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 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) {
|
||||
mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
|
||||
{ id: msg.id, error: error, result: null });
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_setAlarm: function _setAlarm(aAlarm, aCallback) {
|
||||
let currentAlarm = this._currentAlarms[aAlarm.networkId];
|
||||
if (Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
|
||||
aAlarm.absoluteThreshold > currentAlarm.alarm.absoluteThreshold) {
|
||||
aCallback(null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
this._updateThreshold(aAlarm, function onUpdate(aError, aThreshold) {
|
||||
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,
|
||||
aThreshold.systemThreshold,
|
||||
callback);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback(null, true);
|
||||
});
|
||||
},
|
||||
|
||||
_updateThreshold: function _updateThreshold(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 offset = aAlarm.threshold - result.rxTotalBytes - result.txTotalBytes;
|
||||
|
||||
// Alarm set to a threshold lower than current rx/tx bytes.
|
||||
if (offset <= 0) {
|
||||
aCallback("InvalidStateError", null);
|
||||
return;
|
||||
}
|
||||
|
||||
let threshold = {
|
||||
systemThreshold: result.rxSystemBytes + result.txSystemBytes + offset,
|
||||
absoluteThreshold: result.rxTotalBytes + result.txTotalBytes + offset
|
||||
};
|
||||
|
||||
aCallback(null, threshold);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_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.threshold,
|
||||
"data": aAlarm.data };
|
||||
messenger.sendMessage("networkstats-alarm", alarm, pageURI, manifestURI);
|
||||
}
|
||||
};
|
||||
|
||||
NetworkStatsService.init();
|
||||
|
|
|
@ -15,5 +15,6 @@ MOCHITEST_FILES = \
|
|||
test_networkstats_disabled.html \
|
||||
test_networkstats_enabled_no_perm.html \
|
||||
test_networkstats_enabled_perm.html \
|
||||
test_networkstats_alarms.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for NetworkStats alarms</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function test() {
|
||||
ok(true, "Checking if no alarms are set.");
|
||||
|
||||
req = navigator.mozNetworkStats.getAllAlarms();
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(true, "Succeeded to get alarms.");
|
||||
ok(Array.isArray(req.result) && req.result.length == 0,
|
||||
"There are no alarms set.");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(false, "getAllAlarms() shouldn't fail!");
|
||||
}
|
||||
}
|
||||
|
||||
var req;
|
||||
var index = -1;
|
||||
|
||||
var wifi = {'type': 0, 'id': '0'};
|
||||
var mobile = {'type': 1, 'id': '1'};
|
||||
|
||||
var steps = [
|
||||
function () {
|
||||
ok(true, "Calling getAllAlarms() with invalid network.");
|
||||
|
||||
req = navigator.mozNetworkStats.getAllAlarms(mobile);
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(false, "getAllAlarms() shouldn't succeed!");
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(req.error.name == "InvalidInterface", "Get InvalidInterface error");
|
||||
next();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ok(true, "Calling addAlarm() with invalid network or parameters.");
|
||||
|
||||
try {
|
||||
navigator.mozNetworkStats.addAlarm();
|
||||
} catch(ex) {
|
||||
ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
|
||||
"addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no parameters");
|
||||
}
|
||||
|
||||
try {
|
||||
navigator.mozNetworkStats.addAlarm(100000);
|
||||
} catch(ex) {
|
||||
ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
|
||||
"addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no network");
|
||||
}
|
||||
|
||||
try {
|
||||
navigator.mozNetworkStats.addAlarm(wifi);
|
||||
} catch(ex) {
|
||||
ok(ex.result == SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
|
||||
"addAlarm() throws NS_ERROR_XPC_NOT_ENOUGH_ARGS exception when no threshold");
|
||||
}
|
||||
|
||||
req = navigator.mozNetworkStats.addAlarm(mobile, -100000);
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(false, "addAlarm() shouldn't succeed with negative threshold.");
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(req.error.name == "InvalidThresholdValue", "Get InvalidThresholdValue error");
|
||||
next();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ok(true, "Calling addAlarm()");
|
||||
|
||||
req = navigator.mozNetworkStats.addAlarm(wifi, 1000000);
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(true, "Succeeded to add alarm. AlarmId: " + req.result);
|
||||
next();
|
||||
};
|
||||
req.onerror = function () {
|
||||
ok(false, "addAlarm() shouldn't fail.");
|
||||
};
|
||||
},
|
||||
function () {
|
||||
ok(true, "Calling getAllAlarms()");
|
||||
|
||||
req = navigator.mozNetworkStats.getAllAlarms(wifi);
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Only one alarm");
|
||||
ok(req.result[0].alarmId == 1, "Get correct alarmId");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(false, "getAllAlarms() shouldn't fail.");
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ok(true, "Calling removeAlarms() to remove alarms.");
|
||||
|
||||
req = navigator.mozNetworkStats.removeAlarms();
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(req.result, "Succeeded to remove alarms.");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(false, "removeAlarms() shouldn't fail.");
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ok(true, "Checking if all alarms are removed.");
|
||||
|
||||
req = navigator.mozNetworkStats.getAllAlarms();
|
||||
|
||||
req.onsuccess = function () {
|
||||
ok(Array.isArray(req.result) && req.result.length == 0,
|
||||
"Succeeded to remove all alarms.");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function () {
|
||||
ok(false, "getAllAlarms() shouldn't fail.");
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
SpecialPowers.removePermission("networkstats-manage", document);
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
];
|
||||
|
||||
function next() {
|
||||
index += 1;
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
steps[index]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.addPermission("networkstats-manage", true, document);
|
||||
SpecialPowers.pushPrefEnv({'set': [["dom.mozNetworkStats.enabled", true]]}, test);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -13,10 +13,8 @@
|
|||
<script type="application/javascript">
|
||||
|
||||
function test() {
|
||||
ok('mozNetworkStats' in navigator, "navigator.mozMozNetworkStats should exist");
|
||||
ok(navigator.mozNetworkStats, "navigator.mozNetworkStats returns an object");
|
||||
|
||||
netStats = navigator.mozNetworkStats;
|
||||
netStats = window.navigator.mozNetworkStats;
|
||||
ok(netStats, "mozNetworkStats exists");
|
||||
|
||||
// Test IDL attributes
|
||||
ok('sampleRate' in netStats,
|
||||
|
|
|
@ -7,12 +7,28 @@ Cu.import("resource://gre/modules/NetworkStatsDB.jsm");
|
|||
|
||||
const netStatsDb = new NetworkStatsDB();
|
||||
|
||||
function clearWholeDB(callback) {
|
||||
netStatsDb.dbNewTxn("readwrite", function(aTxn, aStore) {
|
||||
aStore.delete();
|
||||
function clearStore(store, callback) {
|
||||
netStatsDb.dbNewTxn(store, "readwrite", function(aTxn, aStore) {
|
||||
aStore.openCursor().onsuccess = function (event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor){
|
||||
cursor.delete();
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
}, callback);
|
||||
}
|
||||
|
||||
add_test(function prepareDatabase() {
|
||||
// Clear whole database to avoid starting tests with unknown state
|
||||
// due to the previous tests.
|
||||
clearStore('net_stats', function() {
|
||||
clearStore('net_alarm', function() {
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function filterTimestamp(date) {
|
||||
var sampleRate = netStatsDb.sampleRate;
|
||||
var offset = date.getTimezoneOffset() * 60 * 1000;
|
||||
|
@ -127,10 +143,12 @@ add_test(function test_internalSaveStats_singleSample() {
|
|||
timestamp: Date.now(),
|
||||
rxBytes: 0,
|
||||
txBytes: 0,
|
||||
rxSystemBytes: 1234,
|
||||
txSystemBytes: 1234,
|
||||
rxTotalBytes: 1234,
|
||||
txTotalBytes: 1234 };
|
||||
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
netStatsDb._saveStats(txn, store, stats);
|
||||
}, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
|
@ -143,6 +161,8 @@ add_test(function test_internalSaveStats_singleSample() {
|
|||
do_check_eq(result[0].timestamp, stats.timestamp);
|
||||
do_check_eq(result[0].rxBytes, stats.rxBytes);
|
||||
do_check_eq(result[0].txBytes, stats.txBytes);
|
||||
do_check_eq(result[0].rxSystemBytes, stats.rxSystemBytes);
|
||||
do_check_eq(result[0].txSystemBytes, stats.txSystemBytes);
|
||||
do_check_eq(result[0].rxTotalBytes, stats.rxTotalBytes);
|
||||
do_check_eq(result[0].txTotalBytes, stats.txTotalBytes);
|
||||
run_next_test();
|
||||
|
@ -166,11 +186,13 @@ add_test(function test_internalSaveStats_arraySamples() {
|
|||
timestamp: Date.now() + (10 * i),
|
||||
rxBytes: 0,
|
||||
txBytes: 0,
|
||||
rxSystemBytes: 1234,
|
||||
txSystemBytes: 1234,
|
||||
rxTotalBytes: 1234,
|
||||
txTotalBytes: 1234 });
|
||||
}
|
||||
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
netStatsDb._saveStats(txn, store, stats);
|
||||
}, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
|
@ -182,7 +204,6 @@ add_test(function test_internalSaveStats_arraySamples() {
|
|||
// an empty sample to keep totalBytes synchronized with netd counters
|
||||
result.shift();
|
||||
do_check_eq(result.length, samples);
|
||||
|
||||
var success = true;
|
||||
for (var i = 1; i < samples; i++) {
|
||||
if (result[i].appId != stats[i].appId ||
|
||||
|
@ -190,6 +211,8 @@ add_test(function test_internalSaveStats_arraySamples() {
|
|||
result[i].timestamp != stats[i].timestamp ||
|
||||
result[i].rxBytes != stats[i].rxBytes ||
|
||||
result[i].txBytes != stats[i].txBytes ||
|
||||
result[i].rxSystemBytes != stats[i].rxSystemBytes ||
|
||||
result[i].txSystemBytes != stats[i].txSystemBytes ||
|
||||
result[i].rxTotalBytes != stats[i].rxTotalBytes ||
|
||||
result[i].txTotalBytes != stats[i].txTotalBytes) {
|
||||
success = false;
|
||||
|
@ -216,15 +239,17 @@ add_test(function test_internalRemoveOldStats() {
|
|||
stats.push({ appId: 0,
|
||||
network: network, timestamp: Date.now() + (10 * i),
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxSystemBytes: 1234, txSystemBytes: 1234,
|
||||
rxTotalBytes: 1234, txTotalBytes: 1234 });
|
||||
}
|
||||
|
||||
stats.push({ appId: 0,
|
||||
network: network, timestamp: Date.now() + (10 * samples),
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxSystemBytes: 1234, txSystemBytes: 1234,
|
||||
rxTotalBytes: 1234, txTotalBytes: 1234 });
|
||||
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
netStatsDb._saveStats(txn, store, stats);
|
||||
var date = stats[stats.length - 1].timestamp
|
||||
+ (netStatsDb.sampleRate * netStatsDb.maxStorageSamples - 1) - 1;
|
||||
|
@ -245,10 +270,10 @@ add_test(function test_internalRemoveOldStats() {
|
|||
function processSamplesDiff(networks, lastStat, newStat, callback) {
|
||||
netStatsDb.clearStats(networks, function (error, result){
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
netStatsDb._saveStats(txn, store, lastStat);
|
||||
}, function(error, result) {
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
let request = store.index("network").openCursor(newStat.network, "prev");
|
||||
request.onsuccess = function onsuccess(event) {
|
||||
let cursor = event.target.result;
|
||||
|
@ -276,11 +301,13 @@ add_test(function test_processSamplesDiffSameSample() {
|
|||
var lastStat = { appId: 0,
|
||||
network: network, timestamp: date,
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxTotalBytes: 1234, txTotalBytes: 1234 };
|
||||
rxSystemBytes: 1234, txSystemBytes: 1234,
|
||||
rxTotalBytes: 2234, txTotalBytes: 2234 };
|
||||
|
||||
var newStat = { appId: 0,
|
||||
network: network, timestamp: date,
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxSystemBytes: 2234, txSystemBytes: 2234,
|
||||
rxTotalBytes: 2234, txTotalBytes: 2234 };
|
||||
|
||||
processSamplesDiff(networks, lastStat, newStat, function(result) {
|
||||
|
@ -288,10 +315,12 @@ add_test(function test_processSamplesDiffSameSample() {
|
|||
do_check_eq(result[0].appId, newStat.appId);
|
||||
do_check_true(compareNetworks(result[0].network, newStat.network));
|
||||
do_check_eq(result[0].timestamp, newStat.timestamp);
|
||||
do_check_eq(result[0].rxBytes, newStat.rxTotalBytes - lastStat.rxTotalBytes);
|
||||
do_check_eq(result[0].txBytes, newStat.txTotalBytes - lastStat.txTotalBytes);
|
||||
do_check_eq(result[0].rxTotalBytes, newStat.rxTotalBytes);
|
||||
do_check_eq(result[0].txTotalBytes, newStat.txTotalBytes);
|
||||
do_check_eq(result[0].rxBytes, newStat.rxSystemBytes - lastStat.rxSystemBytes);
|
||||
do_check_eq(result[0].txBytes, newStat.txSystemBytes - lastStat.txSystemBytes);
|
||||
do_check_eq(result[0].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
|
||||
do_check_eq(result[0].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
|
||||
do_check_eq(result[0].rxSystemBytes, newStat.rxSystemBytes);
|
||||
do_check_eq(result[0].txSystemBytes, newStat.txSystemBytes);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
@ -306,22 +335,26 @@ add_test(function test_processSamplesDiffNextSample() {
|
|||
var lastStat = { appId: 0,
|
||||
network: network, timestamp: date,
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxTotalBytes: 1234, txTotalBytes: 1234 };
|
||||
rxSystemBytes: 1234, txSystemBytes: 1234,
|
||||
rxTotalBytes: 2234, txTotalBytes: 2234 };
|
||||
|
||||
var newStat = { appId: 0,
|
||||
network: network, timestamp: date + sampleRate,
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxTotalBytes: 500, txTotalBytes: 500 };
|
||||
rxSystemBytes: 1734, txSystemBytes: 1734,
|
||||
rxTotalBytes: 0, txTotalBytes: 0 };
|
||||
|
||||
processSamplesDiff(networks, lastStat, newStat, function(result) {
|
||||
do_check_eq(result.length, 2);
|
||||
do_check_eq(result[1].appId, newStat.appId);
|
||||
do_check_true(compareNetworks(result[1].network, newStat.network));
|
||||
do_check_eq(result[1].timestamp, newStat.timestamp);
|
||||
do_check_eq(result[1].rxBytes, newStat.rxTotalBytes);
|
||||
do_check_eq(result[1].txBytes, newStat.txTotalBytes);
|
||||
do_check_eq(result[1].rxTotalBytes, newStat.rxTotalBytes);
|
||||
do_check_eq(result[1].txTotalBytes, newStat.txTotalBytes);
|
||||
do_check_eq(result[1].rxBytes, newStat.rxSystemBytes - lastStat.rxSystemBytes);
|
||||
do_check_eq(result[1].txBytes, newStat.txSystemBytes - lastStat.txSystemBytes);
|
||||
do_check_eq(result[1].rxSystemBytes, newStat.rxSystemBytes);
|
||||
do_check_eq(result[1].txSystemBytes, newStat.txSystemBytes);
|
||||
do_check_eq(result[1].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
|
||||
do_check_eq(result[1].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
@ -335,12 +368,14 @@ add_test(function test_processSamplesDiffSamplesLost() {
|
|||
var lastStat = { appId: 0,
|
||||
network: network, timestamp: date,
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxTotalBytes: 1234, txTotalBytes: 1234 };
|
||||
rxSystemBytes: 1234, txSystemBytes: 1234,
|
||||
rxTotalBytes: 2234, txTotalBytes: 2234};
|
||||
|
||||
var newStat = { appId: 0,
|
||||
network: network, timestamp: date + (sampleRate * samples),
|
||||
rxBytes: 0, txBytes: 0,
|
||||
rxTotalBytes: 2234, txTotalBytes: 2234 };
|
||||
rxSystemBytes: 2234, txSystemBytes: 2234,
|
||||
rxTotalBytes: 0, txTotalBytes: 0 };
|
||||
|
||||
processSamplesDiff(networks, lastStat, newStat, function(result) {
|
||||
do_check_eq(result.length, samples + 1);
|
||||
|
@ -349,8 +384,10 @@ add_test(function test_processSamplesDiffSamplesLost() {
|
|||
do_check_eq(result[samples].timestamp, newStat.timestamp);
|
||||
do_check_eq(result[samples].rxBytes, newStat.rxTotalBytes - lastStat.rxTotalBytes);
|
||||
do_check_eq(result[samples].txBytes, newStat.txTotalBytes - lastStat.txTotalBytes);
|
||||
do_check_eq(result[samples].rxTotalBytes, newStat.rxTotalBytes);
|
||||
do_check_eq(result[samples].txTotalBytes, newStat.txTotalBytes);
|
||||
do_check_eq(result[samples].rxSystemBytes, newStat.rxSystemBytes);
|
||||
do_check_eq(result[samples].txSystemBytes, newStat.txSystemBytes);
|
||||
do_check_eq(result[samples].rxTotalBytes, lastStat.rxTotalBytes + newStat.rxSystemBytes - lastStat.rxSystemBytes);
|
||||
do_check_eq(result[samples].txTotalBytes, lastStat.txTotalBytes + newStat.txSystemBytes - lastStat.txSystemBytes);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
@ -366,8 +403,7 @@ add_test(function test_saveStats() {
|
|||
rxBytes: 2234,
|
||||
txBytes: 2234};
|
||||
|
||||
netStatsDb.clearStats(networks, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
clearStore('net_stats', function() {
|
||||
netStatsDb.saveStats(stats, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.logAllRecords(function(error, result) {
|
||||
|
@ -377,8 +413,10 @@ add_test(function test_saveStats() {
|
|||
do_check_true(compareNetworks(result[0].network, network));
|
||||
let timestamp = filterTimestamp(stats.date);
|
||||
do_check_eq(result[0].timestamp, timestamp);
|
||||
do_check_eq(result[0].rxBytes, 0);
|
||||
do_check_eq(result[0].txBytes, 0);
|
||||
do_check_eq(result[0].rxBytes, stats.rxBytes);
|
||||
do_check_eq(result[0].txBytes, stats.txBytes);
|
||||
do_check_eq(result[0].rxSystemBytes, stats.rxBytes);
|
||||
do_check_eq(result[0].txSystemBytes, stats.txBytes);
|
||||
do_check_eq(result[0].rxTotalBytes, stats.rxBytes);
|
||||
do_check_eq(result[0].txTotalBytes, stats.txBytes);
|
||||
run_next_test();
|
||||
|
@ -416,6 +454,8 @@ add_test(function test_saveAppStats() {
|
|||
do_check_eq(result[1].timestamp, timestamp);
|
||||
do_check_eq(result[1].rxBytes, stats.rxBytes);
|
||||
do_check_eq(result[1].txBytes, stats.txBytes);
|
||||
do_check_eq(result[1].rxSystemBytes, 0);
|
||||
do_check_eq(result[1].txSystemBytes, 0);
|
||||
do_check_eq(result[1].rxTotalBytes, 0);
|
||||
do_check_eq(result[1].txTotalBytes, 0);
|
||||
run_next_test();
|
||||
|
@ -427,7 +467,7 @@ add_test(function test_saveAppStats() {
|
|||
function prepareFind(network, stats, callback) {
|
||||
netStatsDb.clearStats(network, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.dbNewTxn("readwrite", function(txn, store) {
|
||||
netStatsDb.dbNewTxn("net_stats", "readwrite", function(txn, store) {
|
||||
netStatsDb._saveStats(txn, store, stats);
|
||||
}, function(error, result) {
|
||||
callback(error, result);
|
||||
|
@ -452,11 +492,14 @@ add_test(function test_find () {
|
|||
stats.push({ appId: appId,
|
||||
network: networkWifi, timestamp: saveDate + (sampleRate * i),
|
||||
rxBytes: 0, txBytes: 10,
|
||||
rxSystemBytes: 0, txSystemBytes: 0,
|
||||
rxTotalBytes: 0, txTotalBytes: 0});
|
||||
|
||||
|
||||
stats.push({ appId: appId,
|
||||
network: networkMobile, timestamp: saveDate + (sampleRate * i),
|
||||
rxBytes: 0, txBytes: 10,
|
||||
rxSystemBytes: 0, txSystemBytes: 0,
|
||||
rxTotalBytes: 0, txTotalBytes: 0});
|
||||
}
|
||||
|
||||
|
@ -569,6 +612,7 @@ add_test(function test_saveMultipleAppStats () {
|
|||
do_check_eq(result[0].txBytes, 10);
|
||||
run_next_test();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
|
@ -577,12 +621,188 @@ add_test(function test_saveMultipleAppStats () {
|
|||
});
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
var networkWifi = '00';
|
||||
var networkMobile = '11';
|
||||
|
||||
// Clear whole database to avoid start tests with unknown state
|
||||
// due to previous tests.
|
||||
clearWholeDB(function(){
|
||||
var examplePageURL = "http://example.com/index.html";
|
||||
var exampleManifestURL = "http://example.com/manifest.webapp";
|
||||
|
||||
var testPageURL = "http://test.com/index.html";
|
||||
var testManifestURL = "http://test.com/manifest.webapp";
|
||||
|
||||
var alarms = [{ id: null,
|
||||
networkId: networkWifi,
|
||||
threshold: 10000,
|
||||
data: {foo: "something"},
|
||||
pageURL: examplePageURL,
|
||||
manifestURL: exampleManifestURL },
|
||||
{ id: null,
|
||||
networkId: networkWifi,
|
||||
threshold: 1000,
|
||||
data: {foo: "else"},
|
||||
pageURL: examplePageURL,
|
||||
manifestURL: exampleManifestURL },
|
||||
{ id: null,
|
||||
networkId: networkMobile,
|
||||
threshold: 100,
|
||||
data: {foo: "to"},
|
||||
pageURL: examplePageURL,
|
||||
manifestURL: exampleManifestURL },
|
||||
{ id: null,
|
||||
networkId: networkMobile,
|
||||
threshold: 10,
|
||||
data: {foo: "test"},
|
||||
pageURL: testPageURL,
|
||||
manifestURL: testManifestURL }];
|
||||
|
||||
var alarmsDbId = 1;
|
||||
|
||||
add_test(function test_addAlarm() {
|
||||
// Add alarms[0] -> DB: [ alarms[0] (id: 1) ]
|
||||
// Check the insertion is OK.
|
||||
netStatsDb.addAlarm(alarms[0], function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
alarmsDbId = result;
|
||||
netStatsDb.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, exampleManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 1);
|
||||
do_check_eq(result[0].id, alarmsDbId);
|
||||
do_check_eq(result[0].networkId, alarms[0].networkId);
|
||||
do_check_eq(result[0].threshold, alarms[0].threshold);
|
||||
do_check_eq(result[0].data.foo, alarms[0].data.foo);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_getFirstAlarm() {
|
||||
// Add alarms[1] -> DB: [ alarms[0] (id: 1), alarms[1] (id: 2) ]
|
||||
// Check first alarm is alarms[1] because threshold is lower.
|
||||
alarmsDbId += 1;
|
||||
netStatsDb.addAlarm(alarms[1], function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result, alarmsDbId);
|
||||
netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.id, alarmsDbId);
|
||||
do_check_eq(result.networkId, alarms[1].networkId);
|
||||
do_check_eq(result.threshold, alarms[1].threshold);
|
||||
do_check_eq(result.data.foo, alarms[1].data.foo);
|
||||
do_check_eq(result.pageURL, alarms[1].pageURL);
|
||||
do_check_eq(result.manifestURL, alarms[1].manifestURL);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_removeAlarm() {
|
||||
// Remove alarms[1] (id: 2) -> DB: [ alarms[0] (id: 1) ]
|
||||
// Check get first return alarms[0].
|
||||
netStatsDb.removeAlarm(alarmsDbId, alarms[0].manifestURL, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.id, alarmsDbId - 1);
|
||||
do_check_eq(result.networkId, alarms[0].networkId);
|
||||
do_check_eq(result.threshold, alarms[0].threshold);
|
||||
do_check_eq(result.data.foo, alarms[0].data.foo);
|
||||
do_check_eq(result.pageURL, alarms[0].pageURL);
|
||||
do_check_eq(result.manifestURL, alarms[0].manifestURL);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_removeAppAlarm() {
|
||||
// Remove alarms[0] (id: 1) -> DB: [ ]
|
||||
netStatsDb.removeAlarm(alarmsDbId - 1, alarms[0].manifestURL, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.getAlarms(networkWifi, exampleManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 0);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_getAlarms() {
|
||||
// Add all alarms -> DB: [ alarms[0] (id: 3),
|
||||
// alarms[1] (id: 4),
|
||||
// alarms[2] (id: 5),
|
||||
// alarms[3] (id: 6) ]
|
||||
// Check that getAlarms for wifi returns 2 alarms.
|
||||
// Check that getAlarms for all connections returns 3 alarms.
|
||||
|
||||
var callback = function () {
|
||||
netStatsDb.getAlarms(networkWifi, exampleManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 2);
|
||||
netStatsDb.getAlarms(null, exampleManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 3);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var index = 0;
|
||||
|
||||
var addFunction = function () {
|
||||
alarmsDbId += 1;
|
||||
netStatsDb.addAlarm(alarms[index], function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
index += 1;
|
||||
do_check_eq(result, alarmsDbId);
|
||||
if (index >= alarms.length) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
addFunction();
|
||||
});
|
||||
};
|
||||
|
||||
addFunction();
|
||||
});
|
||||
|
||||
add_test(function test_removeAppAllAlarms() {
|
||||
// Remove all alarms for exampleManifestURL -> DB: [ alarms[3] (id: 6) ]
|
||||
netStatsDb.removeAlarms(exampleManifestURL, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.getAlarms(null, exampleManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 0);
|
||||
netStatsDb.getAlarms(null, testManifestURL, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 1);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_updateAlarm() {
|
||||
// Update alarms[3] (id: 6) -> DB: [ alarms[3]* (id: 6) ]
|
||||
|
||||
var updatedAlarm = alarms[1];
|
||||
updatedAlarm.id = alarmsDbId;
|
||||
updatedAlarm.threshold = 10;
|
||||
|
||||
netStatsDb.updateAlarm(updatedAlarm, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.id, updatedAlarm.id);
|
||||
do_check_eq(result.networkId, updatedAlarm.networkId);
|
||||
do_check_eq(result.threshold, updatedAlarm.threshold);
|
||||
do_check_eq(result.data.foo, updatedAlarm.data.foo);
|
||||
do_check_eq(result.pageURL, updatedAlarm.pageURL);
|
||||
do_check_eq(result.manifestURL, updatedAlarm.manifestURL);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -139,9 +139,97 @@ add_test(function test_queue() {
|
|||
do_check_eq(NetworkStatsService.updateQueue[0].callbacks[0], null);
|
||||
do_check_neq(NetworkStatsService.updateQueue[0].callbacks[1], null);
|
||||
|
||||
// Clear queue because in test environment requests for mobile networks
|
||||
// can not be handled.
|
||||
NetworkStatsService.updateQueue = [];
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
var wifiId = '00';
|
||||
|
||||
add_test(function test_updateThreshold() {
|
||||
let alarm = { networkId: wifiId, threshold: 10000 };
|
||||
|
||||
NetworkStatsService._updateThreshold(alarm, function onSet(error, threshold){
|
||||
do_check_eq(error, null);
|
||||
do_check_neq(threshold.systemThreshold, undefined);
|
||||
do_check_neq(threshold.absoluteThreshold, undefined);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
var testPageURL = "http://test.com";
|
||||
var testManifestURL = "http://test.com/manifest.webapp";
|
||||
|
||||
add_test(function test_setAlarm() {
|
||||
let alarm = { id: null,
|
||||
networkId: wifiId,
|
||||
threshold: 10000,
|
||||
absoluteThreshold: null,
|
||||
alarmStart: null,
|
||||
alarmEnd: null,
|
||||
data: null,
|
||||
pageURL: testPageURL,
|
||||
manifestURL: testManifestURL };
|
||||
|
||||
NetworkStatsService._setAlarm(alarm, function onSet(error, result) {
|
||||
do_check_eq(result, 1);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_setAlarm_invalid_threshold() {
|
||||
let alarm = { id: null,
|
||||
networkId: wifiId,
|
||||
threshold: -10000,
|
||||
absoluteThreshold: null,
|
||||
alarmStart: null,
|
||||
alarmEnd: null,
|
||||
data: null,
|
||||
pageURL: testPageURL,
|
||||
manifestURL: testManifestURL };
|
||||
|
||||
NetworkStatsService._setAlarm(alarm, function onSet(error, result) {
|
||||
do_check_eq(error, "InvalidStateError");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_fireAlarm() {
|
||||
// Add a fake alarm into database.
|
||||
let alarm = { id: null,
|
||||
networkId: wifiId,
|
||||
threshold: 10000,
|
||||
absoluteThreshold: null,
|
||||
alarmStart: null,
|
||||
alarmEnd: null,
|
||||
data: null,
|
||||
pageURL: testPageURL,
|
||||
manifestURL: testManifestURL };
|
||||
|
||||
NetworkStatsService._db.addAlarm(alarm, function addSuccessCb(error, newId) {
|
||||
NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
|
||||
testManifestURL, function onGet(error, result) {
|
||||
do_check_eq(error, null);
|
||||
do_check_eq(result.length, 1);
|
||||
|
||||
// Result of getAlarms is based on expected child's data format, so
|
||||
// some changes are needed to be able to use it.
|
||||
result[0].networkId = wifiId;
|
||||
result[0].pageURL = testPageURL;
|
||||
result[0].manifestURL = testManifestURL;
|
||||
|
||||
NetworkStatsService._fireAlarm(result[0], false);
|
||||
NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
|
||||
testManifestURL, function onGet(error, result) {
|
||||
do_check_eq(error, undefined);
|
||||
do_check_eq(result.length, 0);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
||||
|
|
|
@ -8,12 +8,33 @@
|
|||
|
||||
#include "MozNdefRecord.h"
|
||||
#include "mozilla/dom/MozNdefRecordBinding.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(MozNdefRecord, mWindow)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MozNdefRecord)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MozNdefRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MozNdefRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(MozNdefRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mType)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mId)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPayload)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MozNdefRecord)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MozNdefRecord)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MozNdefRecord)
|
||||
|
@ -21,11 +42,32 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MozNdefRecord)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
void
|
||||
MozNdefRecord::HoldData()
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
void
|
||||
MozNdefRecord::DropData()
|
||||
{
|
||||
if (mType) {
|
||||
mType = nullptr;
|
||||
}
|
||||
if (mId) {
|
||||
mId = nullptr;
|
||||
}
|
||||
if (mPayload) {
|
||||
mPayload = nullptr;
|
||||
}
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<MozNdefRecord>
|
||||
MozNdefRecord::Constructor(const GlobalObject& aGlobal,
|
||||
uint8_t aTnf, const nsAString& aType,
|
||||
const nsAString& aId, const nsAString& aPayload,
|
||||
uint8_t aTnf, const Uint8Array& aType,
|
||||
const Uint8Array& aId, const Uint8Array& aPayload,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
@ -33,25 +75,35 @@ MozNdefRecord::Constructor(const GlobalObject& aGlobal,
|
|||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<MozNdefRecord> ndefrecord =
|
||||
new MozNdefRecord(win, aTnf, aType, aId, aPayload);
|
||||
|
||||
nsRefPtr<MozNdefRecord> ndefrecord = new MozNdefRecord(aGlobal.GetContext(),
|
||||
win, aTnf, aType, aId,
|
||||
aPayload);
|
||||
if (!ndefrecord) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
return ndefrecord.forget();
|
||||
}
|
||||
|
||||
MozNdefRecord::MozNdefRecord(nsPIDOMWindow* aWindow,
|
||||
uint8_t aTnf, const nsAString& aType,
|
||||
const nsAString& aId, const nsAString& aPayload)
|
||||
MozNdefRecord::MozNdefRecord(JSContext* aCx, nsPIDOMWindow* aWindow,
|
||||
uint8_t aTnf, const Uint8Array& aType,
|
||||
const Uint8Array& aId, const Uint8Array& aPayload)
|
||||
: mTnf(aTnf)
|
||||
, mType(aType)
|
||||
, mId(aId)
|
||||
, mPayload(aPayload)
|
||||
{
|
||||
mWindow = aWindow;
|
||||
mWindow = aWindow; // For GetParentObject()
|
||||
|
||||
mType = Uint8Array::Create(aCx, this, aType.Length(), aType.Data());
|
||||
mId = Uint8Array::Create(aCx, this, aId.Length(), aId.Data());
|
||||
mPayload = Uint8Array::Create(aCx, this, aPayload.Length(), aPayload.Data());
|
||||
|
||||
SetIsDOMBinding();
|
||||
HoldData();
|
||||
}
|
||||
|
||||
MozNdefRecord::~MozNdefRecord()
|
||||
{
|
||||
DropData();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
#include "nsIDocument.h"
|
||||
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/GCAPI.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -31,9 +35,9 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
MozNdefRecord(nsPIDOMWindow* aWindow,
|
||||
uint8_t aTnf, const nsAString& aType,
|
||||
const nsAString& aId, const nsAString& aPlayload);
|
||||
MozNdefRecord(JSContext* aCx, nsPIDOMWindow* aWindow, uint8_t aTnf,
|
||||
const Uint8Array& aType, const Uint8Array& aId,
|
||||
const Uint8Array& aPlayload);
|
||||
|
||||
~MozNdefRecord();
|
||||
|
||||
|
@ -45,41 +49,56 @@ public:
|
|||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<MozNdefRecord> Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
uint8_t aTnf, const nsAString& aType,
|
||||
const nsAString& aId,
|
||||
const nsAString& aPayload,
|
||||
ErrorResult& aRv);
|
||||
static already_AddRefed<MozNdefRecord>
|
||||
Constructor(const GlobalObject& aGlobal, uint8_t aTnf,
|
||||
const Uint8Array& aType, const Uint8Array& aId,
|
||||
const Uint8Array& aPayload, ErrorResult& aRv);
|
||||
|
||||
uint8_t Tnf() const
|
||||
{
|
||||
return mTnf;
|
||||
}
|
||||
|
||||
void GetType(nsString& aType) const
|
||||
JSObject* Type(JSContext* cx) const
|
||||
{
|
||||
aType = mType;
|
||||
return GetTypeObject();
|
||||
}
|
||||
JSObject* GetTypeObject() const
|
||||
{
|
||||
JS::ExposeObjectToActiveJS(mType);
|
||||
return mType;
|
||||
}
|
||||
|
||||
void GetId(nsString& aId) const
|
||||
JSObject* Id(JSContext* cx) const
|
||||
{
|
||||
aId = mId;
|
||||
return GetIdObject();
|
||||
}
|
||||
JSObject* GetIdObject() const
|
||||
{
|
||||
JS::ExposeObjectToActiveJS(mId);
|
||||
return mId;
|
||||
}
|
||||
|
||||
void GetPayload(nsString& aPayload) const
|
||||
JSObject* Payload(JSContext* cx) const
|
||||
{
|
||||
aPayload = mPayload;
|
||||
return GetPayloadObject();
|
||||
}
|
||||
JSObject* GetPayloadObject() const
|
||||
{
|
||||
JS::ExposeObjectToActiveJS(mPayload);
|
||||
return mPayload;
|
||||
}
|
||||
|
||||
private:
|
||||
MozNdefRecord() MOZ_DELETE;
|
||||
nsRefPtr<nsPIDOMWindow> mWindow;
|
||||
void HoldData();
|
||||
void DropData();
|
||||
|
||||
uint8_t mTnf;
|
||||
nsString mType;
|
||||
nsString mId;
|
||||
nsString mPayload;
|
||||
JS::Heap<JSObject*> mType;
|
||||
JS::Heap<JSObject*> mId;
|
||||
JS::Heap<JSObject*> mPayload;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -10,7 +10,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
|
||||
const NETWORKSERVICE_CID = Components.ID("{a6c58260-46df-11e3-8f96-0800200c9a66}");
|
||||
const NETWORKSERVICE_CID = Components.ID("{c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c}");
|
||||
|
||||
// 1xx - Requested action is proceeding
|
||||
const NETD_COMMAND_PROCEEDING = 100;
|
||||
|
@ -117,13 +117,89 @@ NetworkService.prototype = {
|
|||
params.isAsync = true;
|
||||
|
||||
this.controlMessage(params, function(result) {
|
||||
let success = result.resultCode >= NETD_COMMAND_OKAY &&
|
||||
result.resultCode < NETD_COMMAND_ERROR;
|
||||
let success = !isError(result.resultCode);
|
||||
callback.networkStatsAvailable(success, result.rxBytes,
|
||||
result.txBytes, result.date);
|
||||
});
|
||||
},
|
||||
|
||||
setNetworkInterfaceAlarm: function setNetworkInterfaceAlarm(networkName, threshold, callback) {
|
||||
if (!networkName) {
|
||||
callback.networkUsageAlarmResult(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (threshold < 0) {
|
||||
this._disableNetworkInterfaceAlarm(networkName, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
this._setNetworkInterfaceAlarm(networkName, threshold, callback);
|
||||
},
|
||||
|
||||
_setNetworkInterfaceAlarm: function _setNetworkInterfaceAlarm(networkName, threshold, callback) {
|
||||
debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
|
||||
|
||||
let params = {
|
||||
cmd: "setNetworkInterfaceAlarm",
|
||||
ifname: networkName,
|
||||
threshold: threshold
|
||||
};
|
||||
|
||||
params.report = true;
|
||||
params.isAsync = true;
|
||||
|
||||
this.controlMessage(params, function(result) {
|
||||
if (!isError(result.resultCode)) {
|
||||
callback.networkUsageAlarmResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this._enableNetworkInterfaceAlarm(networkName, threshold, callback);
|
||||
});
|
||||
},
|
||||
|
||||
_enableNetworkInterfaceAlarm: function _enableNetworkInterfaceAlarm(networkName, threshold, callback) {
|
||||
debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
|
||||
|
||||
let params = {
|
||||
cmd: "enableNetworkInterfaceAlarm",
|
||||
ifname: networkName,
|
||||
threshold: threshold
|
||||
};
|
||||
|
||||
params.report = true;
|
||||
params.isAsync = true;
|
||||
|
||||
this.controlMessage(params, function(result) {
|
||||
if (!isError(result.resultCode)) {
|
||||
callback.networkUsageAlarmResult(null);
|
||||
return;
|
||||
}
|
||||
callback.networkUsageAlarmResult(result.reason);
|
||||
});
|
||||
},
|
||||
|
||||
_disableNetworkInterfaceAlarm: function _disableNetworkInterfaceAlarm(networkName, callback) {
|
||||
debug("disableNetworkInterfaceAlarm for " + networkName);
|
||||
|
||||
let params = {
|
||||
cmd: "disableNetworkInterfaceAlarm",
|
||||
ifname: networkName,
|
||||
};
|
||||
|
||||
params.report = true;
|
||||
params.isAsync = true;
|
||||
|
||||
this.controlMessage(params, function(result) {
|
||||
if (!isError(result.resultCode)) {
|
||||
callback.networkUsageAlarmResult(null);
|
||||
return;
|
||||
}
|
||||
callback.networkUsageAlarmResult(result.reason);
|
||||
});
|
||||
},
|
||||
|
||||
setWifiOperationMode: function setWifiOperationMode(interfaceName, mode, callback) {
|
||||
if(DEBUG) debug("setWifiOperationMode on " + interfaceName + " to " + mode);
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# NetworkService.js
|
||||
component {a6c58260-46df-11e3-8f96-0800200c9a66} NetworkService.js
|
||||
contract @mozilla.org/network/service;1 {a6c58260-46df-11e3-8f96-0800200c9a66}
|
||||
component {c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c} NetworkService.js
|
||||
contract @mozilla.org/network/service;1 {c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c}
|
||||
|
|
|
@ -151,7 +151,19 @@ function networkInterfaceStatsFail(params) {
|
|||
function networkInterfaceStatsSuccess(params) {
|
||||
// Notify the main thread.
|
||||
params.txBytes = parseFloat(params.resultReason);
|
||||
postMessage(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
function networkInterfaceAlarmFail(params) {
|
||||
// Notify the main thread.
|
||||
postMessage(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
function networkInterfaceAlarmSuccess(params) {
|
||||
// Notify the main thread.
|
||||
params.error = parseFloat(params.resultReason);
|
||||
postMessage(params);
|
||||
return true;
|
||||
}
|
||||
|
@ -607,6 +619,31 @@ function getTxBytes(params, callback) {
|
|||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function enableAlarm(params, callback) {
|
||||
let command = "bandwidth enable";
|
||||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function disableAlarm(params, callback) {
|
||||
let command = "bandwidth disable";
|
||||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function setQuota(params, callback) {
|
||||
let command = "bandwidth setiquota " + params.ifname + " " + parseInt('0xffffffffffffffff');
|
||||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function removeQuota(params, callback) {
|
||||
let command = "bandwidth removeiquota " + params.ifname;
|
||||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function setAlarm(params, callback) {
|
||||
let command = "bandwidth setinterfacealert " + params.ifname + " " + params.threshold;
|
||||
return doCommand(command, callback);
|
||||
}
|
||||
|
||||
function escapeQuote(str) {
|
||||
str = str.replace(/\\/g, "\\\\");
|
||||
return str.replace(/"/g, "\\\"");
|
||||
|
@ -914,6 +951,39 @@ function getNetworkInterfaceStats(params) {
|
|||
return true;
|
||||
}
|
||||
|
||||
let gNetworkInterfaceEnableAlarmChain = [enableAlarm,
|
||||
setQuota,
|
||||
setAlarm,
|
||||
networkInterfaceAlarmSuccess];
|
||||
|
||||
function enableNetworkInterfaceAlarm(params) {
|
||||
debug("enableNetworkInterfaceAlarms: " + params.ifname);
|
||||
|
||||
chain(params, gNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
|
||||
return true;
|
||||
}
|
||||
|
||||
let gNetworkInterfaceDisableAlarmChain = [removeQuota,
|
||||
disableAlarm,
|
||||
networkInterfaceAlarmSuccess];
|
||||
|
||||
function disableNetworkInterfaceAlarm(params) {
|
||||
debug("disableNetworkInterfaceAlarms: " + params.ifname);
|
||||
|
||||
chain(params, gNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
|
||||
return true;
|
||||
}
|
||||
|
||||
let gNetworkInterfaceSetAlarmChain = [setAlarm,
|
||||
networkInterfaceAlarmSuccess];
|
||||
|
||||
function setNetworkInterfaceAlarm(params) {
|
||||
debug("setNetworkInterfaceAlarms: " + params.ifname);
|
||||
|
||||
chain(params, gNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
|
||||
return true;
|
||||
}
|
||||
|
||||
let gWifiOperationModeChain = [wifiFirmwareReload,
|
||||
wifiOperationModeSuccess];
|
||||
|
||||
|
|
|
@ -48,8 +48,7 @@ this.NFC_TECHS = {
|
|||
0:'NDEF',
|
||||
1:'NDEF_WRITEABLE',
|
||||
2:'NDEF_FORMATABLE',
|
||||
3:'P2P',
|
||||
4:'NFC_A'
|
||||
3:'P2P'
|
||||
};
|
||||
|
||||
// TODO: Bug 933595. Fill-in all error codes for Gonk/nfcd protocol
|
||||
|
|
|
@ -112,32 +112,23 @@ let NfcWorker = {
|
|||
let records = [];
|
||||
|
||||
for (let i = 0; i < numOfRecords; i++) {
|
||||
let tnf = Buf.readInt32();
|
||||
let tnf = Buf.readInt32() & 0xff;
|
||||
let typeLength = Buf.readInt32();
|
||||
let type = [];
|
||||
for (let i = 0; i < typeLength; i++) {
|
||||
type.push(Buf.readUint8());
|
||||
}
|
||||
let type = Buf.readUint8Array(typeLength);
|
||||
let padding = getPaddingLen(typeLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
|
||||
let idLength = Buf.readInt32();
|
||||
let id = [];
|
||||
for (let i = 0; i < idLength; i++) {
|
||||
id.push(Buf.readUint8());
|
||||
}
|
||||
let id = Buf.readUint8Array(idLength);
|
||||
padding = getPaddingLen(idLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
|
||||
let payloadLength = Buf.readInt32();
|
||||
let payload = [];
|
||||
for (let i = 0; i < payloadLength; i++) {
|
||||
payload.push(Buf.readUint8());
|
||||
}
|
||||
let payload = Buf.readUint8Array(payloadLength);
|
||||
padding = getPaddingLen(payloadLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
|
@ -196,30 +187,30 @@ let NfcWorker = {
|
|||
let record = records[i];
|
||||
Buf.writeInt32(record.tnf);
|
||||
|
||||
let typeLength = record.type.length;
|
||||
let typeLength = record.type ? record.type.length : 0;
|
||||
Buf.writeInt32(typeLength);
|
||||
for (let j = 0; j < typeLength; j++) {
|
||||
Buf.writeUint8(record.type.charCodeAt(j));
|
||||
Buf.writeUint8(record.type[j]);
|
||||
}
|
||||
let padding = getPaddingLen(typeLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.writeUint8(0x00);
|
||||
}
|
||||
|
||||
let idLength = record.id.length;
|
||||
let idLength = record.id ? record.id.length : 0;
|
||||
Buf.writeInt32(idLength);
|
||||
for (let j = 0; j < idLength; j++) {
|
||||
Buf.writeUint8(record.id.charCodeAt(j));
|
||||
Buf.writeUint8(record.id[j]);
|
||||
}
|
||||
padding = getPaddingLen(idLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.writeUint8(0x00);
|
||||
}
|
||||
|
||||
let payloadLength = record.payload && record.payload.length;
|
||||
let payloadLength = record.payload ? record.payload.length : 0;
|
||||
Buf.writeInt32(payloadLength);
|
||||
for (let j = 0; j < payloadLength; j++) {
|
||||
Buf.writeUint8(record.payload.charCodeAt(j));
|
||||
Buf.writeUint8(record.payload[j]);
|
||||
}
|
||||
padding = getPaddingLen(payloadLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
|
@ -382,7 +373,10 @@ NfcWorker[NFC_NOTIFICATION_TECH_DISCOVERED] = function NFC_NOTIFICATION_TECH_DIS
|
|||
let sessionId = Buf.readInt32();
|
||||
let techCount = Buf.readInt32();
|
||||
for (let count = 0; count < techCount; count++) {
|
||||
techs.push(NFC_TECHS[Buf.readUint8()]);
|
||||
let tech = NFC_TECHS[Buf.readUint8()];
|
||||
if (tech) {
|
||||
techs.push(tech);
|
||||
}
|
||||
}
|
||||
|
||||
let padding = getPaddingLen(techCount);
|
||||
|
|
|
@ -28,6 +28,12 @@ interface nsINetworkStatsCallback : nsISupports
|
|||
in jsval date);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(0706bfa2-ac2d-11e2-9a8d-7b6d988d4767)]
|
||||
interface nsINetworkUsageAlarmCallback : nsISupports
|
||||
{
|
||||
void networkUsageAlarmResult(in jsval error);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(9ede8720-f8bc-11e2-b778-0800200c9a66)]
|
||||
interface nsIWifiOperationModeCallback : nsISupports
|
||||
{
|
||||
|
@ -98,7 +104,7 @@ interface nsIUpdateUpStreamCallback : nsISupports
|
|||
/**
|
||||
* Provide network services.
|
||||
*/
|
||||
[scriptable, uuid(a6c58260-46df-11e3-8f96-0800200c9a66)]
|
||||
[scriptable, uuid(c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c)]
|
||||
interface nsINetworkService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -151,6 +157,24 @@ interface nsINetworkService : nsISupports
|
|||
*/
|
||||
void getNetworkInterfaceStats(in DOMString networkName, in nsINetworkStatsCallback callback);
|
||||
|
||||
/**
|
||||
* Set Alarm of usage per interface
|
||||
*
|
||||
* @param networkName
|
||||
* Select the Network interface to set an alarm.
|
||||
*
|
||||
* @param threshold
|
||||
* Amount of data that will trigger the alarm.
|
||||
*
|
||||
* @param callback
|
||||
* Callback to notify the result.
|
||||
*
|
||||
* @return false if there is no interface registered for the networkType param.
|
||||
*/
|
||||
boolean setNetworkInterfaceAlarm(in DOMString networkName,
|
||||
in long threshold,
|
||||
in nsINetworkUsageAlarmCallback callback);
|
||||
|
||||
/**
|
||||
* Reload Wifi firmware to specific operation mode.
|
||||
*
|
||||
|
|
|
@ -3014,7 +3014,6 @@ let RIL = {
|
|||
}
|
||||
|
||||
ICCRecordHelper.fetchICCRecords();
|
||||
this.reportStkServiceIsRunning();
|
||||
}
|
||||
|
||||
this.cardState = newCardState;
|
||||
|
@ -11225,6 +11224,7 @@ let ICCRecordHelper = {
|
|||
if (DEBUG) debug("ICCID: " + RIL.iccInfo.iccid);
|
||||
if (RIL.iccInfo.iccid) {
|
||||
ICCUtilsHelper.handleICCInfoChange();
|
||||
RIL.reportStkServiceIsRunning();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,12 @@ interface CameraControl {
|
|||
[Throws]
|
||||
attribute any thumbnailSize;
|
||||
|
||||
/* the angle, in degrees, that the image sensor is mounted relative
|
||||
to the display; e.g. if 'sensorAngle' is 270 degrees (or -90 degrees),
|
||||
then the preview stream needs to be rotated +90 degrees to have the
|
||||
same orientation as the real world. */
|
||||
readonly attribute long sensorAngle;
|
||||
|
||||
/* tell the camera to attempt to focus the image */
|
||||
[Throws]
|
||||
void autoFocus(CameraAutoFocusCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
/* Copyright © 2013 Deutsche Telekom, Inc. */
|
||||
|
||||
[Constructor(octet tnf, DOMString type, DOMString id, DOMString payload)]
|
||||
[Constructor(octet tnf, Uint8Array type, Uint8Array id, Uint8Array payload)]
|
||||
interface MozNdefRecord
|
||||
{
|
||||
/**
|
||||
|
@ -19,20 +19,25 @@ interface MozNdefRecord
|
|||
* tnf_unchanged: 0x06
|
||||
* tnf_reserved: 0x07
|
||||
*/
|
||||
[Constant]
|
||||
readonly attribute octet tnf;
|
||||
|
||||
/**
|
||||
* type - Describes the content of the payload. This can be a mime type.
|
||||
*/
|
||||
readonly attribute DOMString type;
|
||||
[Constant]
|
||||
readonly attribute Uint8Array type;
|
||||
|
||||
/**
|
||||
* id - Identifer is application dependent.
|
||||
*/
|
||||
readonly attribute DOMString id;
|
||||
[Constant]
|
||||
readonly attribute Uint8Array id;
|
||||
|
||||
/**
|
||||
* payload - Binary data blob. The meaning of this field is application dependent.
|
||||
* payload - Binary data blob. The meaning of this field is application
|
||||
* dependent.
|
||||
*/
|
||||
readonly attribute DOMString payload;
|
||||
[Constant]
|
||||
readonly attribute Uint8Array payload;
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@ static float gMaxEventAcceleration = 999.0f;
|
|||
/**
|
||||
* Amount of friction applied during flings.
|
||||
*/
|
||||
static float gFlingFriction = 0.006f;
|
||||
static float gFlingFriction = 0.002f;
|
||||
|
||||
/**
|
||||
* Threshold for velocity beneath which we turn off any acceleration we had
|
||||
|
|
|
@ -84,7 +84,7 @@ ThreadStackHelper::GetStack(Stack& aStack)
|
|||
{
|
||||
// Always run PrepareStackBuffer first to clear aStack
|
||||
if (!PrepareStackBuffer(aStack)) {
|
||||
MOZ_ASSERT(false);
|
||||
// Skip and return empty aStack
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,13 +149,23 @@ ThreadStackHelper::SigAction(int aSignal, siginfo_t* aInfo, void* aContext)
|
|||
|
||||
bool
|
||||
ThreadStackHelper::PrepareStackBuffer(Stack& aStack) {
|
||||
// Return false to skip getting the stack and return an empty stack
|
||||
aStack.clear();
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
/* Normally, provided the profiler is enabled, it would be an error if we
|
||||
don't have a pseudostack here (the thread probably forgot to call
|
||||
profiler_register_thread). However, on B2G, profiling secondary threads
|
||||
may be disabled despite profiler being enabled. This is by-design and
|
||||
is not an error. */
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (!mPseudoStack) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
MOZ_ASSERT(mPseudoStack);
|
||||
mStackBuffer.clear();
|
||||
return mStackBuffer.reserve(mMaxStackSize);
|
||||
MOZ_ALWAYS_TRUE(mStackBuffer.reserve(mMaxStackSize));
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче