Proposal: ResourceStats API for NetworkStats API and PowerStats API integration

119 views
Skip to first unread message

Borting Chen

unread,
Dec 20, 2013, 4:44:27 AM12/20/13
to dev-w...@lists.mozilla.org
Hi all:

As we have discussed in [1], we need a new API to integrate the PowerStats API [2] with the existing NetworkStats API [3]. After an internal discussion at Taipei office (with Gene Lian, Vincent Chang, Ken Chang, and John Shih), we want to propose a 'ResourceStats API' [4] to merge these two stats APIs into one.

The proposed ResourceStats API supports two primary functionality:
(1) resource statistics (provide resource usage information, such as power consumption)
(2) resource control (notify user when resource usage exceeds a defined threshold).

The ResourceStats API categorizes a system into several types of resource. Currently, we plan to support statistics and control for two types of resource: 'network' & 'power', which focus on network usage and power consumption, respectively.

The following is our proposal, note that:
(1) getStats() & clearStats() are designed to support the query & delete for statistics. The |resourceStatsOptions| argument provides the detail of the resource we want to obtain/delete, such as the Wi-Fi usage of the browser App.
(2) addAlarm(), getAlarm(), and removeAlarm() are designed for resource control. These functions are retrieved from existing NetworkStats API directly. [5]

== Proposal Start ==
dictionary NetworkStatsOptions
{
/**
* |type| is network type, 0 for Wi-Fi and 1 for Mobile.
*
* |id| is '0' for Wi-Fi, or the iccid for mobile (SIM).
*
* |manifestURL| is used to retrieve network usage of a specified application.
* If null, system network usage is returned.
*/
unsigned long type;
DOMString id;
DOMString manifestURL;
};

dictionary PowerStatsOptions
{
/**
* |component| specifies which component's power consumption will be returned.
* If null, total power consumption is returned.
*
* |manifestURL| is used to retrieve power consumption of a specified
* application. If null, all applications' power consumption is returned.
*/
DOMString component;
DOMString manifestURL;
};

dictionary ResourceStatsAlarmOptions
{
unsigned long long startTime; // time in milliseconds since Epoch
any data;
};

[JSImplementation="@mozilla.org/resourceStatsAlarm;1", Pref="dom.mozResourceStats.enabled"]
interface MozResourceStatsAlarm
{
readonly attribute unsigned long alarmId;
readonly attribute DOMString resourceType;
readonly attribute any resourceStatsOptions;
readonly attribute any threshold;
readonly attribute any data;
};

[JSImplementation="@mozilla.org/resourceStatsManager;1", NavigatorProperty="mozResourceStats", Pref="dom.mozResourceStats.enabled"]
interface ResourceStatsManager
{
const unsigned long WIFI = 0;
const unsigned long MOBILE = 1;

/**
* Query resource statistics.
*
* |resourceType| specifies the type of resource statistics we want to
* obtain. This value should be in the return of resourceTypes attribute.
*
* |start| and |end| specifies the interest time range, both included.
*
* |resourceStatsOptions| specifies the detial of resource in which we are
* are interested. Its value depends on which |resourceType| is specified.
* For 'network' resource, the options should be a NetworkStatsOptions object.
* For 'power' resource, the options should be a PowerStatsOptions object.
*
* If success, the |result| field keeps statistics. For 'network' resource
* the |result| is an array of NetworkStats object. For 'power' resource
* the result is an array of PowerStats object.
*/
Promise getStats(DOMString resourceType,
unsigned long long start,
unsigned long long end,
optional any resourceStatsOptions);

/**
* Clear resource statistics stored in database.
*
* |resourceType| specifies the type of resource statistics we want to clear.
*
* If |resourceStatsOptions| is provided, then only the statistics associated
* to that |resourceStatsOptions| is deleted. Otherwise, all statistics of
* the specified |resourceType| is deleted.
*/
Promise clearStats(DOMString resourceType,
optional any resourceStatsOptions);

/**
* Install an alarm to monitor resource usage.
*
* |resourceType| specifies the type of resource we want to monitor.
*
* The |threshold| is an object specified the limit of resource usage. When
* resource usage reaches the threshold, a "resourceStats-alarm" system
* message is sent to the application.
*
* |resourceStatsOptions| specifies the detial of resource in which we are
* are interested.
*
* |alarmOptions| is a ResourceStatsAlarmOptions object.
*
* If success, the |result| field keeps the alarm Id.
*/
Promise addAlarm(DOMString resourceType,
any threshold,
optional any resourceStatsOptions,
optional ResourceStatsAlarmOptions alarmOptions);

/**
* Obtain alarms set for the specified resource type.
*
* |resourceType| specifies the type of resource.
*
* If |resourceStatsOptions| is provided, then only the alarms monitoring
* that resource are returned. Otherwise, all alarms set for the specified
* |resourceType| is returned.
*
* If success, the |result| is an array of ResourceStatsAlarm.
*/
Promise getAlarms(DOMString resourceType, optional any resourceStatsOptions);

/**
* Remove all alarms.
*
* If an |alarmId| is provided, then only that alarm is removed.
*/
Promise removeAlarm(optional long alarmId);

/**
* Return available resource stats options stored in database.
*
* If success, the |result| is an array of resourceStatsOptions.
*/
Promise getResourceStatsOptions(DOMString resourceType);

/**
* Return the name of supported resource statistics types.
* Currently, we support 'network' and 'power'.
*/
readonly attribute any resourceTypes; // array of DOMString

/**
* Time in milliseconds between statistics stored in database.
*/
readonly attribute unsigned long long sampleRate;

/**
* Time in milliseconds recorded by the API until present time. All
* statistics older than maxStorageAge from now are deleted.
*/
readonly attribute unsigned long long maxStorageAge;
};
== Proposal End ==

We also filed a bug (Bug 951976) on Bugzilla [4] to discuss this API. Please feel free to provide any feedback you think is valuable on this thread or Bugzilla.

Thanks for your time and cheers!

--borting


[1] https://bugzilla.mozilla.org/show_bug.cgi?id=854200#c76
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=854200
[3] https://bugzilla.mozilla.org/show_bug.cgi?id=858003
[4] https://bugzilla.mozilla.org/show_bug.cgi?id=951976
[5] https://bugzilla.mozilla.org/show_bug.cgi?id=858005

--
Borting Chen
Intern of Mozilla Taiwan

JOSE MANUEL CANTERA FONSECA

unread,
Dec 20, 2013, 7:40:29 AM12/20/13
to Borting Chen, dev-w...@lists.mozilla.org
El 20/12/13 10:44, "Borting Chen" <boc...@mozilla.com> escribió:

>Hi all:
>
>As we have discussed in [1], we need a new API to integrate the
>PowerStats API [2] with the existing NetworkStats
As these two dictionaries are quite similar it could be a good idea to
have only one dictionary for the two kind of resources.
>_______________________________________________
>dev-webapi mailing list
>dev-w...@lists.mozilla.org
>https://lists.mozilla.org/listinfo/dev-webapi
>



________________________________

Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo.
This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at:
http://www.tid.es/ES/PAGINAS/disclaimer.aspx

Doug Turner

unread,
Dec 20, 2013, 11:51:16 AM12/20/13
to Borting Chen, dev-w...@lists.mozilla.org
On APIs that return urls and require you to go fetch data -- Why did you
take this approach? Where/How is that content result going to be defined?

Borting Chen wrote:
> Hi all:
>
> As we have discussed in [1], we need a new API to integrate the PowerStats API [2] with the existing NetworkStats API [3]. After an internal discussion at Taipei office (with Gene Lian, Vincent Chang, Ken Chang, and John Shih), we want to propose a 'ResourceStats API' [4] to merge these two stats APIs into one.
>
> The proposed ResourceStats API supports two primary functionality:
> (1) resource statistics (provide resource usage information, such as power consumption)
> (2) resource control (notify user when resource usage exceeds a defined threshold).
>
> The ResourceStats API categorizes a system into several types of resource. Currently, we plan to support statistics and control for two types of resource: 'network'& 'power', which focus on network usage and power consumption, respectively.
>
> The following is our proposal, note that:
> (1) getStats()& clearStats() are designed to support the query& delete for statistics. The |resourceStatsOptions| argument provides the detail of the resource we want to obtain/delete, such as the Wi-Fi usage of the browser App.

Doug Turner

unread,
Dec 20, 2013, 11:51:16 AM12/20/13
to Borting Chen, dev-w...@lists.mozilla.org
On APIs that return urls and require you to go fetch data -- Why did you
take this approach? Where/How is that content result going to be defined?

Borting Chen wrote:
> Hi all:
>
> As we have discussed in [1], we need a new API to integrate the PowerStats API [2] with the existing NetworkStats API [3]. After an internal discussion at Taipei office (with Gene Lian, Vincent Chang, Ken Chang, and John Shih), we want to propose a 'ResourceStats API' [4] to merge these two stats APIs into one.
>
> The proposed ResourceStats API supports two primary functionality:
> (1) resource statistics (provide resource usage information, such as power consumption)
> (2) resource control (notify user when resource usage exceeds a defined threshold).
>
> The ResourceStats API categorizes a system into several types of resource. Currently, we plan to support statistics and control for two types of resource: 'network'& 'power', which focus on network usage and power consumption, respectively.
>
> The following is our proposal, note that:
> (1) getStats()& clearStats() are designed to support the query& delete for statistics. The |resourceStatsOptions| argument provides the detail of the resource we want to obtain/delete, such as the Wi-Fi usage of the browser App.

Doug Turner

unread,
Dec 20, 2013, 11:51:27 AM12/20/13
to Borting Chen
On APIs that return urls and require you to go fetch data -- Why did you
take this approach? Where/How is that content result going to be defined?

Borting Chen wrote:
> Hi all:
>
> As we have discussed in [1], we need a new API to integrate the
> PowerStats API [2] with the existing NetworkStats API [3]. After an
> internal discussion at Taipei office (with Gene Lian, Vincent Chang,
> Ken Chang, and John Shih), we want to propose a 'ResourceStats API'
> [4] to merge these two stats APIs into one.
>
> The proposed ResourceStats API supports two primary functionality:
> (1) resource statistics (provide resource usage information, such as
> power consumption)
> (2) resource control (notify user when resource usage exceeds a
> defined threshold).
>
> The ResourceStats API categorizes a system into several types of
> resource. Currently, we plan to support statistics and control for two
> types of resource: 'network'& 'power', which focus on network usage
> and power consumption, respectively.
>
> The following is our proposal, note that:
> (1) getStats()& clearStats() are designed to support the query& delete

Ehsan Akhgari

unread,
Dec 20, 2013, 12:05:49 PM12/20/13
to JOSE MANUEL CANTERA FONSECA, Borting Chen, dev-w...@lists.mozilla.org
On 12/20/2013, 7:40 AM, JOSE MANUEL CANTERA FONSECA wrote:
> El 20/12/13 10:44, "Borting Chen" <boc...@mozilla.com> escribi�:
>
>> Hi all:
>>
>> As we have discussed in [1], we need a new API to integrate the
>> PowerStats API [2] with the existing NetworkStats
> As these two dictionaries are quite similar it could be a good idea to
> have only one dictionary for the two kind of resources.

Yeah, perhaps something like:

enum ResourceType { "network", "power" };
enum PowerComponent { "CPU", /* other components go here */ };
dictionary ResourceOptions {
ResourceType type;
(PowerComponent or DOMString) component; // for network, "wifi" means
wifi, anything else is an iccid.
DOMString manifestURL;
};

Also, is ResourceStatsAlarmOptions.data a generic user data argument or
is it intended to be used for something else?

Thanks!
Ehsan

Borting Chen

unread,
Dec 20, 2013, 6:30:33 PM12/20/13
to Doug Turner, mozilla-d...@lists.mozilla.org
Hi Doug:

Sorry, I don't understand your question. which APIs did you mean?

Thanks,

-- borting


--
Borting Chen
Intern of Mozilla Taiwan


----- Original Message -----
From: "Doug Turner" <do...@mozilla.com>
To: "Borting Chen" <boc...@mozilla.com>, mozilla-d...@lists.mozilla.org
Sent: Saturday, December 21, 2013 12:51:27 AM
Subject: Re: Proposal: ResourceStats API for NetworkStats API and PowerStats API integration

On APIs that return urls and require you to go fetch data -- Why did you
take this approach? Where/How is that content result going to be defined?

Borting Chen wrote:
> Hi all:
>
> As we have discussed in [1], we need a new API to integrate the
> PowerStats API [2] with the existing NetworkStats API [3]. After an
> internal discussion at Taipei office (with Gene Lian, Vincent Chang,
> Ken Chang, and John Shih), we want to propose a 'ResourceStats API'
> [4] to merge these two stats APIs into one.
>
> The proposed ResourceStats API supports two primary functionality:
> (1) resource statistics (provide resource usage information, such as
> power consumption)
> (2) resource control (notify user when resource usage exceeds a
> defined threshold).
>
> The ResourceStats API categorizes a system into several types of
> resource. Currently, we plan to support statistics and control for two
> types of resource: 'network'& 'power', which focus on network usage
> and power consumption, respectively.
>
> The following is our proposal, note that:
> (1) getStats()& clearStats() are designed to support the query& delete

Borting Chen

unread,
Dec 20, 2013, 7:24:36 PM12/20/13
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
Hi Ehsan and Jose:
> As these two dictionaries are quite similar it could be a good idea to
> have only one dictionary for the two kind of resources.

enum ResourceType { "network", "power" };
enum PowerComponent { "CPU", /* other components go here */ };
dictionary ResourceOptions {
ResourceType type;
(PowerComponent or DOMString) component; // for network, "wifi" means
wifi, anything else is an iccid.
DOMString manifestURL;
};

Yeah, enum is a good idea, thanks.

I think provide a single ResourceOptions dictionary would be more generic, but there are some reasons we separate it as two:
(1) As we are going to add "serviceType" in the NetworkStatsOptions to query system-only network usage (plz refer Bug 992926 [1]), I am afraid the additional argument might confuse a user who want to obtain power stats if we provide ResourceOptions dictionary only.
(2) If we are going to support another types of resource stats (such as "memory") which requires different options, it might enlarge the ResourceOptions dictionary. So, I would like to provide each resource type a specific dictionary for option settings.

Also, is ResourceStatsAlarmOptions.data a generic user data argument or
is it intended to be used for something else?

Yes, the ResourceStatsAlarmOptions.data is a generic user data argument.

Thanks,

-- borting

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=922926

Salvador de la Puente González

unread,
Dec 22, 2013, 3:49:11 PM12/22/13
to Borting Chen, dev-w...@lists.mozilla.org
Hello people

First of all, thank you John for adding Alberto and me to this IDL
proposal. I'm very happy about seeing NetworkStats API 2.0 as the base
for this new ResourceStats API. :)

Second, sorry for the delay. I was eager for contribute to this but my
workload has been huge until now. I'm on holidays but I would want to
provide some feedback before disconnecting completely.

Third my comments about the API inline and some conclusions and
alternative designs at the end:

On 20/12/13 10:44, Borting Chen wrote:

I need some clarification about the 'resource model'. As I understand so
far, it is this way:

The device is seen as a set of `resources` consumed through a set of
`components` by the execution of `applications`. I mean, `system app`
could be using `network` for FOTA through the `mobile component`.
Another example: `contacts app` could be spending `power` through the
use of `CPU`.

I assume there are more components compounding the power resource. Can
you cite some of them?
Am I correct, Am I missing something?


On 20/12/13 10:44, Borting Chen wrote:
> Hi all:
>
> As we have discussed in [1], we need a new API to integrate the PowerStats API [2] with the existing NetworkStats API [3]. After an internal discussion at Taipei office (with Gene Lian, Vincent Chang, Ken Chang, and John Shih), we want to propose a 'ResourceStats API' [4] to merge these two stats APIs into one.
>
> The proposed ResourceStats API supports two primary functionality:
> (1) resource statistics (provide resource usage information, such as power consumption)
> (2) resource control (notify user when resource usage exceeds a defined threshold).
>
> The ResourceStats API categorizes a system into several types of resource. Currently, we plan to support statistics and control for two types of resource: 'network' & 'power', which focus on network usage and power consumption, respectively.
>
> The following is our proposal, note that:
> (1) getStats() & clearStats() are designed to support the query & delete for statistics. The |resourceStatsOptions| argument provides the detail of the resource we want to obtain/delete, such as the Wi-Fi usage of the browser App.
> (2) addAlarm(), getAlarm(), and removeAlarm() are designed for resource control. These functions are retrieved from existing NetworkStats API directly. [5]
>
> == Proposal Start ==
> dictionary NetworkStatsOptions
> {
> /**
> * |type| is network type, 0 for Wi-Fi and 1 for Mobile.
> *
> * |id| is '0' for Wi-Fi, or the iccid for mobile (SIM).
> *
> * |manifestURL| is used to retrieve network usage of a specified application.
> * If null, system network usage is returned.
> */
> unsigned long type;
> DOMString id;
> DOMString manifestURL;
> };
>
> dictionary PowerStatsOptions
> {
> /**
> * |component| specifies which component's power consumption will be returned.
> * If null, total power consumption is returned.
> *
> * |manifestURL| is used to retrieve power consumption of a specified
> * application. If null, all applications' power consumption is returned.
> */
> DOMString component;
> DOMString manifestURL;
> };
As José Manuel already noticed, the two dictionaries are so similar that
they could be only one. If we want to equal both of them we could
provide a DOMString to refer the Wi-Fi/mobile interfaces and SIM
combinations instead of type and id. I'm thinking in some like:
'wifi:0' and 'mobile:<iccid>'.

This way, it's easy to parse and help to unify both dictionaries and
same schema can be easy applied to other multiplexed resources as CPU
for multi-core devices.
>
> dictionary ResourceStatsAlarmOptions
> {
> unsigned long long startTime; // time in milliseconds since Epoch
> any data;
> };
Just to clarify, `startTime` is a convenient way to place an offset from
which perform the measurements (i.e: count power consumption of CPU
since now) and `data` play the same role as in the Alarm API: to be
reflected in the alarm object when the alarm is triggered.
>
> [JSImplementation="@mozilla.org/resourceStatsAlarm;1", Pref="dom.mozResourceStats.enabled"]
> interface MozResourceStatsAlarm
> {
> readonly attribute unsigned long alarmId;
> readonly attribute DOMString resourceType;
> readonly attribute any resourceStatsOptions;
> readonly attribute any threshold;
> readonly attribute any data;
> };
>
> [JSImplementation="@mozilla.org/resourceStatsManager;1", NavigatorProperty="mozResourceStats", Pref="dom.mozResourceStats.enabled"]
> interface ResourceStatsManager
> {
> const unsigned long WIFI = 0;
> const unsigned long MOBILE = 1;
Note we have these constants here completely unrelated to power resource. To
remove this coupling, read my alternative proposal at the end of this
document.
>
> /**
> * Query resource statistics.
> *
> * |resourceType| specifies the type of resource statistics we want to
> * obtain. This value should be in the return of resourceTypes attribute.
> *
> * |start| and |end| specifies the interest time range, both included.
> *
> * |resourceStatsOptions| specifies the detial of resource in which we are
> * are interested. Its value depends on which |resourceType| is specified.
> * For 'network' resource, the options should be a NetworkStatsOptions object.
> * For 'power' resource, the options should be a PowerStatsOptions object.
> *
> * If success, the |result| field keeps statistics. For 'network' resource
> * the |result| is an array of NetworkStats object. For 'power' resource
> * the result is an array of PowerStats object.
> */
> Promise getStats(DOMString resourceType,
> unsigned long long start,
> unsigned long long end,
> optional any resourceStatsOptions);
It could be very convenient to allow `null` or `undefined` for `start`
and `end` to retrieve statistics from the beginning of measurements or
until the end of them.
>
> /**
> * Clear resource statistics stored in database.
> *
> * |resourceType| specifies the type of resource statistics we want to clear.
> *
> * If |resourceStatsOptions| is provided, then only the statistics associated
> * to that |resourceStatsOptions| is deleted. Otherwise, all statistics of
> * the specified |resourceType| is deleted.
> */
> Promise clearStats(DOMString resourceType,
> optional any resourceStatsOptions);
IMHO, it is safer to provide something like `clearAllStats()` if we
really want to clear all statistics. These kind of so much homogeneous
API lead the developer to perform a lot of automatisms which can result
in an unintended undefined object. If this is passed to
`clearAllStats()` the result could be fatale. Furthermore, this forces
you to test the second argument before using this method safely
introducing a lot of noisy `if` statements everywhere.
To be consistent with my last comment, I recommend the same approach
here: to have a `removeAllAlarms()`.
>
> /**
> * Return available resource stats options stored in database.
> *
> * If success, the |result| is an array of resourceStatsOptions.
> */
> Promise getResourceStatsOptions(DOMString resourceType);
I don't understand this very well, could you explain me, please?
>
> /**
> * Return the name of supported resource statistics types.
> * Currently, we support 'network' and 'power'.
> */
> readonly attribute any resourceTypes; // array of DOMString
>
> /**
> * Time in milliseconds between statistics stored in database.
> */
> readonly attribute unsigned long long sampleRate;
Maybe we should transform this into a function or a map as we could be
measuring each resource at different rates.
>
> /**
> * Time in milliseconds recorded by the API until present time. All
> * statistics older than maxStorageAge from now are deleted.
> */
> readonly attribute unsigned long long maxStorageAge;
> };
>
Same here.

So, now, my alternative approach is to have to have a Manager Factory
and allow the developer to instantiate a specific Manager for a specific
resource. I.e.:

var networkStatsManager = new ResourceStatsManager('network');
var powerStatsManager = new ResourceStatsManager('power');
var resources = ResourceStatsManager.getResources();

We should try to keep the API as homogeneous as possible but this allow
us to provide very specific methods for some of them if needed or
particular constants like WIFI or MOBILE applying only where they are
required.

What do you think?

Thank you guys!

Ehsan Akhgari

unread,
Jan 2, 2014, 4:54:10 PM1/2/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
On 12/20/2013, 7:24 PM, Borting Chen wrote:
> Hi Ehsan and Jose:
>> As these two dictionaries are quite similar it could be a good idea to
>> have only one dictionary for the two kind of resources.
>
> enum ResourceType { "network", "power" };
> enum PowerComponent { "CPU", /* other components go here */ };
> dictionary ResourceOptions {
> ResourceType type;
> (PowerComponent or DOMString) component; // for network, "wifi" means
> wifi, anything else is an iccid.
> DOMString manifestURL;
> };
>
> Yeah, enum is a good idea, thanks.
>
> I think provide a single ResourceOptions dictionary would be more generic, but there are some reasons we separate it as two:
> (1) As we are going to add "serviceType" in the NetworkStatsOptions to query system-only network usage (plz refer Bug 992926 [1]), I am afraid the additional argument might confuse a user who want to obtain power stats if we provide ResourceOptions dictionary only.

Hmm, why would we need to change the API for that purpose? Can't you
just pass null for manifestURL to get the system network/power usage?

> (2) If we are going to support another types of resource stats (such as "memory") which requires different options, it might enlarge the ResourceOptions dictionary. So, I would like to provide each resource type a specific dictionary for option settings.

Do you expect the memory stats API to require a lot of additional
dictionary members? (I don't.) If not, let's not worry about that case
for now. Using only a single dictionary here will hopefully make people
think twice before adding members specific to only one measurement to
this dictionary.

Cheers,
Ehsan

Salvador de la Puente González

unread,
Jan 3, 2014, 11:08:18 AM1/3/14
to Ehsan Akhgari, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
Hello guys
>> (2) If we are going to support another types of resource stats (such
>> as "memory") which requires different options, it might enlarge the
>> ResourceOptions dictionary. So, I would like to provide each resource
>> type a specific dictionary for option settings.
>
> Do you expect the memory stats API to require a lot of additional
> dictionary members? (I don't.) If not, let's not worry about that
> case for now. Using only a single dictionary here will hopefully make
> people think twice before adding members specific to only one
> measurement to this dictionary.
Please, consider the option I gave you about having a Statistics factory
and specialize for each service because it could solve these problems.

Cheers.
>
> Cheers,
> Ehsan
>
> _______________________________________________
> dev-webapi mailing list
> dev-w...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-webapi
>
>


Ehsan Akhgari

unread,
Jan 3, 2014, 11:34:13 AM1/3/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
On 1/3/2014, 11:08 AM, Salvador de la Puente Gonz�lez wrote:
> Hello guys
>>> (2) If we are going to support another types of resource stats (such
>>> as "memory") which requires different options, it might enlarge the
>>> ResourceOptions dictionary. So, I would like to provide each resource
>>> type a specific dictionary for option settings.
>>
>> Do you expect the memory stats API to require a lot of additional
>> dictionary members? (I don't.) If not, let's not worry about that
>> case for now. Using only a single dictionary here will hopefully make
>> people think twice before adding members specific to only one
>> measurement to this dictionary.
> Please, consider the option I gave you about having a Statistics factory
> and specialize for each service because it could solve these problems.

I assume you mean this proposal?

var networkStatsManager = new ResourceStatsManager('network');
var powerStatsManager = new ResourceStatsManager('power');
var resources = ResourceStatsManager.getResources();


I was waiting for Borting to reply to your post first, but as far as I
can understand, ResourceStatsManager would still accept the same
arguments and return the same type here for all resource types, so it
shold be no better or worse in terms of being future proof for other
resource types, unless I'm missing something.

Cheers,
Ehsan

Borting Chen

unread,
Jan 3, 2014, 12:01:59 PM1/3/14
to Salvador de la Puente González, dev-w...@lists.mozilla.org
> I need some clarification about the 'resource model'. As I understand so
> far, it is this way:
> The device is seen as a set of `resources` consumed through a set of
> `components` by the execution of `applications`. I mean, `system app`
> could be using `network` for FOTA through the `mobile component`.
> Another example: `contacts app` could be spending `power` through the
> use of `CPU`.
> I assume there are more components compounding the power resource. Can
> you cite some of them?
> Am I correct, Am I missing something?

Yes, you are right.
Here is the list of components which we are interested:
- CPU
- Screen
- WiFi
- Mobile
- GPS
- Bluetooth
- Audio/Video

> As José Manuel already noticed, the two dictionaries are so similar that
> they could be only one. If we want to equal both of them we could
> provide a DOMString to refer the Wi-Fi/mobile interfaces and SIM
> combinations instead of type and id. I'm thinking in some like:
> 'wifi:0' and 'mobile:<iccid>'.

This is a good idea. Thanks for the suggestion.

> > Promise getStats(DOMString resourceType,
> > unsigned long long start,
> > unsigned long long end,
> > optional any resourceStatsOptions);
> It could be very convenient to allow `null` or `undefined` for `start`
> and `end` to retrieve statistics from the beginning of measurements or
> until the end of them.

okay, btw, is that possible to use 0 to indicate the begin and end of measurements?

> > Promise clearStats(DOMString resourceType,
> > optional any resourceStatsOptions);
> IMHO, it is safer to provide something like `clearAllStats()` if we
> really want to clear all statistics. These kind of so much homogeneous
> API lead the developer to perform a lot of automatisms which can result
> in an unintended undefined object. If this is passed to
> `clearAllStats()` the result could be fatale. Furthermore, this forces
> you to test the second argument before using this method safely
> introducing a lot of noisy `if` statements everywhere.

So, you meant that it would be better to provide the following APIs:

Promise clearStats(DOMString resourceType, optional any resourceStatsOptions);
Promise clearAllStats(DOMString resourceType);

Am I right?

> > Promise getResourceStatsOptions(DOMString resourceType);
> I don't understand this very well, could you explain me, please?

Oh, this API is created to support getAvailableNetworks() of NetworkStatsManager.

For network stats, it would return available networks stored in DB.

For power stats, it would return the component supporting power metering.

> > readonly attribute unsigned long long sampleRate;
> Maybe we should transform this into a function or a map as we could be
> measuring each resource at different rates.

I think it would become much easier for implementation if we can measure resources at different rates.
But, because calculating the power consumption of wifi and mobile is based on network stats results (such as Tx/RX bytes),
it would be more efficient if we can save the network and the power stats to DB at the same time.

> So, now, my alternative approach is to have to have a Manager Factory
> and allow the developer to instantiate a specific Manager for a specific
> resource. I.e.:
>
> var networkStatsManager = new ResourceStatsManager('network');
> var powerStatsManager = new ResourceStatsManager('power');
> var resources = ResourceStatsManager.getResources();
>
> We should try to keep the API as homogeneous as possible but this allow
> us to provide very specific methods for some of them if needed or
> particular constants like WIFI or MOBILE applying only where they are
> required.

Thanks for the suggestion.
So, we can remove the |resourceType| parameter from all APIs, am I right?

Borting Chen

unread,
Jan 3, 2014, 12:13:20 PM1/3/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
> Hmm, why would we need to change the API for that purpose? Can't you
> just pass null for manifestURL to get the system network/power usage?

okay, I see.
btw, because we may need to support the query for different service type [1], could we define something like these for the |manifestURL| variable?
1. "app://..." represents an app's manifestURL
2. "sys://..." represents a system service type
3. null means get the total usage

Here are some example for querying system services:
"sys://FOTA" means query the usage for FOTA
"sys://Tethering" means query the usage for Tethering


> > (2) If we are going to support another types of resource stats (such as
> > "memory") which requires different options, it might enlarge the
> > ResourceOptions dictionary. So, I would like to provide each resource type
> > a specific dictionary for option settings.
>
> Do you expect the memory stats API to require a lot of additional
> dictionary members? (I don't.) If not, let's not worry about that case
> for now. Using only a single dictionary here will hopefully make people
> think twice before adding members specific to only one measurement to
> this dictionary.

Yak, you are right.
So I think the ResourceStatsOptions could be something like this:

dictionary ResourceStatsOptions {
/**
* For Power stats, |component| specifies which component's power consumption will be returned.
* If null, total power consumption is returned.
*
* For Network stats, |component| specifies the network interface. WiFi is repreented as "wifi:0"
* and mobile is represented as "mobile:<iccid>".
* If null, system network usage (wifi + mobile) is returned.
*/
DOMString component;

/**
* If |manifestURL| is "app://...", then the stats of an application is returned.
*
* If |manifestURL| is "sys://...", then the stats of a system service is returned.
*
* If |manifestURL| is null, then the total resource usage (app + system) is returned.
*/
DOMString manifestURL;
};

Does this look better?

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=922926

Cheers,

-- borting

Ehsan Akhgari

unread,
Jan 3, 2014, 12:49:12 PM1/3/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
On 1/3/2014, 12:13 PM, Borting Chen wrote:
>> Hmm, why would we need to change the API for that purpose? Can't you
>> just pass null for manifestURL to get the system network/power usage?
>
> okay, I see.
> btw, because we may need to support the query for different service type [1], could we define something like these for the |manifestURL| variable?
> 1. "app://..." represents an app's manifestURL
> 2. "sys://..." represents a system service type
> 3. null means get the total usage

I would rather avoid inventing a new URI scheme for this purpose.

> Here are some example for querying system services:
> "sys://FOTA" means query the usage for FOTA
> "sys://Tethering" means query the usage for Tethering

Alternatively, we can add components for these purposes, such as:

enum NetworkComponent { "wifi", "tethering", "OTA" };
dictionary ResourceOptions {
ResourceType type;
(PowerComponent or NetworkComponent or DOMString) component; // for
network, arbitrary strings represent an iccid
DOMString manifestURL;
};

That way, you'll pass {type: "network", component: "tethering"} to
measure the tethering usage, for example. If you pass a manifestURL,
you'll measure the tethering usage for that particular app. If you pass
a manifestURL to an app that is not the system app and specify
component:"OTA" then you'll get zero usage results as non-system apps do
not handle updates, for example.

Do you think this proposal addresses your needs here?

>>> (2) If we are going to support another types of resource stats (such as
>>> "memory") which requires different options, it might enlarge the
>>> ResourceOptions dictionary. So, I would like to provide each resource type
>>> a specific dictionary for option settings.
>>
>> Do you expect the memory stats API to require a lot of additional
>> dictionary members? (I don't.) If not, let's not worry about that case
>> for now. Using only a single dictionary here will hopefully make people
>> think twice before adding members specific to only one measurement to
>> this dictionary.
>
> Yak, you are right.
> So I think the ResourceStatsOptions could be something like this:
>
> dictionary ResourceStatsOptions {
> /**
> * For Power stats, |component| specifies which component's power consumption will be returned.
> * If null, total power consumption is returned.
> *
> * For Network stats, |component| specifies the network interface. WiFi is repreented as "wifi:0"
> * and mobile is represented as "mobile:<iccid>".
> * If null, system network usage (wifi + mobile) is returned.
> */
> DOMString component;
>

I still prefer to use a union of enums and DOMStrings for the iccid case.

> /**
> * If |manifestURL| is "app://...", then the stats of an application is returned.
> *
> * If |manifestURL| is "sys://...", then the stats of a system service is returned.
> *
> * If |manifestURL| is null, then the total resource usage (app + system) is returned.
> */
> DOMString manifestURL;
> };

See above.

Cheers,
Ehsan

Borting Chen

unread,
Jan 4, 2014, 12:44:02 PM1/4/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org
> I would rather avoid inventing a new URI scheme for this purpose.
>
> > Here are some example for querying system services:
> > "sys://FOTA" means query the usage for FOTA
> > "sys://Tethering" means query the usage for Tethering
>
> Alternatively, we can add components for these purposes, such as:
>
> enum NetworkComponent { "wifi", "tethering", "OTA" };
> dictionary ResourceOptions {
> ResourceType type;
> (PowerComponent or NetworkComponent or DOMString) component; // for
> network, arbitrary strings represent an iccid
> DOMString manifestURL;
> };
>
> That way, you'll pass {type: "network", component: "tethering"} to
> measure the tethering usage, for example. If you pass a manifestURL,
> you'll measure the tethering usage for that particular app. If you pass
> a manifestURL to an app that is not the system app and specify
> component:"OTA" then you'll get zero usage results as non-system apps do
> not handle updates, for example.
>
> Do you think this proposal addresses your needs here?

Thank you for the suggestion, but I think it is a little weird for me to use the same variable to represent "tethering" and "wifi".
In my opinion, the wifi is a component which "provides" network resources,
but tethering (or OTA) is a service which "consumes" network resources (as well as power resources).
So, I think it could be better if we can use separated variables to represent those have different characteristics.
Even more, tethering may transmit packets to Internet via different SIMs (on a multi-SIM phone).
So, providing a single "component" variable is not sufficient if we want to know how many packets that a SIM transmits for tethering.

Hence, my alternative proposal is something like this:

enum PowerComponent {"CPU", "Scrren", "WiFi", "Mobile", "Bluetooth", "GPS", ...};
enum NetworkComponent {"WiFi", ...};
enum SystemService {"OTA", "Tethering", ...}; // represent system services

dictionary ResourceOptions {
ResourceType type; // this could be removed if we decided to use the factory design suggested by Salvador
(PowerComponent or NetworkComponent or DOMString) component; // for network, arbitrary strings represent an iccid
(SystermService or DOMString) task; // arbitrary strings represent an manifestURL
};

Does this look much better?



Cheers,

-- borting

Gene Lian

unread,
Jan 8, 2014, 3:04:04 AM1/8/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Ehsan Akhgari
Please see the in-line response.

> Thank you for the suggestion, but I think it is a little weird for me to use
> the same variable to represent "tethering" and "wifi".

Agreed. In the long term, we can still query the network stats like:

"How much traffic passes through WiFi when doing the Tethering service?"

IMO, we shouldn't assume WiFi and Tethering are exclusive.

> enum PowerComponent {"CPU", "Scrren", "WiFi", "Mobile", "Bluetooth", "GPS",
> ...};
> enum NetworkComponent {"WiFi", ...};
> enum SystemService {"OTA", "Tethering", ...}; // represent system services
>
> dictionary ResourceOptions {
> ResourceType type; // this could be removed if we decided to use the
> factory design suggested by Salvador
> (PowerComponent or NetworkComponent or DOMString) component; // for
> network, arbitrary strings represent an iccid
> (SystermService or DOMString) task; // arbitrary strings represent an
> manifestURL

Here comes the similar issue. Querying the following combination is
still imaginable:

"How much traffic has App A used to do the Tethering?" and
"How much traffic has App B used to do the Tethering?"

which means it's inconsiderate to keep (SystemService or DOMString)
by one attribute.

Based on the previous idea, I'd suggest:

----------------------------------------
enum ResourceType {"power", "network"}
enum PowerComponent {"cpu", "screen", "wifi", "bluetooth", ...}
enum NetworkComponent {"wifi", ...};
enum SystemService {"unknown", "ota", "tethering", ...};

dictionary ResourceOptions {
ResourceType resourceType;
(PowerComponent or NetworkComponent or DOMString) component; [1]
SystemService systemService;
DOMString appManifestURL;
}

[1] DOMString is an ICC ID to specify SIM if we want to query
the mobile network.
----------------------------------------

Note that we make component/systemService/appManifestURL separate
so we're allowed to query the following user cases, which are
all common and reasonable:

Example 1: "How much traffic has App A used to do the Tethering
through the SIM-1's 3G?"

=> { resourceType: "network",
component: "89886920...",
systemService: "tethering",
appManifestURL: "app://A" }

Example 2: "How much traffic has App B used to do the OTA update
through the WiFi?"

=> { resourceType: "network",
component: "wifi",
systemService: "ota",
appManifestURL: "app://B" }

Example 3: "How much power has App C consumed to do the Bluetooth-
related connections?"

=> { resourceType: "power",
component: "bluetooth",
systemService: "unknown",
appManifestURL: "app://C" }


Hope it makes sense.

Cheers,
Gene

Borting Chen

unread,
Jan 8, 2014, 10:47:42 PM1/8/14
to Gene Lian, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Ehsan Akhgari
yah, I think this can meet all possible queries, thanks a lot.

BTW, a little question. Why you suggest an "unknown" type in systemService?
Does this mean "misc" system services?



Cheers,
Borting

Gene Lian

unread,
Jan 9, 2014, 4:50:27 AM1/9/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Ehsan Akhgari


----- Original Message -----
> From: "Borting Chen" <boc...@mozilla.com>
> To: "Gene Lian" <cl...@mozilla.com>
> Cc: "Ehsan Akhgari" <ehsan....@gmail.com>, "JOSE MANUEL CANTERA FONSECA" <jm...@tid.es>,
> dev-w...@lists.mozilla.org
> Sent: Thursday, January 9, 2014 11:47:42 AM
> Subject: Re: Proposal: ResourceStats API for NetworkStats API and PowerStats API integration
>
Please see the above-mentioned example 3: what if we don't care
about the system service? That is, we only want to query the power
consumption based on a certain app. So I define a "unknown" to
sum up all types of system service. TBH, I'm not sure if we really
need that. Maybe setting |systemService = null| is OK?

The same issue also occurs in |appManifestURL|. Since its a
DOMString, we can assign null to it to specify we want to query
the network traffic or power consumption for all apps.

Gene

Borting Chen

unread,
Jan 9, 2014, 9:28:20 AM1/9/14
to Gene Lian, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Ehsan Akhgari
----- Original Message -----
> From: "Gene Lian" <cl...@mozilla.com>
> To: "Borting Chen" <boc...@mozilla.com>
> Cc: "Ehsan Akhgari" <ehsan....@gmail.com>, "JOSE MANUEL CANTERA FONSECA" <jm...@tid.es>,
> dev-w...@lists.mozilla.org
> Sent: Thursday, January 9, 2014 5:50:27 PM
> Subject: Re: Proposal: ResourceStats API for NetworkStats API and PowerStats API integration
>
> Please see the above-mentioned example 3: what if we don't care
> about the system service? That is, we only want to query the power
> consumption based on a certain app. So I define a "unknown" to
> sum up all types of system service. TBH, I'm not sure if we really
> need that. Maybe setting |systemService = null| is OK?
>
> The same issue also occurs in |appManifestURL|. Since its a
> DOMString, we can assign null to it to specify we want to query
> the network traffic or power consumption for all apps.

I see. I think maybe we can left |systemService| as undefined when querying app's resource stats.
I'll check this during implementation. thanks for the suggestion.



Cheers,
Borting

Borting Chen

unread,
Jan 9, 2014, 10:12:34 AM1/9/14
to dev-w...@lists.mozilla.org, JOSE MANUEL CANTERA FONSECA, Ehsan Akhgari, Salvador de la Puente González, Gene Lian
Hi all:

Thank you guys for the great suggestions.
The revised ResourceStats API proposal is attached at the end of this mail.
Please left your comments if anyone has other thoughts.
Thanks a lot!

Modification note:
1. Use the factory design as suggested by Salvador. So, I separate the original interface to two:
-- ResourceStatsFactory is used to instantiate a ResourceStatsManger for a specific resource
-- ResourceStatsManager is used to query statistics and add resource alarms
2. Merge PowerStatsOptions and NetworkStatsOptions to one ResourceStatsOptions dictionary.
And, define several enums to represent resource types, components and system services.
3. Provide methods to get/clear "all" stats/alarms, which includes:
clearAllStats, getAllAlarms, and removeAllAlarm.

== Proposal Start ==

/**
* Supported resource statistics
*/
enum ResourceType {
"network",
"power"
};

/**
* List of components supporting power statistics
*/
enum PowerComponent {
"cpu",
"screen",
"mobile",
"wifi",
"bluetooth",
"gps"
};

/**
* List of components supporting network statistics.
*
* Note that a query for mobile network usage should use a DOMString to specify
* the ICC ID of the SIM card rather than specify a NetworkComponent enum type.
*/
enum NetworkComponent {
"wifi"
};

/**
* List of system services supporting resource statistics
*/
enum SystemService {
"ota",
"tethering"
};

typedef (PowerComponent or NetworkComponent or DOMString) ResourceStatsComponent;

dictionary ResourceStatsOptions
{
/**
* For power stats, |component| specifies which component's power consumption
* will be returned. If null, total power consumption is returned.
*
* For network stats, |component| specifies the network interface. DOMString
* is used to specify an ICC ID when querying the usage of mobile network.
* To query the stats of other network interfaces, a NetworkComponent enum
* type should be specified. If null, total network usage (Wi-Fi + mobile) is
* returned.
*/
ResourceStatsComponent component;

/**
* |manifestURL| specifies the manifestURL of an application.
* |systemService| specifies the system service.
*
* If both |systemService| and |manifestURL| are null, then a system-wide
* resource statistics is returned.
*
* If |manifestURL| is specified, then the resource statistics of the
* specified application is returned.
*
* If |systemService| is specified, then the resource statistics of the
* specified system service is returned.
*
* If both |systemService| and |manifestURL| are specified, then the return
* statistics indicates the resources that the system service consumed for
* the application.
*/
SystemService systemService;
DOMString manifestURL;
};

dictionary ResourceStatsAlarmOptions
{
/**
* |startTime| indicates the start time of counting the resource usage.
*
* |data| is used to reflect in the alarm object when the alarm is triggered.
*/
unsigned long long startTime; // time in milliseconds since Epoch
any data;
};


[JSImplementation="@mozilla.org/resourceStatsAlarm;1", Pref="dom.mozResourceStats.enabled"]
interface MozResourceStatsAlarm
{
readonly attribute unsigned long alarmId;
readonly attribute ResourceType type;
readonly attribute any statsOptions; // ResourceStatsOptions
readonly attribute any threshold;
readonly attribute any data;
};

[Constructor(ResourceType type), JSImplementation="@mozilla.org/resourceStatsManager;1", Pref="dom.mozResourceStats.enabled"]
interface ResourceStatsManager
{
/**
* Query resource statistics.
*
* |start| and |end| specifies the time range of interest, both included.
* If |start| is 0, retrieves the stats since measurements.
* If |end| is 0. retrieves the stats until the current time.
*
* |statsOptions| specifies the detial of statistics of interest.
*
* If success, the |result| field keeps statistics.
* For networkStatsManager, the |result| is an array of NetworkStats object.
* For powerStatsManager, the |result| is an array of PowerStats object.
*/
Promise getStats(unsigned long long start,
unsigned long long end,
optional ResourceStatsOptions statsOptions);

/**
* Clear resource statistics stored in database.
*
* If |statsOptions| is provided, then only the statistics associated to that
* |statsOptions| is deleted. Otherwise, all statistics of this resource type
* is deleted.
*/
Promise clearStats(optional ResourceStatsOptions statsOptions);

/**
* Clear all resource statistics stored in database.
*/
Promise clearAllStats();

/**
* Install an alarm to monitor resource usage.
*
* The |threshold| is an object specified the limit of resource usage. When
* resource usage reaches the threshold, a "resourceStats-alarm" system
* message is sent to the application.
*
* |statsOptions| specifies the detial of statistics of interest.
*
* |alarmOptions| is a ResourceStatsAlarmOptions object.
*
* If success, the |result| field keeps the alarm Id.
*/
Promise addAlarm(any threshold,
optional ResourceStatsOptions statsOptions,
optional ResourceStatsAlarmOptions alarmOptions);

/**
* Obtain alarms.
*
* If |statsOptions| is provided, then only the alarms monitoring that
* resource are returned. Otherwise, all alarms set for this resource type
* is returned.
*
* If success, the |result| is an array of ResourceStatsAlarm.
*/
Promise getAlarms(optional ResourceStatsOptions statsOptions);

/**
* Obtain all alarms.
*
* If success, the |result| is an array of ResourceStatsAlarm.
*/
Promise getAllAlarms();

/**
* Remove alarms.
*
* If an |alarmId| is provided, then only that alarm is removed.
*/
Promise removeAlarm(optional long alarmId);

/**
* Remove all alarms.
*/
Promise removeAllAlarm();

/**
* Return available resource stats options stored in database.
*
* If success, the |result| is an array of ResourceStatsOptions.
*/
Promise getResourceStatsOptions();

/**
* Return the type of resource statistics provided by this manager.
*/
readonly attribute DOMString resourceType;
};

[JSImplementation="@mozilla.org/resourceStatsFactory;1", NavigatorProperty="mozResourceStats", Pref="dom.mozResourceStats.enabled"]
interface ResourceStatsFactory
{
/**
* Get the resourceStatsManager for a resource type.
*
* |type| specifies the type of resourceStatsManager we want to obtain.
* This value should be one of those returned by resourceTypes attribute.
*
* If success, this method returns an object of ResourceStatsManager.
* Otherwise, null is resturned
*/
ResourceStatsManager getResourceStatsManager(ResourceType type);

/**
* Return the name of supported resource statistics types.
* Currently, 'network' and 'power' statistics are supported.
*/
readonly attribute any resourceTypes; // array of DOMString

/**
* Time in milliseconds between statistics stored in database.
*/
readonly attribute unsigned long long sampleRate;

/**
* Time in milliseconds recorded by the API until present time. All
* statistics older than maxStorageAge from now are deleted.
*/
readonly attribute unsigned long long maxStorageAge;
};

== Proposal End ==

Cheers,
Borting

Salvador de la Puente González

unread,
Jan 9, 2014, 11:27:29 AM1/9/14
to Borting Chen, dev-w...@lists.mozilla.org, JOSE MANUEL CANTERA FONSECA, Ehsan Akhgari, Gene Lian
Hello Borting, Gene, Ehsan and all!

First, happy new year!

Second: Borting, you got all at first glance! (I was on vacations so I
was not able to answer before).

Third, I want to review the abstraction before commenting in-line:

I like how the API is evolving because we can model the device as a set
of resources (first dimension) to be consumed through components (a
sub-dimension of the resource) by a set of application (second
dimension) optionally using some system's service (third dimension).
Examples provided by Gene illustrate this metaphor very well.

The only coupling is between resources and components. By using the
factory we specialize the manager for a specific resource. Now each
dimension (component, application and system's service) is not dependant
of other and has a slot in the ResourceOptions so we have a very
orthogonal, homogeneous and easy to automatize API. The absence of any
of these dimension should be treated as the addition of all it. So, no
manifestURL means "all the applications"; no systemService means "any
system's service"; no component means "all components together" and so on.

Before commenting the new API proposal I want to remark we have two
resources: network and wi-fi but I would want to introduce another one
(telephony: counting calls, SMS, MMS...). I will give you the details in
another thread ,)

And now:

On 09/01/14 16:12, Borting Chen wrote:
> Hi all:
>
> Thank you guys for the great suggestions.
> The revised ResourceStats API proposal is attached at the end of this mail.
> Please left your comments if anyone has other thoughts.
> Thanks a lot!
>
> Modification note:
> 1. Use the factory design as suggested by Salvador. So, I separate the original interface to two:
> -- ResourceStatsFactory is used to instantiate a ResourceStatsManger for a specific resource
> -- ResourceStatsManager is used to query statistics and add resource alarms
> 2. Merge PowerStatsOptions and NetworkStatsOptions to one ResourceStatsOptions dictionary.
> And, define several enums to represent resource types, components and system services.
> 3. Provide methods to get/clear "all" stats/alarms, which includes:
> clearAllStats, getAllAlarms, and removeAllAlarm.
>
> == Proposal Start ==
>
> /**
> * Supported resource statistics
> */
> enum ResourceType {
> "network",
> "power"
> };
As I said before, I will send a proposal for counting telephony statistics.
>
> /**
> * List of components supporting power statistics
> */
> enum PowerComponent {
> "cpu",
> "screen",
> "mobile",
> "wifi",
> "bluetooth",
> "gps"
> };
>
> /**
> * List of components supporting network statistics.
> *
> * Note that a query for mobile network usage should use a DOMString to specify
> * the ICC ID of the SIM card rather than specify a NetworkComponent enum type.
> */
> enum NetworkComponent {
> "wifi"
> };
I would rather prefer to pass the string with the
<component>:<subcomponent> format as it is more generic. Or a complex
object combination of enum (wifi / mobile) and identifier (interface
name / iccid). Note now, in our devices there are no more than one Wi-Fi
interface but this could change. Just my opinion, no more.
>
> /**
> * List of system services supporting resource statistics
> */
> enum SystemService {
> "ota",
> "tethering"
> };
>
> typedef (PowerComponent or NetworkComponent or DOMString) ResourceStatsComponent;
>
> dictionary ResourceStatsOptions
> {
> /**
> * For power stats, |component| specifies which component's power consumption
> * will be returned. If null, total power consumption is returned.
I encourage to be null or undefined (may this is implicit, just to
remark) in order to avoid including it in the JS object.
I was thinking 0 is perfectly valid for the 'beginning of time' but 0
makes no sense meaning "till the end of time". Furthermore, [0,0] is the
set containing only 0 so it is a valid value. For the sake of
correctness, if we could accept -inf and +inf it would be perfect and
they are valid values JS' numbers. If not, I suggest to specify
enumerates such as BEGIN and END or, in the less semantic option: null /
undefined.
> *
> * |statsOptions| specifies the detial of statistics of interest.
> *
> * If success, the |result| field keeps statistics.
> * For networkStatsManager, the |result| is an array of NetworkStats object.
> * For powerStatsManager, the |result| is an array of PowerStats object.
> */
> Promise getStats(unsigned long long start,
> unsigned long long end,
> optional ResourceStatsOptions statsOptions);
>
> /**
> * Clear resource statistics stored in database.
> *
> * If |statsOptions| is provided, then only the statistics associated to that
> * |statsOptions| is deleted. Otherwise, all statistics of this resource type
> * is deleted.
> */
> Promise clearStats(optional ResourceStatsOptions statsOptions);
As we are providing the next `clearAllStats()` method, the parameter is
no longer optional and the explanation about it, when omitted should be
moved to the next method.
>
> /**
> * Clear all resource statistics stored in database.
> */
> Promise clearAllStats();
This clear all stats of the resource type as I said in my previous comment.
Although I like this, note getting is not a critical functionality (we
can not destroy any information with a get operation) so, according to
the getAlarms() documentation, we are providing here a redundant way to
get all the alarms.
>
> /**
> * Remove alarms.
> *
> * If an |alarmId| is provided, then only that alarm is removed.
> */
> Promise removeAlarm(optional long alarmId);
Here we have the opposite example. As we are destroying things, we
should make mandatory the parameter and use the next method,
removeAllAlarms(), if we want to short-cut the method and destroy all
the alarms.
May be we can reduce verbosity by renaming this method to getManager().
>
> /**
> * Return the name of supported resource statistics types.
> * Currently, 'network' and 'power' statistics are supported.
> */
> readonly attribute any resourceTypes; // array of DOMString
>
> /**
> * Time in milliseconds between statistics stored in database.
> */
> readonly attribute unsigned long long sampleRate;
>
> /**
> * Time in milliseconds recorded by the API until present time. All
> * statistics older than maxStorageAge from now are deleted.
> */
> readonly attribute unsigned long long maxStorageAge;
> };
>
> == Proposal End ==
>
> Cheers,
> Borting
>
>
Hope it makes sense!
Thank you very much.

Ehsan Akhgari

unread,
Jan 9, 2014, 6:30:02 PM1/9/14
to Salvador de la Puente González, Borting Chen, dev-w...@lists.mozilla.org, JOSE MANUEL CANTERA FONSECA, Gene Lian
On 1/9/2014, 11:27 AM, Salvador de la Puente González wrote:
> Hello Borting, Gene, Ehsan and all!
>
> First, happy new year!

Same to you!

> Second: Borting, you got all at first glance! (I was on vacations so I
> was not able to answer before).
>
> Third, I want to review the abstraction before commenting in-line:
>
> I like how the API is evolving because we can model the device as a set
> of resources (first dimension) to be consumed through components (a
> sub-dimension of the resource) by a set of application (second
> dimension) optionally using some system's service (third dimension).
> Examples provided by Gene illustrate this metaphor very well.

Yes, agreed.

> The only coupling is between resources and components. By using the
> factory we specialize the manager for a specific resource. Now each
> dimension (component, application and system's service) is not dependant
> of other and has a slot in the ResourceOptions so we have a very
> orthogonal, homogeneous and easy to automatize API. The absence of any
> of these dimension should be treated as the addition of all it. So, no
> manifestURL means "all the applications"; no systemService means "any
> system's service"; no component means "all components together" and so on.
>
> Before commenting the new API proposal I want to remark we have two
> resources: network and wi-fi but I would want to introduce another one
> (telephony: counting calls, SMS, MMS...). I will give you the details in
> another thread ,)

That would be interesting!

> And now:
>
> On 09/01/14 16:12, Borting Chen wrote:
>> Hi all:
>>
>> Thank you guys for the great suggestions.
>> The revised ResourceStats API proposal is attached at the end of this
>> mail.
>> Please left your comments if anyone has other thoughts.
>> Thanks a lot!
>>
>> Modification note:
>> 1. Use the factory design as suggested by Salvador. So, I separate the
>> original interface to two:
>> -- ResourceStatsFactory is used to instantiate a
>> ResourceStatsManger for a specific resource
>> -- ResourceStatsManager is used to query statistics and add
>> resource alarms
>> 2. Merge PowerStatsOptions and NetworkStatsOptions to one
>> ResourceStatsOptions dictionary.
>> And, define several enums to represent resource types, components
>> and system services.
>> 3. Provide methods to get/clear "all" stats/alarms, which includes:
>> clearAllStats, getAllAlarms, and removeAllAlarm.

FWIW these modifications look good overall.
Yeah I think at this point, NetworkComponet doesn't make sense as a
separate enum any more, we might as well just use a DOMString instead.
I think a "<component>:<subcomponent>" identifier makes sense, or we can
choose to be more verbose and convert that into its own small
dictionary. Also, the multiple WiFi extensibility in the future is a
great point, so we should take that into account here as well.

>> /**
>> * List of system services supporting resource statistics
>> */
>> enum SystemService {
>> "ota",
>> "tethering"
>> };
>>
>> typedef (PowerComponent or NetworkComponent or DOMString)
>> ResourceStatsComponent;
>>
>> dictionary ResourceStatsOptions
>> {
>> /**
>> * For power stats, |component| specifies which component's power
>> consumption
>> * will be returned. If null, total power consumption is returned.
> I encourage to be null or undefined (may this is implicit, just to
> remark) in order to avoid including it in the JS object.

We should probably make this default to null, and take the null value or
not specifying at all to mean "all". Similarly for other cases. Of
course, that means that the type should be nullable too.
I think we can do better:

Promise getStats(optional unsigned long long start,
optional unsigned long long end,
optional ResourceStatsOptions statsOptions);

That should let us drop |end| when we want current time, and drop both
start and end when we want the full range. Does that make sense?

>> *
>> * |statsOptions| specifies the detial of statistics of interest.
>> *
>> * If success, the |result| field keeps statistics.
>> * For networkStatsManager, the |result| is an array of
>> NetworkStats object.
>> * For powerStatsManager, the |result| is an array of PowerStats
>> object.
>> */
>> Promise getStats(unsigned long long start,
>> unsigned long long end,
>> optional ResourceStatsOptions statsOptions);
>>
>> /**
>> * Clear resource statistics stored in database.
>> *
>> * If |statsOptions| is provided, then only the statistics
>> associated to that
>> * |statsOptions| is deleted. Otherwise, all statistics of this
>> resource type
>> * is deleted.
>> */
>> Promise clearStats(optional ResourceStatsOptions statsOptions);

Is it OK that this doesn't accept a time range?

> As we are providing the next `clearAllStats()` method, the parameter is
> no longer optional and the explanation about it, when omitted should be
> moved to the next method.

Wouldn't it be better if we just get rid of clearAllStats and make
mgr.clearStats() clear all stats? That would be consistent with the
semantics of getStats(), which is an advantage.

>> /**
>> * Clear all resource statistics stored in database.
>> */
>> Promise clearAllStats();
> This clear all stats of the resource type as I said in my previous comment.
>>
>> /**
>> * Install an alarm to monitor resource usage.
>> *
>> * The |threshold| is an object specified the limit of resource
>> usage. When
>> * resource usage reaches the threshold, a "resourceStats-alarm"
>> system
>> * message is sent to the application.
>> *
>> * |statsOptions| specifies the detial of statistics of interest.
>> *
>> * |alarmOptions| is a ResourceStatsAlarmOptions object.
>> *
>> * If success, the |result| field keeps the alarm Id.
>> */
>> Promise addAlarm(any threshold,
>> optional ResourceStatsOptions statsOptions,
>> optional ResourceStatsAlarmOptions alarmOptions);

Should we specify that the data argument to this API is cloned using the
Structured Clone algorithm? We can't accept any JS object here unless
I'm missing something.

>> /**
>> * Obtain alarms.
>> *
>> * If |statsOptions| is provided, then only the alarms monitoring that
>> * resource are returned. Otherwise, all alarms set for this
>> resource type
>> * is returned.
>> *
>> * If success, the |result| is an array of ResourceStatsAlarm.
>> */
>> Promise getAlarms(optional ResourceStatsOptions statsOptions);
>>
>> /**
>> * Obtain all alarms.
>> *
>> * If success, the |result| is an array of ResourceStatsAlarm.
>> */
>> Promise getAllAlarms();
> Although I like this, note getting is not a critical functionality (we
> can not destroy any information with a get operation) so, according to
> the getAlarms() documentation, we are providing here a redundant way to
> get all the alarms.

Yes, I agree. I think we should remove this function and just have
mgr.getAlarms() return all alarms.

>> /**
>> * Remove alarms.
>> *
>> * If an |alarmId| is provided, then only that alarm is removed.
>> */
>> Promise removeAlarm(optional long alarmId);
> Here we have the opposite example. As we are destroying things, we
> should make mandatory the parameter and use the next method,
> removeAllAlarms(), if we want to short-cut the method and destroy all
> the alarms.

Hmm, but if we did what we do for the rest of these similar concepts,
then we would benefit from the consistency of the usage of this API.
What do you think?

>> /**
>> * Remove all alarms.
>> */
>> Promise removeAllAlarm();
>>
>> /**
>> * Return available resource stats options stored in database.
>> *
>> * If success, the |result| is an array of ResourceStatsOptions.
>> */
>> Promise getResourceStatsOptions();

It's not exactly clear to me what this method is expected to return...

>> /**
>> * Return the type of resource statistics provided by this manager.
>> */
>> readonly attribute DOMString resourceType;
>> };
>>
>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
>> NavigatorProperty="mozResourceStats",
>> Pref="dom.mozResourceStats.enabled"]
>> interface ResourceStatsFactory

I'm not convinced that this is a good idea. We have
[Constructor(ResourceType)] on ResourceStatsManager which means that the
getResourceStatsManager function here is useless. We can have
resourceTypes, sampleRate and maxStorageAge be static read-only
attributes on ResourceStatsManager. That would mean that we can
eliminate ResourceStatsFactory completely, and not have this interface
tie to navigator at all, which would let you write code like:

var stats = new ResourceStatsManager("network");
stats.getStats(...).then(...);

>> {
>> /**
>> * Get the resourceStatsManager for a resource type.
>> *
>> * |type| specifies the type of resourceStatsManager we want to
>> obtain.
>> * This value should be one of those returned by resourceTypes
>> attribute.
>> *
>> * If success, this method returns an object of ResourceStatsManager.
>> * Otherwise, null is resturned
>> */
>> ResourceStatsManager getResourceStatsManager(ResourceType type);
> May be we can reduce verbosity by renaming this method to getManager().
>>
>> /**
>> * Return the name of supported resource statistics types.
>> * Currently, 'network' and 'power' statistics are supported.
>> */
>> readonly attribute any resourceTypes; // array of DOMString

Can't you use sequence<DOMString> instead of any?

>> /**
>> * Time in milliseconds between statistics stored in database.
>> */
>> readonly attribute unsigned long long sampleRate;

Why is this an unsigned long long? Do you expect to have to deal with
such large sampling rates?

>> /**
>> * Time in milliseconds recorded by the API until present time. All
>> * statistics older than maxStorageAge from now are deleted.
>> */
>> readonly attribute unsigned long long maxStorageAge;
>> };
>>
>> == Proposal End ==

Thanks for your work here so far!
Ehsan

Borting Chen

unread,
Jan 10, 2014, 2:25:53 AM1/10/14
to Ehsan Akhgari, Salvador de la Puente González, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Gene Lian
Hi Ehsan and Salvador:

Thanks for the suggestions. Please see my in-line response.
I am not sure that whether we are planning to count bluetooth traffic.
But, if so, we will have "bluetooth" in NetworkComponent.
Hence, I would prefer to use an enum plus an identifier to express the network components.

Another idea, how about use an "ResourceComponent" enum to integrate "PowerComponent" and "NetworkComponent"?
and provide an |id| variable for further identification (i.e. this is the iccid for mobile)

My approach would be something like this:

enum ResourceComponent {
"cpu",
"screen",
"mobile",
"wifi",
"bluetooth",
"gps"
}

DOMString id; // for mobile, this is the iccid

I think this could give a clear classification, as the ResourceComponent defines the component owned by a mobile phone and the |id| is used to specify a more detail description if necessary.
Here are some use cases:

Case 1: Query network packets transmit by a particular SIM

==> { type: "network",
component: "mobile",
id: "89886920...", // iccid
...
}

Case 2: Query network usage of mobile (i,e, sum of all SIMs)

==> { type: "network",
component: "mobile",
id: null, // or undefined
...
}

Case 3: Query network usage of wifi

==> { type: "network",
component: "wifi",
id: null, // or undefined
...
}

Case 4: Query power consumption of mobile

==> { type: "power",
component: "mobile",
id: null, // or undefined
...
}

And the following misuse cases would return an error or an exception:

Misuse 1: Query network usage of cpu

==> { type: "network",
component: "cpu",
id: null, // or undefined
...
}

Misuse 2: Query network usage of wifi, but specify an id (assume we have only one wifi interface now)

==> { type: "network",
component: "wifi",
id: "1",
...
}

Misuse 3: Query power consumption of mobile, but specify an iccid
(It is not necessary to distinguish the power consumption of different SIMs.)

==> { type: "power",
component: "mobile",
id: "89886920...",
...
}

Is this okay?

> >> /**
> >> * List of system services supporting resource statistics
> >> */
> >> enum SystemService {
> >> "ota",
> >> "tethering"
> >> };
> >>
> >> typedef (PowerComponent or NetworkComponent or DOMString)
> >> ResourceStatsComponent;
> >>
> >> dictionary ResourceStatsOptions
> >> {
> >> /**
> >> * For power stats, |component| specifies which component's power
> >> consumption
> >> * will be returned. If null, total power consumption is returned.
> > I encourage to be null or undefined (may this is implicit, just to
> > remark) in order to avoid including it in the JS object.
>
> We should probably make this default to null, and take the null value or
> not specifying at all to mean "all". Similarly for other cases. Of
> course, that means that the type should be nullable too.

okay, thanks for the suggestion.
Good idea. Thanks for the suggestion
I would like to change the order of the parameter as following:

Promise getStats(optional ResourceStatsOptions statsOptions,
optional unsigned long long start,
optional unsigned long long end);

So, we can use this method as following:

mgr.getStats(options, startTime, endTime); // query stats of the specified app/service in the specified time range
mgr.getStats(options, startTime); // query stats of the specified app/service in the range [startTime, Now]
mgr.getStats(options); // query stats of the specified app/service stored in DB
mgr.getStats(); // query all stats stored in DB

Is this okay?

> >> *
> >> * |statsOptions| specifies the detial of statistics of interest.
> >> *
> >> * If success, the |result| field keeps statistics.
> >> * For networkStatsManager, the |result| is an array of
> >> NetworkStats object.
> >> * For powerStatsManager, the |result| is an array of PowerStats
> >> object.
> >> */
> >> Promise getStats(unsigned long long start,
> >> unsigned long long end,
> >> optional ResourceStatsOptions statsOptions);
> >>
> >> /**
> >> * Clear resource statistics stored in database.
> >> *
> >> * If |statsOptions| is provided, then only the statistics
> >> associated to that
> >> * |statsOptions| is deleted. Otherwise, all statistics of this
> >> resource type
> >> * is deleted.
> >> */
> >> Promise clearStats(optional ResourceStatsOptions statsOptions);
>
> Is it OK that this doesn't accept a time range?

I guess most users will want to delete all records associated to an app or a service when calling this method.
But it is okay for me to provide something like:

Promise clearStats(optional ResourceStatsOptions statsOptions,
optional unsigned long long start,
optional unsigned long long end);

This makes clearStats() to be consistent with the getStats().

> > As we are providing the next `clearAllStats()` method, the parameter is
> > no longer optional and the explanation about it, when omitted should be
> > moved to the next method.

I don't know why but I need to keep the "optional"; or else, WebIDL.py would return the following error:
"error: Dictionary argument or union argument containing a dictionary not followed by a required argument must be optional"
My fault. The |threshold| should be defined as unsigned long.
So, this method should be:

Promise addAlarm(unsigned long threshold,
optional ResourceStatsOptions statsOptions,
optional ResourceStatsAlarmOptions alarmOptions);

> >> /**
> >> * Obtain alarms.
> >> *
> >> * If |statsOptions| is provided, then only the alarms monitoring that
> >> * resource are returned. Otherwise, all alarms set for this
> >> resource type
> >> * is returned.
> >> *
> >> * If success, the |result| is an array of ResourceStatsAlarm.
> >> */
> >> Promise getAlarms(optional ResourceStatsOptions statsOptions);
> >>
> >> /**
> >> * Obtain all alarms.
> >> *
> >> * If success, the |result| is an array of ResourceStatsAlarm.
> >> */
> >> Promise getAllAlarms();
> > Although I like this, note getting is not a critical functionality (we
> > can not destroy any information with a get operation) so, according to
> > the getAlarms() documentation, we are providing here a redundant way to
> > get all the alarms.
>
> Yes, I agree. I think we should remove this function and just have
> mgr.getAlarms() return all alarms.

Thanks for the suggestion. I will remove the getAllAlarms().

> >> /**
> >> * Remove alarms.
> >> *
> >> * If an |alarmId| is provided, then only that alarm is removed.
> >> */
> >> Promise removeAlarm(optional long alarmId);
> > Here we have the opposite example. As we are destroying things, we
> > should make mandatory the parameter and use the next method,
> > removeAllAlarms(), if we want to short-cut the method and destroy all
> > the alarms.
>
> Hmm, but if we did what we do for the rest of these similar concepts,
> then we would benefit from the consistency of the usage of this API.
> What do you think?



> >> /**
> >> * Remove all alarms.
> >> */
> >> Promise removeAllAlarm();
> >>
> >> /**
> >> * Return available resource stats options stored in database.
> >> *
> >> * If success, the |result| is an array of ResourceStatsOptions.
> >> */
> >> Promise getResourceStatsOptions();
>
> It's not exactly clear to me what this method is expected to return...

Actually, this API is created to support getAvailableNetworks() of NetworkStatsManager.
(please refer: https://bugzilla.mozilla.org/show_bug.cgi?id=922926)

For network stats, it would return available networks stored in DB.
For power stats, it would return the component supporting power metering.

> >> /**
> >> * Return the type of resource statistics provided by this manager.
> >> */
> >> readonly attribute DOMString resourceType;
> >> };
> >>
> >> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
> >> NavigatorProperty="mozResourceStats",
> >> Pref="dom.mozResourceStats.enabled"]
> >> interface ResourceStatsFactory
>
> I'm not convinced that this is a good idea. We have
> [Constructor(ResourceType)] on ResourceStatsManager which means that the
> getResourceStatsManager function here is useless. We can have
> resourceTypes, sampleRate and maxStorageAge be static read-only
> attributes on ResourceStatsManager. That would mean that we can
> eliminate ResourceStatsFactory completely, and not have this interface
> tie to navigator at all, which would let you write code like:
>
> var stats = new ResourceStatsManager("network");
> stats.getStats(...).then(...);

You are right. I will merge this to ResourceStatsManager.

But, a little question here.
In original design, ResourceStatsFactory.resourceTypes returns the supported statistic types (i.e. ["network", "power"]).
And a manager returns the statistic type it supported, for example netStatsMgr.resourceType would return "network".
But, if we provide ResourceStatsManager only, there is no attribute can provide the info of supported statistic types.
Do we need to provide another attribute to support this?

> >> {
> >> /**
> >> * Get the resourceStatsManager for a resource type.
> >> *
> >> * |type| specifies the type of resourceStatsManager we want to
> >> obtain.
> >> * This value should be one of those returned by resourceTypes
> >> attribute.
> >> *
> >> * If success, this method returns an object of ResourceStatsManager.
> >> * Otherwise, null is resturned
> >> */
> >> ResourceStatsManager getResourceStatsManager(ResourceType type);
> > May be we can reduce verbosity by renaming this method to getManager().
> >>
> >> /**
> >> * Return the name of supported resource statistics types.
> >> * Currently, 'network' and 'power' statistics are supported.
> >> */
> >> readonly attribute any resourceTypes; // array of DOMString
>
> Can't you use sequence<DOMString> instead of any?

I never thought about it before. Thanks for the suggestion.

> >> /**
> >> * Time in milliseconds between statistics stored in database.
> >> */
> >> readonly attribute unsigned long long sampleRate;
>
> Why is this an unsigned long long? Do you expect to have to deal with
> such large sampling rates?

Oh, I just wanted to keep consistent with maxStorageAge.
It is okay for me to define sampleRate as unsigned long.
Thanks for the suggestion.

> >> /**
> >> * Time in milliseconds recorded by the API until present time. All
> >> * statistics older than maxStorageAge from now are deleted.
> >> */
> >> readonly attribute unsigned long long maxStorageAge;
> >> };
> >>
> >> == Proposal End ==

Cheers,
Borting

Salvador de la Puente González

unread,
Jan 10, 2014, 6:48:08 AM1/10/14
to Borting Chen, Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hello guys!

I would want to make a call for other developers (better if they are
pure front-end developers) to take a look to our proposals in order to
provide a higher perspective.

In addition, Albert, can you provide some technical feedback here?

After my calling, comments in line:
I would like to keep all component dimension related stuff together but
your idea lead me to a variation I think it could provide functionality
and expresivity. Instead of component and id keys, why not { component:
{ <component>:<id> }, ... } ?

If you want to not specify a component, use { component: '<component>', ...}
>
> I think this could give a clear classification, as the ResourceComponent defines the component owned by a mobile phone and the |id| is used to specify a more detail description if necessary.
> Here are some use cases:
>
> Case 1: Query network packets transmit by a particular SIM
>
> ==> { type: "network",
> component: "mobile",
> id: "89886920...", // iccid
> ...
> }
This would be:

==> { type: "network",
component: { "mobile":"89886920..."}
...
}

Anyway, I still bet for the DOMString approach since it is more flexible
and allow undefined levels of multiplexing.
> Case 2: Query network usage of mobile (i,e, sum of all SIMs)
>
> ==> { type: "network",
> component: "mobile",
> id: null, // or undefined
> ...
> }
This would end as:

==> { type: "network",
component: "mobile"
See my comments about getResourceStatsOptions()
I like it but I want to hear the opinion of Albert and José Manuel
because we designed the API of NetworkStatistics and, for some reason,
we moved from an approach based on an interval object to making these
parameters mandatory. Anyway, the approach based on a range object makes
a lot of sense to me and reduces the number of parameters. This is
something like a dictionary with start and end keys to represent
interval [start, end]. If some of them is omitted, it is assumed to be a
semi-open interval to the limit: no start -> (-inf, end]; no end ->
[start, +inf). This way the signature for the method is as follows:

getStats(range[, options]);

Based on my experience with Cost Control app it is quite common to ask
for big-picture statistics in a specific range so the order of
parameters seems more intuitive to me this way.
Adding the start and end options (or the range object proposed before)
to the signatures seems a great idea to me and yes, make it consistent
with getStats().
>
>>> As we are providing the next `clearAllStats()` method, the parameter is
>>> no longer optional and the explanation about it, when omitted should be
>>> moved to the next method.
> I don't know why but I need to keep the "optional"; or else, WebIDL.py would return the following error:
> "error: Dictionary argument or union argument containing a dictionary not followed by a required argument must be optional"
>
>> Wouldn't it be better if we just get rid of clearAllStats and make
>> mgr.clearStats() clear all stats? That would be consistent with the
>> semantics of getStats(), which is an advantage.
I totally agree with you that ripping out the "all" versions of the
methods provides a more homogeneous API but I simply think it's more
dangerous. Please, consider the risk of wiping out the complete database
because your optional objects become null / undefined due to a bugged
behaviour in production. If this could happen, I prefer to end with a
console error about incorrect types for parameters and explicitly call a
'all' version rather than silently loose al my data. Well though, the
developer could provide their own safe methods too so I will discuss no
more here. Hope it makes sense to you.
Yep, we should.
Same reasons as above.
>
>
>>>> /**
>>>> * Remove all alarms.
>>>> */
>>>> Promise removeAllAlarm();
>>>>
>>>> /**
>>>> * Return available resource stats options stored in database.
>>>> *
>>>> * If success, the |result| is an array of ResourceStatsOptions.
>>>> */
>>>> Promise getResourceStatsOptions();
>> It's not exactly clear to me what this method is expected to return...
> Actually, this API is created to support getAvailableNetworks() of NetworkStatsManager.
> (please refer: https://bugzilla.mozilla.org/show_bug.cgi?id=922926)
>
> For network stats, it would return available networks stored in DB.
> For power stats, it would return the component supporting power metering.
I think the point here is we need a function in the manager to enumerate
components. So the method could be renamed to
getAvailableComponents() and, depending in which specific manager we
are, this method return a set of components. This is why I prefer
DOMStrings instead of other kind of values for components. In the case
of network it will return ['wifi:0', 'mobile:<iccid1>', 'mobile:<iccid2>'].
>
>>>> /**
>>>> * Return the type of resource statistics provided by this manager.
>>>> */
>>>> readonly attribute DOMString resourceType;
>>>> };
>>>>
>>>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
>>>> NavigatorProperty="mozResourceStats",
>>>> Pref="dom.mozResourceStats.enabled"]
>>>> interface ResourceStatsFactory
>> I'm not convinced that this is a good idea. We have
>> [Constructor(ResourceType)] on ResourceStatsManager which means that the
>> getResourceStatsManager function here is useless. We can have
>> resourceTypes, sampleRate and maxStorageAge be static read-only
>> attributes on ResourceStatsManager. That would mean that we can
>> eliminate ResourceStatsFactory completely, and not have this interface
>> tie to navigator at all, which would let you write code like:
>>
>> var stats = new ResourceStatsManager("network");
>> stats.getStats(...).then(...);
> You are right. I will merge this to ResourceStatsManager.
>
> But, a little question here.
> In original design, ResourceStatsFactory.resourceTypes returns the supported statistic types (i.e. ["network", "power"]).
> And a manager returns the statistic type it supported, for example netStatsMgr.resourceType would return "network".
> But, if we provide ResourceStatsManager only, there is no attribute can provide the info of supported statistic types.
> Do we need to provide another attribute to support this?
I think you're right. The only remark here is I would avoid the `new`
notation. IMHO, some like
navigator.resourceStats.getManager('<resource>') is a better idea.
Consider now 'resourceStats' could contain other methods or properties
like the list of available 'resources'.
Hope all this makes sense to you.
Kind regards!

Ehsan Akhgari

unread,
Jan 10, 2014, 11:25:50 AM1/10/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
On 1/10/2014, 6:48 AM, Salvador de la Puente González wrote:
> Hello guys!
>
> I would want to make a call for other developers (better if they are
> pure front-end developers) to take a look to our proposals in order to
> provide a higher perspective.
>
> In addition, Albert, can you provide some technical feedback here?

Great idea, thanks for getting them into the loop. :-)
Hmm, if I understand what you mean here correctly, I'm not sure if that
would be expressible in Web IDL, since the |{ <component>:<id> }| bit is
not really a dictionary. If that's not the case, do you mind suggesting
the Web IDL declaration of the construct you have in mind please?

[snipped]
I don't feel very strongly about this either way; the range object idea
also seems good. It seems worth noting that the (-inf, end] range would
not be expressible with my proposal. Let's wait to hear from Albert and
José Manuel on this.

[snipped]
>>>> As we are providing the next `clearAllStats()` method, the parameter is
>>>> no longer optional and the explanation about it, when omitted should be
>>>> moved to the next method.
>> I don't know why but I need to keep the "optional"; or else, WebIDL.py
>> would return the following error:
>> "error: Dictionary argument or union argument containing a dictionary
>> not followed by a required argument must be optional"
>>
>>> Wouldn't it be better if we just get rid of clearAllStats and make
>>> mgr.clearStats() clear all stats? That would be consistent with the
>>> semantics of getStats(), which is an advantage.
> I totally agree with you that ripping out the "all" versions of the
> methods provides a more homogeneous API but I simply think it's more
> dangerous. Please, consider the risk of wiping out the complete database
> because your optional objects become null / undefined due to a bugged
> behaviour in production. If this could happen, I prefer to end with a
> console error about incorrect types for parameters and explicitly call a
> 'all' version rather than silently loose al my data. Well though, the
> developer could provide their own safe methods too so I will discuss no
> more here. Hope it makes sense to you.

Hmm, yeah that is a convincing argument. As much as I like a more
consistent and smaller API surface, you're right here. Perhaps we
should keep clearAllStats() and clearAllAlarms() for this reason.

[snipped]
>>>>> /**
>>>>> * Remove all alarms.
>>>>> */
>>>>> Promise removeAllAlarm();
>>>>>
>>>>> /**
>>>>> * Return available resource stats options stored in database.
>>>>> *
>>>>> * If success, the |result| is an array of ResourceStatsOptions.
>>>>> */
>>>>> Promise getResourceStatsOptions();
>>> It's not exactly clear to me what this method is expected to return...
>> Actually, this API is created to support getAvailableNetworks() of
>> NetworkStatsManager.
>> (please refer: https://bugzilla.mozilla.org/show_bug.cgi?id=922926)
>>
>> For network stats, it would return available networks stored in DB.
>> For power stats, it would return the component supporting power metering.
> I think the point here is we need a function in the manager to enumerate
> components. So the method could be renamed to
> getAvailableComponents() and, depending in which specific manager we
> are, this method return a set of components. This is why I prefer
> DOMStrings instead of other kind of values for components. In the case
> of network it will return ['wifi:0', 'mobile:<iccid1>', 'mobile:<iccid2>'].

Hmm, getResourceStatsOptions() would also enumerate the components...
Am I missing something?
What I suggested was to move these to be static attributes of
ResourceStatsManager, so you would access them using
|ResourceStatsManager.resourceTypes| for example. Does that sound good?

Cheers,
Ehsan

Ehsan Akhgari

unread,
Jan 10, 2014, 11:33:01 AM1/10/14
to Borting Chen, Salvador de la Puente González, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Gene Lian
OK, fair enough!

> Another idea, how about use an "ResourceComponent" enum to integrate "PowerComponent" and "NetworkComponent"?
> and provide an |id| variable for further identification (i.e. this is the iccid for mobile)
>
> My approach would be something like this:
>
> enum ResourceComponent {
> "cpu",
> "screen",
> "mobile",
> "wifi",
> "bluetooth",
> "gps"
> }
>
> DOMString id; // for mobile, this is the iccid

I think this is a nice idea, but Salvador doesn't agree. I'll let you
guys try to come up with the best option for now. :-)

> I think this could give a clear classification, as the ResourceComponent defines the component owned by a mobile phone and the |id| is used to specify a more detail description if necessary.
> Here are some use cases:
>
> Case 1: Query network packets transmit by a particular SIM
>
> ==> { type: "network",
> component: "mobile",
> id: "89886920...", // iccid
> ...
> }
>
> Case 2: Query network usage of mobile (i,e, sum of all SIMs)
>
> ==> { type: "network",
> component: "mobile",
> id: null, // or undefined
> ...
> }
>
FWIW for these misuse cases, we can probably throw in the implementation.

[snipped]
>>> As we are providing the next `clearAllStats()` method, the parameter is
>>> no longer optional and the explanation about it, when omitted should be
>>> moved to the next method.
>
> I don't know why but I need to keep the "optional"; or else, WebIDL.py would return the following error:
> "error: Dictionary argument or union argument containing a dictionary not followed by a required argument must be optional"

Given what Salvador argued, this should be moot now!

>> Wouldn't it be better if we just get rid of clearAllStats and make
>> mgr.clearStats() clear all stats? That would be consistent with the
>> semantics of getStats(), which is an advantage.
>>
>>>> /**
>>>> * Clear all resource statistics stored in database.
>>>> */
>>>> Promise clearAllStats();
>>> This clear all stats of the resource type as I said in my previous comment.
>>>>
>>>> /**
>>>> * Install an alarm to monitor resource usage.
>>>> *
>>>> * The |threshold| is an object specified the limit of resource
>>>> usage. When
>>>> * resource usage reaches the threshold, a "resourceStats-alarm"
>>>> system
>>>> * message is sent to the application.
>>>> *
>>>> * |statsOptions| specifies the detial of statistics of interest.
>>>> *
>>>> * |alarmOptions| is a ResourceStatsAlarmOptions object.
>>>> *
>>>> * If success, the |result| field keeps the alarm Id.
>>>> */
>>>> Promise addAlarm(any threshold,
>>>> optional ResourceStatsOptions statsOptions,
>>>> optional ResourceStatsAlarmOptions alarmOptions);
>>
>> Should we specify that the data argument to this API is cloned using the
>> Structured Clone algorithm? We can't accept any JS object here unless
>> I'm missing something.
>
> My fault. The |threshold| should be defined as unsigned long.
> So, this method should be:
>
> Promise addAlarm(unsigned long threshold,
> optional ResourceStatsOptions statsOptions,
> optional ResourceStatsAlarmOptions alarmOptions);

Oh, good! But I was actually talking about
ResourceStatsAlarmOptions.id. :-) It can't just be |any|.

[snipped]
>>>> /**
>>>> * Return the type of resource statistics provided by this manager.
>>>> */
>>>> readonly attribute DOMString resourceType;
>>>> };
>>>>
>>>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
>>>> NavigatorProperty="mozResourceStats",
>>>> Pref="dom.mozResourceStats.enabled"]
>>>> interface ResourceStatsFactory
>>
>> I'm not convinced that this is a good idea. We have
>> [Constructor(ResourceType)] on ResourceStatsManager which means that the
>> getResourceStatsManager function here is useless. We can have
>> resourceTypes, sampleRate and maxStorageAge be static read-only
>> attributes on ResourceStatsManager. That would mean that we can
>> eliminate ResourceStatsFactory completely, and not have this interface
>> tie to navigator at all, which would let you write code like:
>>
>> var stats = new ResourceStatsManager("network");
>> stats.getStats(...).then(...);
>
> You are right. I will merge this to ResourceStatsManager.
>
> But, a little question here.
> In original design, ResourceStatsFactory.resourceTypes returns the supported statistic types (i.e. ["network", "power"]).
> And a manager returns the statistic type it supported, for example netStatsMgr.resourceType would return "network".
> But, if we provide ResourceStatsManager only, there is no attribute can provide the info of supported statistic types.
> Do we need to provide another attribute to support this?

I'm not suggesting to change any of this from your proposal, please just
move those attributes to be static attributes of ResourceStatsManager.

Cheers,
Ehsan

Borting Chen

unread,
Jan 10, 2014, 12:58:28 PM1/10/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
Hi Ehsan:

> >> Should we specify that the data argument to this API is cloned using the
> >> Structured Clone algorithm? We can't accept any JS object here unless
> >> I'm missing something.
> >
> > My fault. The |threshold| should be defined as unsigned long.
> > So, this method should be:
> >
> > Promise addAlarm(unsigned long threshold,
> > optional ResourceStatsOptions statsOptions,
> > optional ResourceStatsAlarmOptions alarmOptions);
>
> Oh, good! But I was actually talking about
> ResourceStatsAlarmOptions.id. :-) It can't just be |any|.

Oops, I misunderstood.
Should I specify the data as an object type?
so, the ResourceStatsAlarmOptions would be something like this:

dictionary ResourceStatsAlarmOptions
{
unsigned long long startTime; // time in milliseconds since Epoch
object data;
};

[snipped]

> >>>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
> >>>> NavigatorProperty="mozResourceStats",
> >>>> Pref="dom.mozResourceStats.enabled"]
> >>>> interface ResourceStatsFactory
> >>
> >> I'm not convinced that this is a good idea. We have
> >> [Constructor(ResourceType)] on ResourceStatsManager which means that the
> >> getResourceStatsManager function here is useless. We can have
> >> resourceTypes, sampleRate and maxStorageAge be static read-only
> >> attributes on ResourceStatsManager. That would mean that we can
> >> eliminate ResourceStatsFactory completely, and not have this interface
> >> tie to navigator at all, which would let you write code like:
> >>
> >> var stats = new ResourceStatsManager("network");
> >> stats.getStats(...).then(...);
> >
> > You are right. I will merge this to ResourceStatsManager.
> >
> > But, a little question here.
> > In original design, ResourceStatsFactory.resourceTypes returns the
> > supported statistic types (i.e. ["network", "power"]).
> > And a manager returns the statistic type it supported, for example
> > netStatsMgr.resourceType would return "network".
> > But, if we provide ResourceStatsManager only, there is no attribute can
> > provide the info of supported statistic types.
> > Do we need to provide another attribute to support this?
>
> I'm not suggesting to change any of this from your proposal, please just
> move those attributes to be static attributes of ResourceStatsManager.

Sorry, I am a little confused.
What you suggested is removing the ResourceStatsFactory interface and providing a ResourceStatsManager interface like this:

[Constructor(ResourceType), NavigatorProperty="mozResourceStats", ...]
interface ResourceStatsManager{
...
readonly attribute sequence<DOMString> resourceTypes;
readonly attribute unsigned long long sampleRate;
readonly attribute unsigned long long maxStorageAge;
};

Am I right?



Thanks for your responses.

Cheers,
Borting

Ehsan Akhgari

unread,
Jan 10, 2014, 1:15:33 PM1/10/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
On 1/10/2014, 12:58 PM, Borting Chen wrote:
> Hi Ehsan:
>
>>>> Should we specify that the data argument to this API is cloned using the
>>>> Structured Clone algorithm? We can't accept any JS object here unless
>>>> I'm missing something.
>>>
>>> My fault. The |threshold| should be defined as unsigned long.
>>> So, this method should be:
>>>
>>> Promise addAlarm(unsigned long threshold,
>>> optional ResourceStatsOptions statsOptions,
>>> optional ResourceStatsAlarmOptions alarmOptions);
>>
>> Oh, good! But I was actually talking about
>> ResourceStatsAlarmOptions.id. :-) It can't just be |any|.
>
> Oops, I misunderstood.
> Should I specify the data as an object type?
> so, the ResourceStatsAlarmOptions would be something like this:
>
> dictionary ResourceStatsAlarmOptions
> {
> unsigned long long startTime; // time in milliseconds since Epoch
> object data;
> };

Are you familiar with the structured clone algorithm?
<http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#structured-clone>
This is an algorithm used to safely pass structured data around. The
problem here is that if we specify the type of data as |any| without
further restructions, you can pass things that are not safely
transportable to other browsing contexts etc, and we need to prevent
that by calling out that the data argument needs to be cloned using
structured clone. Does that make sense?
Almost, I suggested these attributes to be static
<http://heycam.github.io/webidl/#idl-static-attributes-and-operations>
which means they can be accessed off of the interface object without
needing to instantiate any objects from that interface first. So, for
example, instead of writing |navigator.mozResourceStats.resourceTypes|,
you would write |ResourceStatsManager.resourceTypes|.

Cheers,
Ehsan

Salvador de la Puente González

unread,
Jan 14, 2014, 5:29:19 AM1/14/14
to Ehsan Akhgari, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hello guys!

More comments in-line:

On 10/01/14 17:25, Ehsan Akhgari wrote:
> Hmm, if I understand what you mean here correctly, I'm not sure if
> that would be expressible in Web IDL, since the |{ <component>:<id> }|
> bit is not really a dictionary. If that's not the case, do you mind
> suggesting the Web IDL declaration of the construct you have in mind
> please?
Oh, sorry, I would mean { '<component>':'<id>' } as strings. That is a
valid dictionary / JS object. Anyway, I want to say I support the idea
of taking a separate 'id' key for specifying the specific component.
What I don't agree is to have this at the same level of 'component' key
because it is **part of the component** not a sibling of the component.
Just notice since negative dates are invalid, (-inf, end] === [0, end]
so don't worry, both alternatives have the same expressibility. I'm only
concerned about how much intuitive is to write `getStats(somePastDate,
null, options)` or getStats(null, somePastDate). Lets hear news from
José Manuel and Albert.
> [snipped]
>>>>>> /**
>>>>>> * Remove all alarms.
>>>>>> */
>>>>>> Promise removeAllAlarm();
>>>>>>
>>>>>> /**
>>>>>> * Return available resource stats options stored in database.
>>>>>> *
>>>>>> * If success, the |result| is an array of ResourceStatsOptions.
>>>>>> */
>>>>>> Promise getResourceStatsOptions();
>>>> It's not exactly clear to me what this method is expected to return...
>>> Actually, this API is created to support getAvailableNetworks() of
>>> NetworkStatsManager.
>>> (please refer: https://bugzilla.mozilla.org/show_bug.cgi?id=922926)
>>>
>>> For network stats, it would return available networks stored in DB.
>>> For power stats, it would return the component supporting power
>>> metering.
>> I think the point here is we need a function in the manager to enumerate
>> components. So the method could be renamed to
>> getAvailableComponents() and, depending in which specific manager we
>> are, this method return a set of components. This is why I prefer
>> DOMStrings instead of other kind of values for components. In the case
>> of network it will return ['wifi:0', 'mobile:<iccid1>',
>> 'mobile:<iccid2>'].
>
> Hmm, getResourceStatsOptions() would also enumerate the components...
> Am I missing something?
I'm suggesting only to rename the function as I don't understand what
more information is provided here. I mean, the resourceStatsOptions
dictionary is always the same. The only field that is semantically
specific to the resource you're querying is the 'component' field so it
makes sense to ask explicitly for those components and nothing more.
>
>>>>>> /**
>>>>>> * Return the type of resource statistics provided by this
>>>>>> manager.
>>>>>> */
>>>>>> readonly attribute DOMString resourceType;
>>>>>> };
>>>>>>
>>>>>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
>>>>>> NavigatorProperty="mozResourceStats",
>>>>>> Pref="dom.mozResourceStats.enabled"]
>>>>>> interface ResourceStatsFactory
>>>> I'm not convinced that this is a good idea. We have
>>>> [Constructor(ResourceType)] on ResourceStatsManager which means
>>>> that the
>>>> getResourceStatsManager function here is useless. We can have
>>>> resourceTypes, sampleRate and maxStorageAge be static read-only
>>>> attributes on ResourceStatsManager. That would mean that we can
>>>> eliminate ResourceStatsFactory completely, and not have this interface
>>>> tie to navigator at all, which would let you write code like:
>>>>
>>>> var stats = new ResourceStatsManager("network");
>>>> stats.getStats(...).then(...);
>>> You are right. I will merge this to ResourceStatsManager.
>>>
>>> But, a little question here.
>>> In original design, ResourceStatsFactory.resourceTypes returns the
>>> supported statistic types (i.e. ["network", "power"]).
>>> And a manager returns the statistic type it supported, for example
>>> netStatsMgr.resourceType would return "network".
>>> But, if we provide ResourceStatsManager only, there is no attribute
>>> can provide the info of supported statistic types.
>>> Do we need to provide another attribute to support this?
>> I think you're right. The only remark here is I would avoid the `new`
>> notation. IMHO, some like
>> navigator.resourceStats.getManager('<resource>') is a better idea.
>> Consider now 'resourceStats' could contain other methods or properties
>> like the list of available 'resources'.
>
> What I suggested was to move these to be static attributes of
> ResourceStatsManager, so you would access them using
> |ResourceStatsManager.resourceTypes| for example. Does that sound good?
Yes, I realized I added my comment in a wrong place. I agree on moving
resourceTypes as a static attribute of ResourceStatsManager but I what
I was suggesting is a factory strategy. Take a look to this example:

var specificResources = navigator.resourceStats.resources;

var specificResourceManager = navigator.resourceStats.getManager(specificResource[0]);


Does all this make sense to you?

Thank you.

Ehsan Akhgari

unread,
Jan 14, 2014, 10:47:04 AM1/14/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
On 1/14/2014, 5:29 AM, Salvador de la Puente Gonz�lez wrote:
> Hello guys!
>
> More comments in-line:
>
> On 10/01/14 17:25, Ehsan Akhgari wrote:
>> Hmm, if I understand what you mean here correctly, I'm not sure if
>> that would be expressible in Web IDL, since the |{ <component>:<id> }|
>> bit is not really a dictionary. If that's not the case, do you mind
>> suggesting the Web IDL declaration of the construct you have in mind
>> please?
> Oh, sorry, I would mean { '<component>':'<id>' } as strings. That is a
> valid dictionary / JS object. Anyway, I want to say I support the idea
> of taking a separate 'id' key for specifying the specific component.
> What I don't agree is to have this at the same level of 'component' key
> because it is **part of the component** not a sibling of the component.

Yes, I think I understood you correctly, but like I said, what you're
describing is not expressible in WebIDL, and I prefer if we came up with
a syntax that does map to existing WebIDL constructs. I don't care very
strongly how it looks like here as long as it's in WebIDL. :-)

>> [snipped]
>>>>> I think we can do better:
>>>>>
>>>>> Promise getStats(optional unsigned long long start,
>>>>> optional unsigned long long end,
>>>>> optional ResourceStatsOptions statsOptions);
>>>>>
>>>>> That should let us drop |end| when we want current time, and drop both
>>>>> start and end when we want the full range. Does that make sense?
>>>> Good idea. Thanks for the suggestion
>>>> I would like to change the order of the parameter as following:
>>>>
>>>> Promise getStats(optional ResourceStatsOptions statsOptions,
>>>> optional unsigned long long start,
>>>> optional unsigned long long end);
>>>>
>>>> So, we can use this method as following:
>>>>
>>>> mgr.getStats(options, startTime, endTime); // query stats of the
>>>> specified app/service in the specified time range
>>>> mgr.getStats(options, startTime); // query stats of the specified
>>>> app/service in the range [startTime, Now]
>>>> mgr.getStats(options); // query stats of the specified app/service
>>>> stored in DB
>>>> mgr.getStats(); // query all stats stored in DB
>>>>
>>>> Is this okay?
>>> I like it but I want to hear the opinion of Albert and Jos� Manuel
>>> because we designed the API of NetworkStatistics and, for some reason,
>>> we moved from an approach based on an interval object to making these
>>> parameters mandatory. Anyway, the approach based on a range object makes
>>> a lot of sense to me and reduces the number of parameters. This is
>>> something like a dictionary with start and end keys to represent
>>> interval [start, end]. If some of them is omitted, it is assumed to be a
>>> semi-open interval to the limit: no start -> (-inf, end]; no end ->
>>> [start, +inf). This way the signature for the method is as follows:
>>>
>>> getStats(range[, options]);
>>>
>>> Based on my experience with Cost Control app it is quite common to ask
>>> for big-picture statistics in a specific range so the order of
>>> parameters seems more intuitive to me this way.
>>
>> I don't feel very strongly about this either way; the range object
>> idea also seems good. It seems worth noting that the (-inf, end]
>> range would not be expressible with my proposal. Let's wait to hear
>> from Albert and Jos� Manuel on this.
>>
> Just notice since negative dates are invalid, (-inf, end] === [0, end]
> so don't worry, both alternatives have the same expressibility. I'm only
> concerned about how much intuitive is to write `getStats(somePastDate,
> null, options)` or getStats(null, somePastDate). Lets hear news from
> Jos� Manuel and Albert.

Hmm yeah you're right (well, except that s/null/undefined/ in your example.)
Right, makes sense.
What I suggested gives you exactly that, without pinning anything off of
navigator:

var specificResources = ResourceStatsManager.resourceTypes;
var specificResourceManager = new
ResourceStatsManager(specificResources[0]);

The main difference between our proposals is that mine doesn't pollute
the navigator object at all, and just uses a constructor which acts as a
factory. No navigator pollution + less Java-ism == win! :-)

Cheers,
Ehsan

Ehsan Akhgari

unread,
Jan 14, 2014, 10:51:17 AM1/14/14
to Borting Chen, dev-w...@lists.mozilla.org, JOSE MANUEL CANTERA FONSECA, Salvador de la Puente González, Gene Lian
On 1/9/2014, 10:12 AM, Borting Chen wrote:
[snipped]

> [Constructor(ResourceType type), JSImplementation="@mozilla.org/resourceStatsManager;1", Pref="dom.mozResourceStats.enabled"]
> interface ResourceStatsManager
> {
> /**
> * Query resource statistics.
> *
> * |start| and |end| specifies the time range of interest, both included.
> * If |start| is 0, retrieves the stats since measurements.
> * If |end| is 0. retrieves the stats until the current time.
> *
> * |statsOptions| specifies the detial of statistics of interest.
> *
> * If success, the |result| field keeps statistics.
> * For networkStatsManager, the |result| is an array of NetworkStats object.
> * For powerStatsManager, the |result| is an array of PowerStats object.

BTW, I just realized that you need to define the NetworkStats and
PowerStats interfaces in WebIDL as well.

Cheers,
Ehsan

Salvador de la Puente González

unread,
Jan 14, 2014, 12:36:26 PM1/14/14
to Ehsan Akhgari, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hi,

Just a couple of comments:

On 14/01/14 16:47, Ehsan Akhgari wrote:
> On 1/14/2014, 5:29 AM, Salvador de la Puente González wrote:
>> Hello guys!
>>
>> More comments in-line:
>>
>> On 10/01/14 17:25, Ehsan Akhgari wrote:
>>> Hmm, if I understand what you mean here correctly, I'm not sure if
>>> that would be expressible in Web IDL, since the |{ <component>:<id> }|
>>> bit is not really a dictionary. If that's not the case, do you mind
>>> suggesting the Web IDL declaration of the construct you have in mind
>>> please?
>> Oh, sorry, I would mean { '<component>':'<id>' } as strings. That is a
>> valid dictionary / JS object. Anyway, I want to say I support the idea
>> of taking a separate 'id' key for specifying the specific component.
>> What I don't agree is to have this at the same level of 'component' key
>> because it is **part of the component** not a sibling of the component.
>
> Yes, I think I understood you correctly, but like I said, what you're
> describing is not expressible in WebIDL, and I prefer if we came up
> with a syntax that does map to existing WebIDL constructs. I don't
> care very strongly how it looks like here as long as it's in WebIDL. :-)
Yes, you're right. It is not impossible, it is just a mess to define
upon dictionaries but you can do:
{
...
jsval component,
...
}
> What I suggested gives you exactly that, without pinning anything off
> of navigator:
>
> var specificResources = ResourceStatsManager.resourceTypes;
> var specificResourceManager = new
> ResourceStatsManager(specificResources[0]);
>
> The main difference between our proposals is that mine doesn't pollute
> the navigator object at all, and just uses a constructor which acts as
> a factory. No navigator pollution + less Java-ism == win! :-)
>
Let's discuss if `new` is more or less JS face of face xD... I see the
advantages for a developer to simply make `new
ResourceStatsManager(...)` so being pragmatic, I agree on you and I wont
push on the alternative any more.
> Cheers,
> Ehsan
>
Thank you very much. I think we agree on almost everything.
Let's see what happen with the `component` field and the `getStats()`
signature.

Cheers!

Ehsan Akhgari

unread,
Jan 14, 2014, 2:25:35 PM1/14/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
On 1/14/2014, 12:36 PM, Salvador de la Puente Gonz�lez wrote:
> Hi,
>
> Just a couple of comments:
>
> On 14/01/14 16:47, Ehsan Akhgari wrote:
>> On 1/14/2014, 5:29 AM, Salvador de la Puente Gonz�lez wrote:
>>> Hello guys!
>>>
>>> More comments in-line:
>>>
>>> On 10/01/14 17:25, Ehsan Akhgari wrote:
>>>> Hmm, if I understand what you mean here correctly, I'm not sure if
>>>> that would be expressible in Web IDL, since the |{ <component>:<id> }|
>>>> bit is not really a dictionary. If that's not the case, do you mind
>>>> suggesting the Web IDL declaration of the construct you have in mind
>>>> please?
>>> Oh, sorry, I would mean { '<component>':'<id>' } as strings. That is a
>>> valid dictionary / JS object. Anyway, I want to say I support the idea
>>> of taking a separate 'id' key for specifying the specific component.
>>> What I don't agree is to have this at the same level of 'component' key
>>> because it is **part of the component** not a sibling of the component.
>>
>> Yes, I think I understood you correctly, but like I said, what you're
>> describing is not expressible in WebIDL, and I prefer if we came up
>> with a syntax that does map to existing WebIDL constructs. I don't
>> care very strongly how it looks like here as long as it's in WebIDL. :-)
> Yes, you're right. It is not impossible, it is just a mess to define
> upon dictionaries but you can do:
> {
> ...
> jsval component,
> ...
> }

The issue is that WebIDL dictionaries allow you to specify any number of
the members of that dictionary. So we can't create a dictionary which
has one member per component for the purposes of your proposal. So I
think the only way to represent this in WebIDL is to just accept an
|any| argument, which is terrible.

Cheers,
Ehsan

Ehsan Akhgari

unread,
Jan 14, 2014, 2:25:29 PM1/14/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian

Salvador de la Puente González

unread,
Jan 15, 2014, 5:13:28 AM1/15/14
to Ehsan Akhgari, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hello Ehsan

On 14/01/14 20:25, Ehsan Akhgari wrote:
> On 1/14/2014, 12:36 PM, Salvador de la Puente González wrote:
>> Hi,
>>
>> Just a couple of comments:
>>
>> On 14/01/14 16:47, Ehsan Akhgari wrote:
Several choices here:

1) A fragment of the IDL needed:
dictionary SimComponentSpec { DOMString sim }
dictionary CPUComponentSpec { number cpu }
...

{
...
(SimComponentSpec or CPUComponenSpec or ...) component;
...
}

Is this not a valid IDL?

2) We can check a jsval and iterate on the first key only.

3) We can adopt another simpler type as:

dictionary ComponentSpecification {
DOMString name,
DOMString id
}

{
...
(DOMString or ComponentSpecification) component;
...
}

And this only remarks that what I don't agree is to have the `id` at the
same level of `component` as I said in my previos e-mail.

4) Allow this...

dictionary ComponentsSepecs {
DOMString sim,
DOMString cpu,
DOMString network,
....
}

{
...
ComponentsSpecs component,
...
}

For the present implementation, we only accept one of the fields being
not null (the behaviour for other combinations is undefined). A future
implementation could aggregate the concepts into the `component` field
(and I suggest renaming it to `components`).

I insist, my only complain is this arrangement of fields:

DOMString component,
DOMString id

Because I think we have a very clear interface based on specifying what
you want to meter based on independent criteria (component, application,
systemService) and I would want to keep this independence. But If my
arguments does not convince you, I agree on the `id` option. There is
always room for improvement : )

Thank you guys.

Ehsan Akhgari

unread,
Jan 15, 2014, 2:14:18 PM1/15/14
to Salvador de la Puente González, Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
On 1/15/2014, 5:13 AM, Salvador de la Puente Gonz�lez wrote:
> Hello Ehsan
>
> On 14/01/14 20:25, Ehsan Akhgari wrote:
>> On 1/14/2014, 12:36 PM, Salvador de la Puente Gonz�lez wrote:
>>> Hi,
>>>
>>> Just a couple of comments:
>>>
>>> On 14/01/14 16:47, Ehsan Akhgari wrote:
Hmm it is, but it will let you write code like:

foo.component = { sim: "bar" };
foo.component = { cpu: 100 };

Is that what you were looking to achieve?

> 2) We can check a jsval and iterate on the first key only.

I'd rather adopt an API which doesn't require this.

> 3) We can adopt another simpler type as:
>
> dictionary ComponentSpecification {
> DOMString name,
> DOMString id
> }
>
> {
> ...
> (DOMString or ComponentSpecification) component;
> ...
> }
>
> And this only remarks that what I don't agree is to have the `id` at the
> same level of `component` as I said in my previos e-mail.
>
> 4) Allow this...
>
> dictionary ComponentsSepecs {
> DOMString sim,
> DOMString cpu,
> DOMString network,
> ....
> }
>
> {
> ...
> ComponentsSpecs component,
> ...
> }
>
> For the present implementation, we only accept one of the fields being
> not null (the behaviour for other combinations is undefined). A future
> implementation could aggregate the concepts into the `component` field
> (and I suggest renaming it to `components`).

This is kind of abusing WebIDL dictionaries.

> I insist, my only complain is this arrangement of fields:
>
> DOMString component,
> DOMString id
>
> Because I think we have a very clear interface based on specifying what
> you want to meter based on independent criteria (component, application,
> systemService) and I would want to keep this independence. But If my
> arguments does not convince you, I agree on the `id` option. There is
> always room for improvement : )

To be honest, I don't care much about the dimensionality of component
and the rest of the values here, so I'm happy to leave this up to you.
Based on the four alternatives you suggested, I guess the #1 is the
least bad option, but I'm concerned that it makes the API too verbose.
But that's something that we can get feedback on from the useers of the
API once we implement one of these alternatives. I guess I'm happy to
leave it to Borting which one he wants to choose here. :-)

Cheers,
Ehsan

Borting Chen

unread,
Jan 15, 2014, 10:20:23 PM1/15/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
Hi Ehsan:

--
Borting Chen
Intern of Mozilla Taiwan


----- Original Message -----
> From: "Ehsan Akhgari" <ehsan....@gmail.com>
> To: "Borting Chen" <boc...@mozilla.com>
> Cc: "Salvador de la Puente González" <s...@tid.es>, dev-w...@lists.mozilla.org, "JOSE MANUEL CANTERA FONSECA"
> <jm...@tid.es>, "Gene Lian" <cl...@mozilla.com>
> Sent: Saturday, January 11, 2014 2:15:33 AM
> Subject: Re: Proposal: ResourceStats API for NetworkStats API and PowerStats API integration
>
Yah, I understood.
But I still have no idea about how to specify the data argument to be cloned using structured clone.
(Or this should be done in the implementation?)
Could you give me some hints? Thanks.

> > Sorry, I am a little confused.
> > What you suggested is removing the ResourceStatsFactory interface and
> > providing a ResourceStatsManager interface like this:
> >
> > [Constructor(ResourceType), NavigatorProperty="mozResourceStats", ...]
> > interface ResourceStatsManager{
> > ...
> > readonly attribute sequence<DOMString> resourceTypes;
> > readonly attribute unsigned long long sampleRate;
> > readonly attribute unsigned long long maxStorageAge;
> > };
> >
> > Am I right?
>
> Almost, I suggested these attributes to be static
> <http://heycam.github.io/webidl/#idl-static-attributes-and-operations>
> which means they can be accessed off of the interface object without
> needing to instantiate any objects from that interface first. So, for
> example, instead of writing |navigator.mozResourceStats.resourceTypes|,
> you would write |ResourceStatsManager.resourceTypes|.

Understood, leaned a lot from you, thanks. :-)

Cheers,
Borting

Borting Chen

unread,
Jan 15, 2014, 10:22:38 PM1/15/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
> >>>>>> [JSImplementation="@mozilla.org/resourceStatsFactory;1",
> >>>>>> NavigatorProperty="mozResourceStats",
> >>>>>> Pref="dom.mozResourceStats.enabled"]
> >>>>>> interface ResourceStatsFactory
> >>>>
> >>>> I'm not convinced that this is a good idea. We have
> >>>> [Constructor(ResourceType)] on ResourceStatsManager which means that the
> >>>> getResourceStatsManager function here is useless. We can have
> >>>> resourceTypes, sampleRate and maxStorageAge be static read-only
> >>>> attributes on ResourceStatsManager. That would mean that we can
> >>>> eliminate ResourceStatsFactory completely, and not have this interface
> >>>> tie to navigator at all, which would let you write code like:
> >>>>
> >>>> var stats = new ResourceStatsManager("network");
> >>>> stats.getStats(...).then(...);
> >>>
> >>> You are right. I will merge this to ResourceStatsManager.
> >>>
> >>> But, a little question here.
> >>> In original design, ResourceStatsFactory.resourceTypes returns the
> >>> supported statistic types (i.e. ["network", "power"]).
> >>> And a manager returns the statistic type it supported, for example
> >>> netStatsMgr.resourceType would return "network".
> >>> But, if we provide ResourceStatsManager only, there is no attribute can
> >>> provide the info of supported statistic types.
> >>> Do we need to provide another attribute to support this?
> >>
> >> I'm not suggesting to change any of this from your proposal, please just
> >> move those attributes to be static attributes of ResourceStatsManager.
> >
> > Sorry, I am a little confused.
> > What you suggested is removing the ResourceStatsFactory interface and
> > providing a ResourceStatsManager interface like this:
> >
> > [Constructor(ResourceType), NavigatorProperty="mozResourceStats", ...]
> > interface ResourceStatsManager{
> > ...
> > readonly attribute sequence<DOMString> resourceTypes;
> > readonly attribute unsigned long long sampleRate;
> > readonly attribute unsigned long long maxStorageAge;
> > };
> >
> > Am I right?
>
> Almost, I suggested these attributes to be static
> <http://heycam.github.io/webidl/#idl-static-attributes-and-operations>
> which means they can be accessed off of the interface object without
> needing to instantiate any objects from that interface first. So, for
> example, instead of writing |navigator.mozResourceStats.resourceTypes|,
> you would write |ResourceStatsManager.resourceTypes|.

Understood. Leaned a lot from you, thanks. :-)

Cheers,
Borting

Borting Chen

unread,
Jan 16, 2014, 1:13:59 AM1/16/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
Hi Ehsan:
Sorry, I missed this part.

The webidl would be something like this:

[JSImplementation="@mozilla.org/networkStatsData;1", Pref="dom.mozResourceStats.enabled"]
interface MozNetworkStatsData
{
readonly attribute unsigned long rxBytes; // Received bytes.
readonly attribute unsigned long txBytes; // Sent bytes
readonly attribute unsigned long long date;
};

[JSImplementation="@mozilla.org/powerStatsData;1", Pref="dom.mozResourceStats.enabled"]
interface MozPowerStatsData
{
readonly attribute unsigned long power; // power consumption
readonly attribute unsigned long long date;
};

[JSImplementation="@mozilla.org/resourceStats;1", Pref="dom.mozResourceStats.enabled"]
interface MozResourceStats
{
/**
* Type of statistics
*/
readonly attribute ResourceType type;

/**
* Manifest URL of the application.
*/
readonly attribute DOMString? manifestURL;

/**
* Type of system service
*/
readonly attribute SystemService? serviceType;

/**
* The component that the statistics belongs to.
* If null, sum of all components' statistics are returned.
*/
readonly attribute DOMString? component;

/**
* Statistics, one element per day
*/
readonly attribute (sequence<MozNetworkStatsData> or sequence<MozPowerStatsData>) data;

/**
* Date range
*/
readonly attribute unsigned long long start; // start date
readonly attribute unsigned long long end; // end date
};

Some notes:
1. This design is mainly refer the design of present NetworkStats interface.
2. The type of |component| would be changed according to the type we defined in resourceStatsOptions dictionary.
3. I am not quite sure the type of |data| could be defined as such a union, is that a valid webidl?

Cheers,
Borting

Borting Chen

unread,
Jan 16, 2014, 1:31:06 AM1/16/14
to Ehsan Akhgari, Salvador de la Puente González, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hi Ehsan and Salvador:

First, thank you guys for the great comments and suggestions.
I am really learned a lot from you guys, thanks.

About the resourceStatsOptions dictionary, I totally agree Salvador's concern
that we should not put "id" and "component" at the same level.
And, it also makes sense to me to have the three dimensions
{"component", "service", "application"} being separated independently.
So, I would like to vote Salvador's option (1).

Hi, Salvador.
Sorry, I still have a small question.
Why do you want to define a dictionary for each component in your option (1)?
Could we use a DOMString to express component and id, like "<component>:<id>" as you mentioned before?

I think both solutions are okay for me.
I am just curious about what benefit we can obtain from the design of option (1)? :-)

Thank you guys for the help!

> > On 14/01/14 20:25, Ehsan Akhgari wrote:
> >> On 1/14/2014, 12:36 PM, Salvador de la Puente González wrote:
> >>> On 14/01/14 16:47, Ehsan Akhgari wrote:
Borting

Salvador de la Puente González

unread,
Jan 16, 2014, 3:28:54 AM1/16/14
to Borting Chen, Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-webapi, ALBERTO CRESPELL PEREZ, Gene Lian
Hello Borting

On 16/01/14 07:31, Borting Chen wrote:
> Hi Ehsan and Salvador:
>
> First, thank you guys for the great comments and suggestions.
> I am really learned a lot from you guys, thanks.
>
> About the resourceStatsOptions dictionary, I totally agree Salvador's concern
> that we should not put "id" and "component" at the same level.
> And, it also makes sense to me to have the three dimensions
> {"component", "service", "application"} being separated independently.
> So, I would like to vote Salvador's option (1).
>
> Hi, Salvador.
> Sorry, I still have a small question.
> Why do you want to define a dictionary for each component in your option (1)?
> Could we use a DOMString to express component and id, like "<component>:<id>" as you mentioned before?
I don't remember where or why I suggested the dictionary one but my
favourite solution was always **this** (the WebIDL solution is very
verbose as Ehsan noticed). So I totally agree!
>
> I think both solutions are okay for me.
> I am just curious about what benefit we can obtain from the design of option (1)? :-)
>
> Thank you guys for the help!
Thank you. I learn a lot with you too!
Hope we can discuss about other APIs cause I think the result is very
good. :)

Ehsan Akhgari

unread,
Jan 21, 2014, 4:12:26 PM1/21/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
You can use the any type, and in the prose describing the API mention
that the data field will be copied using the structured clone algorithm.
It's not possible to declare this in WebIDL.
We're moving towards a good solution here, thanks to you! Keep up the
good work. :-)

Cheers,
Ehsan

Ehsan Akhgari

unread,
Jan 21, 2014, 4:19:29 PM1/21/14
to Borting Chen, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
On 1/16/2014, 1:13 AM, Borting Chen wrote:
> Hi Ehsan:
>
>>> [Constructor(ResourceType type),
>>> JSImplementation="@mozilla.org/resourceStatsManager;1",
>>> Pref="dom.mozResourceStats.enabled"]
>>> interface ResourceStatsManager
>>> {
>>> /**
>>> * Query resource statistics.
>>> *
>>> * |start| and |end| specifies the time range of interest, both
>>> included.
>>> * If |start| is 0, retrieves the stats since measurements.
>>> * If |end| is 0. retrieves the stats until the current time.
>>> *
>>> * |statsOptions| specifies the detial of statistics of interest.
>>> *
>>> * If success, the |result| field keeps statistics.
>>> * For networkStatsManager, the |result| is an array of NetworkStats
>>> object.
>>> * For powerStatsManager, the |result| is an array of PowerStats object.
>>
>> BTW, I just realized that you need to define the NetworkStats and
>> PowerStats interfaces in WebIDL as well.
>
> Sorry, I missed this part.
>
> The webidl would be something like this:
>
> [JSImplementation="@mozilla.org/networkStatsData;1", Pref="dom.mozResourceStats.enabled"]
> interface MozNetworkStatsData

Nit: please don't use Moz prefixes.

> {
> readonly attribute unsigned long rxBytes; // Received bytes.
> readonly attribute unsigned long txBytes; // Sent bytes

Nit: why not name these receivedBytes and sentBytes respectively? Also,
shouldn't these be unsigned long long?

> readonly attribute unsigned long long date;

Nit: I think date is a little bit misleading here because this
represents more than just the date. How about calling it timestamp?

(I think you should use the DOMTimeStamp type for this stuff, please see
<http://www.w3.org/TR/DOM-Level-3-Core/core.html#Core-DOMTimeStamp>,
even though it's a typedef to unsigned long long, it will make things
clearer.)

> };
>
> [JSImplementation="@mozilla.org/powerStatsData;1", Pref="dom.mozResourceStats.enabled"]
> interface MozPowerStatsData
> {
> readonly attribute unsigned long power; // power consumption

You should specify the units of measurement here. Depending on that,
this might need to be unsigned long long as well.
> readonly attribute unsigned long long start; // start date
> readonly attribute unsigned long long end; // end date

Nit: DOMTimeStamp for these and all other similar things as well. Sorry
I forgot to mention this earlier.

> };
>
> Some notes:
> 1. This design is mainly refer the design of present NetworkStats interface.
> 2. The type of |component| would be changed according to the type we defined in resourceStatsOptions dictionary.
> 3. I am not quite sure the type of |data| could be defined as such a union, is that a valid webidl?

Yes, I don't see anything wrong with it.

Cheers,
Ehsan

Borting Chen

unread,
Jan 23, 2014, 10:24:37 PM1/23/14
to Ehsan Akhgari, JOSE MANUEL CANTERA FONSECA, dev-w...@lists.mozilla.org, Salvador de la Puente González, Gene Lian
Hi Ehsan:

> > [JSImplementation="@mozilla.org/networkStatsData;1",
> > Pref="dom.mozResourceStats.enabled"]
> > interface MozNetworkStatsData
>
> Nit: please don't use Moz prefixes.
>
> > {
> > readonly attribute unsigned long rxBytes; // Received bytes.
> > readonly attribute unsigned long txBytes; // Sent bytes
>
> Nit: why not name these receivedBytes and sentBytes respectively? Also,
> shouldn't these be unsigned long long?

Yes, these should be unsigned long long, thanks.
And you are right, receivedBytes and sentBytes are more clear, I would change the naming. :P

> > readonly attribute unsigned long long date;
>
> Nit: I think date is a little bit misleading here because this
> represents more than just the date. How about calling it timestamp?
>
> (I think you should use the DOMTimeStamp type for this stuff, please see
> <http://www.w3.org/TR/DOM-Level-3-Core/core.html#Core-DOMTimeStamp>,
> even though it's a typedef to unsigned long long, it will make things
> clearer.)

Understood. Thanks.

> > };
> >
> > [JSImplementation="@mozilla.org/powerStatsData;1",
> > Pref="dom.mozResourceStats.enabled"]
> > interface MozPowerStatsData
> > {
> > readonly attribute unsigned long power; // power consumption
>
> You should specify the units of measurement here. Depending on that,
> this might need to be unsigned long long as well.

The unit is mW, so you are right, the data type should be unsigned long long.
And, in order to consist with the naming of NetworkStatsData, I would like to rename |power| to |consumedPower|.
What do you think?
Oh, because webidl.py said it cannot distinguish sequence<NetworkStatsData> from sequence<PowerStatsData>,
I am just wondering whether it is a valid definition.
(or, should I define it as sequence<any> ?)
BTW, could I rename |data| to |stats|? I think it could be more clear for users.



Thanks for your comments.


Cheers,
Borting

Borting Chen

unread,
Jan 24, 2014, 3:41:02 AM1/24/14