Merge birch to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 14 Jun 2013 13:03:51 -0400
changeset 135455 5ddb1bf962618e8afdbd467a86546e4d5f392019
parent 135439 7d50de16dff81e828c6f9e7814cd3407eacb0ddc (current diff)
parent 135454 c273c5f261870ef7bdd4cbaf8ca5a68b39a4eb21 (diff)
child 135456 8c05aa558b45c6a50a71f57fb0e98109b653cb85
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone24.0a1
Merge birch to m-c.
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "7bfb4efb6e67c97e1178fa340a17eff63d0c33d4", 
+    "revision": "0eef3cf5ff4407369e0bfb773672a6e4b5687558", 
     "repo_path": "/integration/gaia-central"
 }
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -20,20 +20,21 @@ const STORE_NAME = "net_stats";
 
 // Constant defining the maximum values allowed per interface. If more, older
 // will be erased.
 const VALUES_MAX_LENGTH = 6 * 30;
 
 // Constant defining the rate of the samples. Daily.
 const SAMPLE_RATE = 1000 * 60 * 60 * 24;
 
-this.NetworkStatsDB = function NetworkStatsDB(aGlobal) {
+this.NetworkStatsDB = function NetworkStatsDB(aGlobal, aConnectionTypes) {
   if (DEBUG) {
     debug("Constructor");
   }
+  this._connectionTypes = aConnectionTypes;
   this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME], aGlobal);
 }
 
 NetworkStatsDB.prototype = {
   __proto__: IndexedDBHelper.prototype,
 
   dbNewTxn: function dbNewTxn(txn_type, callback, txnCb) {
     function successCb(result) {
@@ -62,30 +63,51 @@ NetworkStatsDB.prototype = {
         objectStore.createIndex("timestamp", "timestamp", { unique: false });
         objectStore.createIndex("rxBytes", "rxBytes", { unique: false });
         objectStore.createIndex("txBytes", "txBytes", { unique: false });
         objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
         objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
         if (DEBUG) {
           debug("Created object stores and indexes");
         }
+
+        // There could be a time delay between the point when the network
+        // interface comes up and the point when the database is initialized.
+        // In this short interval some traffic data are generated but are not
+        // registered by the first sample. The initialization of the database
+        // should make up the missing sample.
+        let stats = [];
+        for (let connection in this._connectionTypes) {
+          let connectionType = this._connectionTypes[connection].name;
+          let timestamp = this.normalizeDate(new Date());
+          stats.push({ connectionType: connectionType,
+                       timestamp:      timestamp,
+                       rxBytes:        0,
+                       txBytes:        0,
+                       rxTotalBytes:   0,
+                       txTotalBytes:   0 });
+        }
+        this._saveStats(aTransaction, objectStore, stats);
+        if (DEBUG) {
+          debug("Database initialized");
+        }
       }
     }
   },
 
-  convertDate: function convertDate(aDate) {
+   normalizeDate: function normalizeDate(aDate) {
     // Convert to UTC according to timezone and
     // filter timestamp to get SAMPLE_RATE precission
-    let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000;
+    let timestamp = aDate.getTime() - (new Date()).getTimezoneOffset() * 60 * 1000;
     timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE;
     return timestamp;
   },
 
   saveStats: function saveStats(stats, aResultCb) {
-    let timestamp = this.convertDate(stats.date);
+    let timestamp = this.normalizeDate(stats.date);
 
     stats = {connectionType: stats.connectionType,
              timestamp:      timestamp,
              rxBytes:        0,
              txBytes:        0,
              rxTotalBytes:   stats.rxBytes,
              txTotalBytes:   stats.txBytes};
 
@@ -229,18 +251,19 @@ NetworkStatsDB.prototype = {
       if (DEBUG) {
         debug("Going to clear all!");
       }
       store.clear();
     }, aResultCb);
   },
 
   find: function find(aResultCb, aOptions) {
-    let start = this.convertDate(aOptions.start);
-    let end = this.convertDate(aOptions.end);
+    let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
+    let start = this.normalizeDate(aOptions.start);
+    let end = this.normalizeDate(aOptions.end);
 
     if (DEBUG) {
       debug("Find: connectionType:" + aOptions.connectionType + " start: " + start + " end: " + end);
       debug("Start time: " + new Date(start));
       debug("End time: " + new Date(end));
     }
 
     this.dbNewTxn("readonly", function(txn, store) {
@@ -254,36 +277,37 @@ NetworkStatsDB.prototype = {
         txn.result = {};
       }
 
       let request = store.openCursor(range).onsuccess = function(event) {
         var cursor = event.target.result;
         if (cursor){
           data.push({ rxBytes: cursor.value.rxBytes,
                       txBytes: cursor.value.txBytes,
-                      date: new Date(cursor.value.timestamp) });
+                      date: new Date(cursor.value.timestamp + offset) });
           cursor.continue();
           return;
         }
 
         // When requested samples (start / end) are not in the range of now and
         // now - VALUES_MAX_LENGTH, fill with empty samples.
-        this.fillResultSamples(start, end, data);
+        this.fillResultSamples(start + offset, end + offset, data);
 
         txn.result.connectionType = aOptions.connectionType;
         txn.result.start = aOptions.start;
         txn.result.end = aOptions.end;
         txn.result.data = data;
       }.bind(this);
     }.bind(this), aResultCb);
   },
 
   findAll: function findAll(aResultCb, aOptions) {
-    let start = this.convertDate(aOptions.start);
-    let end = this.convertDate(aOptions.end);
+    let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
+    let start = this.normalizeDate(aOptions.start);
+    let end = this.normalizeDate(aOptions.end);
 
     if (DEBUG) {
       debug("FindAll: start: " + start + " end: " + end + "\n");
     }
 
     let self = this;
     this.dbNewTxn("readonly", function(txn, store) {
       let lowFilter = start;
@@ -294,30 +318,31 @@ NetworkStatsDB.prototype = {
 
       if (!txn.result) {
         txn.result = {};
       }
 
       let request = store.index("timestamp").openCursor(range).onsuccess = function(event) {
         var cursor = event.target.result;
         if (cursor) {
-          if (data.length > 0 && data[data.length - 1].date.getTime() == cursor.value.timestamp) {
+          if (data.length > 0 &&
+              data[data.length - 1].date.getTime() == cursor.value.timestamp + offset) {
             // Time is the same, so add values.
             data[data.length - 1].rxBytes += cursor.value.rxBytes;
             data[data.length - 1].txBytes += cursor.value.txBytes;
           } else {
             data.push({ rxBytes: cursor.value.rxBytes,
                         txBytes: cursor.value.txBytes,
-                        date: new Date(cursor.value.timestamp) });
+                        date: new Date(cursor.value.timestamp + offset) });
           }
           cursor.continue();
           return;
         }
 
-        this.fillResultSamples(start, end, data);
+        this.fillResultSamples(start + offset, end + offset, data);
 
         txn.result.connectionType = aOptions.connectionType;
         txn.result.start = aOptions.start;
         txn.result.end = aOptions.end;
         txn.result.data = data;
       }.bind(this);
     }.bind(this), aResultCb);
   },
--- a/dom/network/src/NetworkStatsService.jsm
+++ b/dom/network/src/NetworkStatsService.jsm
@@ -63,17 +63,17 @@ this.NetworkStatsService = {
                      "NetworkStats:SampleRate",
                      "NetworkStats:MaxStorageSamples"];
 
     this.messages.forEach(function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }, this);
 
     gIDBManager.initWindowless(myGlobal);
-    this._db = new NetworkStatsDB(myGlobal);
+    this._db = new NetworkStatsDB(myGlobal, this._connectionTypes);
 
     // Stats for all interfaces are updated periodically
     this.timer.initWithCallback(this, this._db.sampleRate,
                                 Ci.nsITimer.TYPE_REPEATING_PRECISE);
 
     this.updateQueue = [];
     this.isQueueRunning = false;
   },
--- a/dom/network/tests/test_networkstats_basics.html
+++ b/dom/network/tests/test_networkstats_basics.html
@@ -46,18 +46,19 @@ function test() {
    "maxStorageSamples is greater than 0.");
 
   // Test IDL methods
   next();
   return;
 }
 
 function checkDataDates(data, start, end, sampleRate){
-  start = Math.floor(start.getTime() / sampleRate) * sampleRate;
-  end = Math.floor(end.getTime() / sampleRate) * sampleRate;
+  var offset = (new Date()).getTimezoneOffset() * 60 * 1000;
+  start = Math.floor((start.getTime() - offset) / sampleRate) * sampleRate + offset;
+  end = Math.floor((end.getTime() - offset) / sampleRate) * sampleRate + offset;
 
   var counter = 0;
   var date = start;
   var success = true;
 
   do {
     if(data[counter].date.getTime() !=  date) {
       success = false;
@@ -144,17 +145,19 @@ var steps = [
   function () {
     ok(true, "Get stats for a connectionType and dates adapted to samplerate");
     // Prepare get params
     var type = netStats.connectionTypes[0];
     var diff = 2;
     // Get samplerate in millis
     var sampleRate = netStats.sampleRate * 1000;
     // Get date with samplerate's precision
-    var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate);
+    var offset = new Date().getTimezoneOffset() * 60 * 1000;
+    var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate)
+                           * sampleRate + offset);
     var startDate = new Date(endDate.getTime() - (sampleRate * diff));
     // Calculate the number of samples that should be returned based on the
     // the samplerate and including final and initial samples.
     var samples = (endDate.getTime() - startDate.getTime()) / sampleRate + 1;
 
     // Launch request
     req = netStats.getNetworkStats({start: startDate, end: endDate, connectionType: type});
     req.onsuccess = function () {
@@ -174,17 +177,19 @@ var steps = [
   },
   function () {
     ok(true, "Get stats for all connectionTypes and dates adapted to samplerate");
     // Prepare get params
     var diff = 2;
     // Get samplerate in millis
     var sampleRate = netStats.sampleRate * 1000;
     // Get date with samplerate's precision
-    var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate);
+    var offset = new Date().getTimezoneOffset() * 60 * 1000;
+    var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate)
+                           * sampleRate + offset);
     var startDate = new Date(endDate.getTime() - (sampleRate * diff));
     // Calculate the number of samples that should be returned based on the
     // the samplerate and including final and initial samples.
     var samples = (endDate.getTime() - startDate.getTime()) / sampleRate + 1;
 
     // Launch request
     req = netStats.getNetworkStats({start: startDate, end: endDate});
     req.onsuccess = function () {