Skip to content

Instantly share code, notes, and snippets.

@jaredhirsch
Created June 16, 2015 19:55
Show Gist options
  • Save jaredhirsch/2c164d1185bd92af90e6 to your computer and use it in GitHub Desktop.
Save jaredhirsch/2c164d1185bd92af90e6 to your computer and use it in GitHub Desktop.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// TODO: it would be nice to check size of places DB before starting (precondition?)
// TODO: do we need to listen for shutdown events to avoid corrupting the DB?
// or does PlacesUtils handle that for us?
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
var serpCountQuery = 'SELECT COUNT(*) AS count FROM moz_historyvisits ' +
'INNER JOIN moz_places ' +
'ON moz_historyvisits.place_id = moz_places.id ' +
'WHERE moz_places.url LIKE ":providerURL" ;';
var counts = {
google: null,
yahoo: null,
amazon: null,
total: null
};
var getCount = function(url, db) {
try {
var query = serpCountQuery.replace(':providerURL', url);
return db.execute(query);
} catch (ex) {
return Promise.reject(ex);
}
};
var getGoogleCount = getCount.bind(null, '%google.com/search?q%');
var getYahooCount = getCount.bind(null, '%/search.yahoo.com/yhs/search?p%');
var getBingCount = getCount.bind(null, '%bing.com/search?q%');
var getAmazonCount = getCount.bind(null, '%amazon.com/s?%');
var saveCount = function(providerName, results) {
var count = results && results[0] && results[0].getResultByName('count');
counts[providerName] = count;
console.log('the ' + providerName + ' count is ' + count);
return Promise.resolve(count);
};
var totalCount = function(db) {
try {
var query = 'SELECT COUNT(*) AS count FROM moz_historyvisits;';
return db.execute(query);
} catch (ex) {
return Promise.reject(ex);
}
};
var summarize = function() {
// round to two decimal places
function _round(n) {
return parseFloat(n.toPrecision(3));
}
// convert absolute counts into percentages (eg 5.18%),
// and round off the total number of visits to the nearest thousand
//
// XXX: not guarding against division by zero; might see some NaNs or Infinitys.
var result = {
total: Math.round(counts.total / 1000) * 1000,
google: _round(counts.google / counts.total),
yahoo: _round(counts.yahoo / counts.total),
bing: _round(counts.bing / counts.total),
amazon: _round(counts.amazon/ counts.total)
};
return Promise.resolve(result);
}
var send = function(data) {
// JSONify the data, if necessary (does telemetry do this?)
// ship down using telemetry libs
};
var onError = function(err) {
// TODO: what's the right way to handle errors here?
console.log(err);
}
PlacesUtils.promiseDBConnection()
.then(getGoogleCount, onError)
.then(saveCount.bind(null, 'google'), onError)
.then(PlacesUtils.promiseDBConnection, onError)
.then(getYahooCount, onError)
.then(saveCount.bind(null, 'yahoo'), onError)
.then(PlacesUtils.promiseDBConnection, onError)
.then(getAmazonCount, onError)
.then(saveCount.bind(null, 'amazon'), onError)
.then(PlacesUtils.promiseDBConnection, onError)
.then(getTotalCount, onError)
.then(saveCount.bind(null, 'total'), onError)
.then(summarize, onError)
.then(send, onError);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment