Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
1958 lines
61 KiB
JavaScript
Executable file
1958 lines
61 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
/* exported SyncBrowserDB */
|
|
/* global Browser */
|
|
/* global Awesomescreen */
|
|
/* global IDBDatabaseException */
|
|
/* global IDBKeyRange */
|
|
|
|
const DBOS_PLACES = 'sync_places';
|
|
const DBOS_VISITS = 'sync_visits';
|
|
const DBOS_ICONS = 'sync_icons';
|
|
const DBOS_BOOKMARKS = 'sync_bookmarks';
|
|
var idb = window.indexedDB;
|
|
|
|
/**
|
|
* Provide access to bookmarks, topsites, and history in IndexedDB.
|
|
* @namespace SyncBrowserDB
|
|
*/
|
|
var SyncBrowserDB = {
|
|
/**
|
|
* How long is a icon expired in database in miliseconds.
|
|
* Default to 1 day.
|
|
*/
|
|
DEFAULT_ICON_EXPIRATION: 86400000, // One day
|
|
DEFAULT_TYPE_HISTORY: 'History',
|
|
DEFAULT_TYPE_BOOKMARK: 'Bookmark',
|
|
/**
|
|
* Maximum icon file size allowed.
|
|
* Default to 100kB.
|
|
*/
|
|
MAX_ICON_SIZE: 102400, // 100kB
|
|
variantObserver: null,
|
|
browserTitle: null,
|
|
|
|
/**
|
|
* Initialization. Open a database.
|
|
*/
|
|
init: function browserDB_init() {
|
|
this.db.open();
|
|
},
|
|
|
|
/**
|
|
* Add a DBOS_PLACES entry for the uri.
|
|
* @param {String} uri The uri to be added
|
|
* @param {Function} callback Runs when it finishs
|
|
*/
|
|
addPlace: function browserDB_addPlace(uri, callback) {
|
|
this.db.placeMaxCheck(uri, (function() {
|
|
this.db.createPlace(uri, callback);
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Add a raw history entry to DBOS_PLACES store.
|
|
* @param {String} history The history to be added
|
|
* @param {Function} callback Runs when it finishs
|
|
*/
|
|
updateRawHistory: function browserDB_updateRawHistory(history, callback) {
|
|
this.db.createRawHistory(history, callback);
|
|
},
|
|
|
|
/**
|
|
* Get a place by URI from DBOS_PLACES object store.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Function} callback Invoked with an icon object as argument on
|
|
* success. Invoked without arguments on error.
|
|
*/
|
|
getPlace: function browserDB_getPlace(uri, callback) {
|
|
this.db.getPlace(uri, callback);
|
|
},
|
|
|
|
/**
|
|
* Save the current time of the visit and update frequency (view count).
|
|
* @param {String} uri A visited URI to be saved
|
|
* @param {Function} callback Runs on frequency (view count) updated
|
|
*/
|
|
addVisit: function browserDB_addVisit(uri, callback) {
|
|
|
|
var urlTitle = uri;
|
|
if(SyncBrowserDB.browserTitle) {
|
|
urlTitle = SyncBrowserDB.browserTitle;
|
|
}
|
|
|
|
var visit = {
|
|
uri: uri,
|
|
title: urlTitle,
|
|
timestamp: new Date().getTime()
|
|
};
|
|
this.addPlace(uri, (function() {
|
|
this.db.visitMaxCheck(uri, (function() {
|
|
this.db.saveVisit(visit, (function() {
|
|
this.updateFrecency(uri, callback);
|
|
}).bind(this));
|
|
}).bind(this));
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Remove visit to the oldest of URL.
|
|
* @param {String} uri A visited URI to be saved
|
|
* @param {Function} callback Runs on topsite delete
|
|
*/
|
|
oldVisitDelete: function browserDB_oldVisitDelete(uri, callback) {
|
|
this.removeHistory(uri,callback);
|
|
},
|
|
|
|
/**
|
|
* Update the visit(title) of the specified URI,
|
|
* @param {String} uri A visited URI to be saved
|
|
* @param {String} title A visited title to be saved
|
|
* @param {Function} callback Runs on frequency (view count) updated
|
|
*/
|
|
updateVisit: function browserDB_updateVisit(uri, title, callback) {
|
|
var visit = {
|
|
uri: uri,
|
|
title: title,
|
|
timestamp: new Date().getTime()
|
|
};
|
|
this.db.visitMaxCheck(uri, (function() {
|
|
this.db.saveVisit(visit, callback);
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Update the frequency(view count) of the specified URI,
|
|
* if the URI has been visited.
|
|
* @param {String} uri The URI to be updated
|
|
* @param {Function} callback Runs if the URI is the start page or
|
|
* the update process is successful
|
|
*/
|
|
updateFrecency: function browserDB_updateFrecency(uri, callback) {
|
|
this.db.updatePlaceFrecency(uri, callback);
|
|
},
|
|
|
|
/**
|
|
* Update a screenshot by URI if the URI is in top sites.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Blob} screenshot A webpage screenshot taken using
|
|
* HTMLIFrameElement.getScreenshot
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updateScreenshot: function place_updateScreenshot(uri, screenshot, callback) {
|
|
var maximum = Browser.MAX_TOPSITE_LIST;
|
|
this.db.getPlaceUrisByFrecency(maximum + 1, (function(topSites) {
|
|
var runnerUp;
|
|
// Get the site that isn't quite a top site, if there is one
|
|
if (topSites.length > maximum) {
|
|
runnerUp = topSites.pop();
|
|
}
|
|
|
|
// If uri is not one of the top sites, don't store the screenshot
|
|
if (topSites.indexOf(uri) == -1) {
|
|
return;
|
|
}
|
|
|
|
this.db.updatePlaceScreenshot(uri, screenshot);
|
|
|
|
// If more top sites than we need screenshots, expire old screenshot
|
|
if (runnerUp) {
|
|
this.db.updatePlaceScreenshot(runnerUp, null);
|
|
}
|
|
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Add a bookmark into database.
|
|
* @param {String} data New bookmark record
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
addBookmark: function browserDB_addBookmark(data, callback) {
|
|
data.timestamp = data.timestamp || new Date().getTime();
|
|
if (data.type === 'bookmark') {
|
|
this.addPlace(data.bmkUri, (function() {
|
|
this.db.saveBookmark(data, callback);
|
|
}).bind(this));
|
|
} else {
|
|
this.db.saveBookmark(data, callback);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get a bookmark by an indexes object from database.
|
|
* @param {String} indexes Indexes Object query parameter. The parameters
|
|
* can be id, bmkUri, or parentid.
|
|
* @param {Function} callback Runs with a bookmark object on success. Runs
|
|
* without arguments on error.
|
|
*/
|
|
getBookmark: function browserDB_getBookmark(indexes, callback) {
|
|
const FXSYNCID_LEN = 12;
|
|
if (typeof indexes === 'string') {
|
|
this.db.getBookmark(indexes, callback);
|
|
} else if (indexes.id) {
|
|
this.db.getBookmark(indexes.id, callback);
|
|
} else if (indexes.bmkUri) {
|
|
this.db.getBookmarkByUri(indexes.bmkUri, callback);
|
|
} else if (indexes.parentid) {
|
|
this.db.getBookmark(indexes.parentid, folder => {
|
|
if (folder && folder.type === 'folder' && folder.children) {
|
|
this.db.getBookmarkByParentId(indexes.parentid, list => {
|
|
var children = folder.children;
|
|
var result = [];
|
|
for (var i = 0; i < children.length; i++) {
|
|
for (var j = 0; j < list.length; j++) {
|
|
var oriId = list[j].id;
|
|
// Append the reduntant underline to match the ID from Syncto.
|
|
var id = (oriId + '____________').substring(0, FXSYNCID_LEN);
|
|
if (children[i] === id) {
|
|
result.push(list[j]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
callback(result);
|
|
});
|
|
} else {
|
|
this.db.getBookmarkByParentId(indexes.parentid, callback);
|
|
}
|
|
});
|
|
} else {
|
|
callback(null);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get all bookmarks.
|
|
* @param {Function} callback Runs on success with an array of bookmarks
|
|
*/
|
|
getBookmarks: function browserDB_getBookmarks(callback) {
|
|
this.db.getAllBookmarks(callback);
|
|
},
|
|
|
|
/**
|
|
* Delete a bookmark by ID
|
|
* @param {String} id ID
|
|
* @param {Function} callback
|
|
*/
|
|
removeBookmark: function browserDB_removeBookmark(id, callback) {
|
|
this.db.deleteBookmark(id, (function() {
|
|
this.db.deleteIconUrl(id, this.DEFAULT_TYPE_BOOKMARK, callback);
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Get history by timestamp range at (start <= record.timestamp <= end)
|
|
* @param {Number} start Start timestamp
|
|
* @param {Number} end End timestamp
|
|
* @param {Boolean} startEqual Include the record equaling start timestamp
|
|
* @param {Boolean} endEqual Include the record equaling end timestamp
|
|
* @param {Function} callback Runs on complete with an array of history
|
|
*/
|
|
getHistoryByTime: function browserDB_getHistoryByTime(start, end, startEqual,
|
|
endEqual, callback) {
|
|
this.db.getHistoryByTime(start, end, startEqual, endEqual, callback);
|
|
},
|
|
|
|
/**
|
|
* Get the timestamp of history range at these 4 combinations:
|
|
* (record.timestamp < timestamp) when direction == 'prev' && equal == false
|
|
* (record.timestamp <= timestamp) when direction == 'prev' && equal == true
|
|
* (record.timestamp > timestamp) when direction == 'next' && equal == false
|
|
* (record.timestamp >= timestamp) when direction == 'next' && equal == true
|
|
* @param {Number} ts The timestamp that you want to search by.
|
|
* @param {String} direction Cursor direction is the same with IndexedDB's.
|
|
* @param {Boolean} equal Want to include the record in the timestamp.
|
|
* @param {Function} callback Runs on complete with the previous/next
|
|
* timestamp of a history record.
|
|
*/
|
|
getHistoryTimestamp:
|
|
function browserDB_getHistoryTimestamp(ts, direction, equal, callback) {
|
|
this.db.getHistoryTimestamp(ts, direction, equal, callback);
|
|
},
|
|
|
|
/**
|
|
* Delete a history by URI
|
|
* @param {String} uri URI
|
|
* @param {Function} callback
|
|
*/
|
|
removeHistory: function browserDB_removeHistory(uri, callback) {
|
|
this.db.deleteHistory(uri, (function() {
|
|
this.db.deleteIconUrl(uri, this.DEFAULT_TYPE_HISTORY, callback);
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Delete a topste by URI
|
|
* @param {String} uri URI
|
|
* @param {Function} callback
|
|
*/
|
|
removeTopsite: function browserDB_removeTopsite(uri, callback) {
|
|
this.db.deleteTopsite(uri, callback);
|
|
},
|
|
/**
|
|
* Add/Update a bookmark in database.
|
|
* @param {String} data New bookmark record
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updateBookmark: function browserDB_updateBookmark(data, callback) {
|
|
this.db.getBookmark(data.id, (function(bookmark) {
|
|
if (bookmark) {
|
|
this.db.saveBookmark(data, callback);
|
|
} else {
|
|
this.addBookmark(data, callback);
|
|
}
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Add/Update a bookmark in database without updating places.
|
|
* @param {String} data New bookmark record
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updateRawBookmark: function browserDB_updateBookmark(data, callback) {
|
|
this.db.saveBookmark(data, callback);
|
|
},
|
|
|
|
/**
|
|
* Create/Update page title in database.
|
|
* @param {String} uri URI query parameter
|
|
* @param {String} title Page title
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
setPageTitle: function browserDB_setPageTitle(uri, title, callback) {
|
|
SyncBrowserDB.browserTitle = title;
|
|
if(!title){
|
|
title = uri;
|
|
}
|
|
this.db.placeMaxCheck(uri, (function() {
|
|
this.db.updatePlaceTitle(uri, title, (function() {
|
|
this.updateVisit(uri, title, callback);
|
|
}).bind(this));
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Save iconUri in DBOS_PLACES object store in database.
|
|
* @param {String} uri URI
|
|
* @param {String} iconUri Base64 encoded image string
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
setPageIconUri: function browserDB_setPageIconUri(uri, iconUri, callback) {
|
|
this.db.updatePlaceIconUri(uri, iconUri, callback);
|
|
},
|
|
|
|
/**
|
|
* Create a DBOS_ICONS object store entry and save it in database.
|
|
* @param {String} iconUri Base64 encoded image string
|
|
* @param {Blob} data Image Blob
|
|
* @param {Function} callback Runs on success
|
|
* @param {Boolean} failed Specify if the image Blob data is successfully
|
|
* saved
|
|
*/
|
|
setIconData:
|
|
function browserDB_setIconData(uri, iconUri, data, callback, failed) {
|
|
var now = new Date().valueOf();
|
|
var iconEntry = {
|
|
uri: uri,
|
|
iconUri: iconUri,
|
|
data: data,
|
|
expiration: now + this.DEFAULT_ICON_EXPIRATION,
|
|
failed: failed
|
|
};
|
|
this.db.saveIcon(iconEntry, callback);
|
|
},
|
|
|
|
/**
|
|
* Load the image icon and save it to IndexedDB.
|
|
* @param {String} uri URI
|
|
* @param {String} iconUri Base64 encoded image string
|
|
* @param {Function} callback Run on saving to IndexedDB successful
|
|
*/
|
|
setAndLoadIconForPage: function browserDB_setAndLoadIconForPage(uri,
|
|
iconUri, callback) {
|
|
this.setPageIconUri(uri, iconUri);
|
|
// If icon is not already cached or has expired, load it
|
|
var now = new Date().valueOf();
|
|
this.db.getIcon(uri, iconUri, (function(icon) {
|
|
if (icon && icon.expiration > now) {
|
|
//return;
|
|
}
|
|
var xhr = new XMLHttpRequest({mozSystem: true});
|
|
xhr.open('GET', iconUri, true);
|
|
xhr.responseType = 'blob';
|
|
xhr.addEventListener('load', (function() {
|
|
// Check icon was successfully downloded
|
|
// 0 is due to https://bugzilla.mozilla.org/show_bug.cgi?id=716491
|
|
if (!(xhr.status === 200 || xhr.status === 0)) {
|
|
//this.setIconData(iconUri, null, callback, true);
|
|
this.setIconData(uri, Awesomescreen.DEFAULT_FAVICON,
|
|
null, callback, true);
|
|
console.error('error downloading icon: ' + xhr.status);
|
|
return;
|
|
}
|
|
|
|
var blob = xhr.response;
|
|
// Check the file is served as an image and isn't too big
|
|
if (blob.type.split('/')[0] != 'image' ||
|
|
blob.size > this.MAX_ICON_SIZE) {
|
|
this.setIconData(uri, iconUri, null, callback, true);
|
|
console.error('Icon was not an image or was too big');
|
|
return;
|
|
}
|
|
|
|
// Only save the icon if it can be loaded as an image bigger than 0px
|
|
var img = document.createElement('img');
|
|
var src = window.URL.createObjectURL(blob);
|
|
img.src = src;
|
|
img.onload = (function() {
|
|
if (img.naturalWidth > 0) {
|
|
this.setIconData(uri, iconUri, blob, callback);
|
|
} else {
|
|
this.setIconData(uri, iconUri, null, callback, true);
|
|
console.error('Icon not saved because less than 1px wide');
|
|
}
|
|
window.URL.revokeObjectURL(src);
|
|
}).bind(this);
|
|
img.onerror = (function() {
|
|
this.setIconData(uri, iconUri, null, callback, true);
|
|
console.error('Icon not saved because can not be decoded');
|
|
window.URL.revokeObjectURL(src);
|
|
}).bind(this);
|
|
|
|
}).bind(this), false);
|
|
xhr.onerror = function getIconError() {
|
|
console.error('Error fetching icon');
|
|
};
|
|
xhr.send();
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Add a DBOS_PLACES entry of the URI.
|
|
* @param {String} uri The URI to be added in DB
|
|
* @param {String} title
|
|
* @param {Number} frequency View count of the specified URI
|
|
* @param {Function} callback Runs when it finishs
|
|
*/
|
|
addTopSite: function browserDB_addTopSite(uri, title, frequency, callback) {
|
|
this.addPlace(uri, (function() {
|
|
this.db.initPlaceFrecency(uri, title, frequency, callback);
|
|
}).bind(this));
|
|
},
|
|
|
|
/**
|
|
* Get top sites.
|
|
* @param {Number} maximum The maximum number of top sites to get
|
|
* @param {String} filter URI filter. Pass in null to ignore.
|
|
* @param {Function} callback Run on success with topsites array and filter
|
|
* as arguments.
|
|
*/
|
|
getTopSites: function browserDB_getTopSites(maximum, filter, callback) {
|
|
// Get the top 9 sites
|
|
this.db.getPlacesByFrecency(maximum, filter, callback);
|
|
},
|
|
|
|
/**
|
|
* Get default configured top sites.
|
|
* @param {Function} callback Run on success with default top sites array.
|
|
*/
|
|
getDefaultTopSites: function browserDB_getDefaultTopSites(callback) {
|
|
this.db.getDefaultPlaces(callback);
|
|
},
|
|
|
|
/**
|
|
* Get the latest history entries based on the maximum number of history.
|
|
* @param {Number} maxQuerySize The maximum number of history to get
|
|
* @param {Function} callback Run with array of history entries
|
|
*/
|
|
getHistory: function browserDB_getHistory(maxQuerySize, callback) {
|
|
// Just get the most recent 20 for now
|
|
var querySize = maxQuerySize ? maxQuerySize : Browser.MAX_HISTORY_LIST;
|
|
this.db.getHistory(querySize, callback);
|
|
},
|
|
|
|
/**
|
|
* Clear history and keep bookmarks.
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearHistory: function browserDB_clearHistory(callback) {
|
|
// Get a list of bookmarks
|
|
this.db.clearHistoryExcluding(callback);
|
|
|
|
},
|
|
|
|
clearBookmarks: function browserDB_clearBookmarks() {
|
|
return new Promise(resolve => {
|
|
this.db.clearBookmarks(resolve);
|
|
});
|
|
},
|
|
|
|
clearHistoryDeep: function browserDB_clearHistoryDeep() {
|
|
return Promise.all([
|
|
new Promise(this.db.clearVisits),
|
|
new Promise(this.db.clearPlaces),
|
|
new Promise(this.db.clearIcons)
|
|
]);
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* @memberOf SyncBrowserDB
|
|
* @namespace SyncBrowserDB.db
|
|
*/
|
|
SyncBrowserDB.db = {
|
|
_db: null,
|
|
START_PAGE_URI: document.location.protocol + '//' + document.location.host +
|
|
'/start.html',
|
|
/** Version of database being upgraded from */
|
|
upgradeFrom: -1,
|
|
|
|
/**
|
|
* Open a IndexedDB database with name as 'browser' and version as 7.
|
|
* @param {Function} callback The callback to be run on success
|
|
*/
|
|
open: function db_open(callback) {
|
|
const DB_VERSION = 7;
|
|
const DB_NAME = 'fxsync_browser';
|
|
var request = idb.open(DB_NAME, DB_VERSION);
|
|
|
|
request.onupgradeneeded = (function onUpgradeNeeded(e) {
|
|
console.log('Browser database upgrade needed, upgrading.');
|
|
this.upgradeFrom = e.oldVersion;
|
|
this._db = e.target.result;
|
|
this.upgrade();
|
|
}).bind(this);
|
|
|
|
request.onsuccess = (function onSuccess(e) {
|
|
this._db = e.target.result;
|
|
callback && callback();
|
|
}).bind(this);
|
|
|
|
request.onerror = (function onDatabaseError(e) {
|
|
console.error('Error opening browser database');
|
|
}).bind(this);
|
|
},
|
|
|
|
/**
|
|
* Create/Update object stores:
|
|
* places
|
|
* visits
|
|
* icons
|
|
* bookmarks
|
|
*/
|
|
upgrade: function db_upgrade() {
|
|
var db = this._db;
|
|
var upgradeFrom = this.upgradeFrom;
|
|
if (upgradeFrom < 1) {
|
|
var placesStore = db.createObjectStore(DBOS_PLACES, { keyPath: 'uri' });
|
|
// Index places by frecency
|
|
placesStore.createIndex('frecency', 'frecency', { unique: false });
|
|
var visitStore = db.createObjectStore(DBOS_VISITS, {
|
|
keyPath: 'uri' ,
|
|
autoIncrement: true
|
|
});
|
|
// Index visits by timestamp
|
|
visitStore.createIndex('timestamp', 'timestamp', { unique: false });
|
|
db.createObjectStore(DBOS_ICONS, { keyPath: 'uri' });
|
|
var bookmarkStore = db.createObjectStore(DBOS_BOOKMARKS, {
|
|
keyPath: 'id'
|
|
});
|
|
// Index bookmarks by timestamp
|
|
bookmarkStore.createIndex('timestamp', 'timestamp', { unique: false });
|
|
bookmarkStore.createIndex('bmkUri', 'bmkUri', { unique: false });
|
|
bookmarkStore.createIndex('parentid', 'parentid', { unique: false });
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Create a new DBOS_PLACES entry of the URI if there's none.
|
|
* @param {String} uri The uri to be inserted
|
|
* @param {Function} callback Runs when the entry exists or a new entry
|
|
* created
|
|
*/
|
|
createPlace: function db_createPlace(uri, callback) {
|
|
var title = uri;
|
|
if (SyncBrowserDB.browserTitle) {
|
|
title = SyncBrowserDB.browserTitle;
|
|
SyncBrowserDB.browserTitle = null;
|
|
}
|
|
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (place) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
return;
|
|
} else {
|
|
place = {
|
|
uri: uri,
|
|
title: title
|
|
};
|
|
}
|
|
|
|
var writeRequest = objectStore.add(place);
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess(event) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
writeRequest.onerror = function onError(event) {
|
|
console.error('error writing place');
|
|
};
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save place ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Create a new raw entry of the history if there's none.
|
|
* @param {String} history The history to be inserted
|
|
* @param {Function} callback Runs when the entry exists or a new entry
|
|
* created
|
|
*/
|
|
createRawHistory: function db_createRawHistory(history, callback) {
|
|
var transaction = this._db.transaction([DBOS_VISITS], 'readwrite');
|
|
var objectStore = transaction.objectStore(DBOS_VISITS);
|
|
var readRequest = objectStore.get(history.uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var existingPlace = event.target.result;
|
|
var writeRequest;
|
|
if (existingPlace) {
|
|
existingPlace.title = history.title;
|
|
existingPlace.timestamp = history.timestamp;
|
|
writeRequest = objectStore.put(history);
|
|
} else {
|
|
writeRequest = objectStore.add(history);
|
|
}
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess(event) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
writeRequest.onerror = function onError(event) {
|
|
console.error('error writing history');
|
|
};
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save history ', history);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Save an places object store entry in database
|
|
* @param {Object} places A visits entry
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
placeMaxCheck: function db_placeMaxCheck(uri, callback) {
|
|
var db = this._db;
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to count places');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var places = event.target.result;
|
|
if (places) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
} else {
|
|
//count check
|
|
var request = objectStore.count();
|
|
request.onsuccess = function onReadSuccess(event) {
|
|
var count = event.target.result;
|
|
if (count < Browser.MAX_TOPSITE_LIST) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
}else{
|
|
var transaction = db.transaction([DBOS_PLACES]);
|
|
var placesStore = transaction.objectStore(DBOS_PLACES);
|
|
var placesIndex = placesStore.index('frecency');
|
|
|
|
placesIndex.openCursor(null, 'next').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var places = cursor.value;
|
|
SyncBrowserDB.removeTopsite(places.uri, callback);
|
|
} else {
|
|
console.error('error get places');
|
|
}
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
request.onerror = function onReadError(event) {
|
|
console.error('error reading place');
|
|
};
|
|
}
|
|
};
|
|
|
|
readRequest.onerror = function onError(event) {
|
|
console.error('error writing places');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get a place by URI from DBOS_PLACES object store.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Function} callback Invoked with an icon object as argument on
|
|
* success. Invoked without arguments on error.
|
|
*/
|
|
getPlace: function db_getPlace(uri, callback) {
|
|
var db = this._db;
|
|
var request = db.transaction(DBOS_PLACES).objectStore(DBOS_PLACES).get(uri);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
callback(event.target.result);
|
|
};
|
|
|
|
request.onerror = function onError(event) {
|
|
if (event.target.errorCode == IDBDatabaseException.NOT_FOUND_ERR) {
|
|
callback();
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Save an visits object store entry in database
|
|
* @param {Object} visit A visits entry
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
visitMaxCheck: function db_visitMaxCheck(uri, callback) {
|
|
var db = this._db;
|
|
var transaction = this._db.transaction([DBOS_VISITS], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to count visit');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_VISITS);
|
|
var readRequest = objectStore.get(uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var visits = event.target.result;
|
|
if (visits) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
} else {
|
|
//count check
|
|
var request = objectStore.count();
|
|
request.onsuccess = function onReadSuccess(event) {
|
|
var count = event.target.result;
|
|
if (count < Browser.MAX_HISTORY_LIST) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
}else{
|
|
var transaction = db.transaction([DBOS_VISITS]);
|
|
var visitsStore = transaction.objectStore(DBOS_VISITS);
|
|
var visitsIndex = visitsStore.index('timestamp');
|
|
|
|
visitsIndex.openCursor(null, 'next').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var visit = cursor.value;
|
|
SyncBrowserDB.oldVisitDelete(visit.uri, callback);
|
|
} else {
|
|
console.error('error get visits');
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
request.onerror = function onReadError(event) {
|
|
console.error('error reading visit');
|
|
};
|
|
}
|
|
};
|
|
|
|
readRequest.onerror = function onError(event) {
|
|
console.error('error writing visit');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Save an visits object store entry in database
|
|
* @param {Object} visit A visits entry
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
saveVisit: function db_saveVisit(visit, callback) {
|
|
var transaction = this._db.transaction([DBOS_VISITS], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save visit');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_VISITS);
|
|
var readRequest = objectStore.get(visit.uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var visits = event.target.result;
|
|
if (visits) {
|
|
if(( visits.title != visit.title ) &&
|
|
( visits.title == visit.uri )) {
|
|
visits.title = visit.title;
|
|
visits.timestamp = visit.timestamp;
|
|
} else {
|
|
visits.timestamp = visit.timestamp;
|
|
}
|
|
} else {
|
|
//TODO num check
|
|
visits = {
|
|
uri: visit.uri,
|
|
title: visit.title,
|
|
timestamp: visit.timestamp
|
|
};
|
|
}
|
|
|
|
var writeRequest = objectStore.put(visits);
|
|
writeRequest.onsuccess = function onWriteSuccess(event) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
writeRequest.onerror = function onError(event) {
|
|
console.error('error writing place');
|
|
};
|
|
};
|
|
|
|
readRequest.onerror = function onReadError(event) {
|
|
console.error('error reading place');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get latest visits entries.
|
|
* @param {Number} maximum Maximum number of history entries to get
|
|
* @param {Function} callback Run with array of history entries
|
|
*/
|
|
getHistory: function db_getHistory(maximum, callback) {
|
|
var history = [];
|
|
var db = this._db;
|
|
|
|
function makeVisitProcessor(visit) {
|
|
return function(e) {
|
|
var object = e.target.result;
|
|
if(object){
|
|
visit.iconUri = object.iconUri;
|
|
}else{
|
|
visit.iconUri = Awesomescreen.DEFAULT_FAVICON;
|
|
}
|
|
history.push(visit);
|
|
};
|
|
}
|
|
|
|
var transaction = db.transaction([DBOS_VISITS, DBOS_ICONS]);
|
|
var visitsStore = transaction.objectStore(DBOS_VISITS);
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
var visitsIndex = visitsStore.index('timestamp');
|
|
|
|
visitsIndex.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor && history.length < maximum) {
|
|
var visit = cursor.value;
|
|
objectStore.get(visit.uri).onsuccess = makeVisitProcessor(visit);
|
|
cursor.continue();
|
|
} else {
|
|
callback(history);
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get default configured places entries. This is possibly broken. Need
|
|
* confirmation.
|
|
* @param {Function} callback Run on success with default top sites array.
|
|
*/
|
|
getDefaultPlaces: function db_defaultPlaces(callback) {
|
|
var topSites = [];
|
|
var transaction = this._db.transaction(DBOS_PLACES);
|
|
var placesStore = transaction.objectStore(DBOS_PLACES);
|
|
var frecencyIndex = placesStore.index('frecency');
|
|
frecencyIndex.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor && cursor.value && cursor.value.frecency < 0) {
|
|
topSites.push(cursor.value);
|
|
cursor.continue();
|
|
} else {
|
|
callback(topSites);
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get places entries ordered by frequency(view count).
|
|
* @param {Number} maximum The maximum number of top sites to get
|
|
* @param {String} filter URI filter. Pass in null to ignore.
|
|
* @param {Function} callback Run on success with topsites array and filter
|
|
* as arguments.
|
|
*/
|
|
getPlacesByFrecency: function db_placesByFrecency(maximum, filter, callback) {
|
|
var topSites = [];
|
|
var self = this;
|
|
var transaction = self._db.transaction(DBOS_PLACES);
|
|
var placesStore = transaction.objectStore(DBOS_PLACES);
|
|
var frecencyIndex = placesStore.index('frecency');
|
|
frecencyIndex.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor && topSites.length < maximum) {
|
|
var place = cursor.value;
|
|
var matched = false;
|
|
if (filter) {
|
|
matched = self.matchesFilter(place.uri, filter) ||
|
|
self.matchesFilter(place.title, filter);
|
|
}
|
|
if (matched || !filter) {
|
|
if(cursor.value.frecency >= 1){
|
|
topSites.push(cursor.value);
|
|
}
|
|
}
|
|
cursor.continue();
|
|
} else {
|
|
callback(topSites, filter);
|
|
}
|
|
};
|
|
},
|
|
/**
|
|
* Check if the URI matches the regular expression filter.
|
|
* @param {String} uri
|
|
* @param {String} filter
|
|
* @returns {Boolean}
|
|
*/
|
|
matchesFilter: function db_matchesFilter(uri, filter) {
|
|
return uri.match(new RegExp(filter, 'i')) !== null;
|
|
},
|
|
|
|
/**
|
|
* Get places URIs ordered by frequency(view count).
|
|
* @param {Number} maximum The maximum number of URIs to get
|
|
* @param {Function} callback Run on success with a URI array
|
|
*/
|
|
getPlaceUrisByFrecency: function db_getPlaceUrisByFrecency(maximum,
|
|
callback) {
|
|
var topSites = [];
|
|
var transaction = this._db.transaction(DBOS_PLACES);
|
|
var placesStore = transaction.objectStore(DBOS_PLACES);
|
|
var frecencyIndex = placesStore.index('frecency');
|
|
frecencyIndex.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor && topSites.length < maximum) {
|
|
topSites.push(cursor.value.uri);
|
|
cursor.continue();
|
|
} else {
|
|
callback(topSites);
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Clear places object store.
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearPlaces: function db_clearPlaces(callback) {
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_PLACES, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear places');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var request = objectStore.clear();
|
|
request.onsuccess = function onSuccess() {
|
|
callback();
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing places object store');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Clear visits object store.
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearVisits: function db_clearVisits(callback) {
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_VISITS, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear visits');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_VISITS);
|
|
objectStore.openCursor().onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var visit = cursor.value;
|
|
SyncBrowserDB.db.deleteIconUrl(visit.uri,
|
|
SyncBrowserDB.DEFAULT_TYPE_HISTORY, null);
|
|
cursor.continue();
|
|
}else{
|
|
var request = objectStore.clear();
|
|
request.onsuccess = function onSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing visits object store');
|
|
};
|
|
}
|
|
};
|
|
|
|
objectStore.openCursor(null, 'prev').onerror =
|
|
function onError(e) {
|
|
console.error('Error Delete visits Icon object store');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Clear icons object store.
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearIcons: function db_clearIcons(callback) {
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_ICONS, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear icons');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
var request = objectStore.clear();
|
|
request.onsuccess = function onSuccess() {
|
|
callback();
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing icons object store');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Clear bookmarks object store.
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearBookmarks: function db_clearBookmarks(callback) {
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_BOOKMARKS, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear bookmarks');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
var request = objectStore.clear();
|
|
request.onsuccess = function onSuccess() {
|
|
callback();
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing bookmarks object store');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Save an icon object store entry in database
|
|
* @param {Object} iconEntry
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
saveIcon: function db_saveIcon(iconEntry, callback) {
|
|
var transaction = this._db.transaction([DBOS_ICONS], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save icon');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
var request = objectStore.put(iconEntry);
|
|
|
|
request.onsuccess = function onSuccess(e) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
request.onerror = function onError(e) {
|
|
console.error('Error while saving icon');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get a icon by iconUri from DBOS_ICONS object store.
|
|
* @param {String} iconUri Base64 encoded icon image string
|
|
* @param {Function} callback Invoked with an icon object as argument on
|
|
* success. Invoked without arguments on error.
|
|
*/
|
|
getIcon: function db_getIcon(uri, iconUri, callback) {
|
|
var request = this._db.transaction(DBOS_ICONS).objectStore(DBOS_ICONS).
|
|
get(uri);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
callback(event.target.result);
|
|
};
|
|
|
|
request.onerror = function onError(event) {
|
|
if (event.target.errorCode == IDBDatabaseException.NOT_FOUND_ERR) {
|
|
callback();
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Save a bookmarks object store entry in database
|
|
* @param {Object} bookmark A bookmarks object store entry
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
saveBookmark: function db_saveBookmark(bookmark, callback) {
|
|
var transaction = this._db.transaction([DBOS_BOOKMARKS], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save bookmark');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
|
|
var request = objectStore.put(bookmark);
|
|
|
|
request.onsuccess = function onSuccess(e) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
request.onerror = function onError(e) {
|
|
console.error('Error while saving bookmark');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get a bookmark by ID from database.
|
|
* @param {String} id ID
|
|
* @param {Function} callback Runs with a bookmark object on success. Runs
|
|
* without arguments on error.
|
|
*/
|
|
getBookmark: function db_getBookmark(id, callback) {
|
|
var request = this._db.transaction(DBOS_BOOKMARKS).
|
|
objectStore(DBOS_BOOKMARKS).get(id);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
callback(event.target.result);
|
|
};
|
|
|
|
request.onerror = function onError(event) {
|
|
if (event.target.errorCode == IDBDatabaseException.NOT_FOUND_ERR) {
|
|
callback();
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get a bookmark by URI from database.
|
|
* @param {String} uri URI
|
|
* @param {Function} callback Runs with a bookmark object on success. Runs
|
|
* without arguments on error.
|
|
*/
|
|
getBookmarkByUri: function db_getBookmarkByUri(uri, callback) {
|
|
var request = this._db.transaction(DBOS_BOOKMARKS).
|
|
objectStore(DBOS_BOOKMARKS).index('bmkUri').get(uri);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
callback(event.target.result);
|
|
};
|
|
|
|
request.onerror = function onError(event) {
|
|
if (event.target.errorCode == IDBDatabaseException.NOT_FOUND_ERR) {
|
|
callback();
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get a bookmark by Parent ID from database.
|
|
* @param {String} parentId Parent ID
|
|
* @param {Function} callback Runs with a bookmark object on success. Runs
|
|
* without arguments on error.
|
|
*/
|
|
getBookmarkByParentId: function db_getBookmarkByParentId(parentId, callback) {
|
|
var records = [];
|
|
var db = this._db;
|
|
|
|
function fetchIconUri(data) {
|
|
return new Promise(resolve => {
|
|
if(data.type !== 'bookmark') {
|
|
resolve(data);
|
|
} else {
|
|
var iconRequest = iconsStore.get(data.bmkUri);
|
|
iconRequest.onsuccess = function(e) {
|
|
var icon = e.target.result;
|
|
if(icon && icon.iconUri){
|
|
data.iconUri = icon.iconUri;
|
|
} else {
|
|
data.iconUri = Awesomescreen.DEFAULT_FAVICON;
|
|
}
|
|
resolve(data);
|
|
};
|
|
iconRequest.onerror = function(e) {
|
|
resolve(data);
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
var transaction = db.transaction([DBOS_BOOKMARKS, DBOS_ICONS]);
|
|
var bookmarksStore =
|
|
transaction.objectStore(DBOS_BOOKMARKS).index('parentid');
|
|
var iconsStore = transaction.objectStore(DBOS_ICONS);
|
|
|
|
bookmarksStore.openCursor(parentId, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
fetchIconUri(cursor.value).then(bookmark => {
|
|
records.push(bookmark);
|
|
});
|
|
cursor.continue();
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_bookmarkTransactionComplete() {
|
|
callback(records);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Delete a bookmark by ID from database.
|
|
* @param {String} id ID
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
deleteBookmark: function db_deleteBookmark(id, callback) {
|
|
var transaction = this._db.transaction([DBOS_BOOKMARKS], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to delete bookmark');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
var request = objectStore.delete(id);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
request.onerror = function onError(e) {
|
|
console.error('Error while deleting bookmark');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Delete a history by URI from database.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
deleteHistory: function db_deleteHistory(uri, callback) {
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_VISITS, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear visits');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_VISITS);
|
|
var request = objectStore.delete(uri);
|
|
request.onsuccess = function onSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing visits object store');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Delete a iconUrl by URI from database.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
deleteIconUrl: function db_deleteIconUrl(uri, type, callback) {
|
|
|
|
var transaction = null;
|
|
var objectStore = null;
|
|
//In the case of history, it searches the same URL is to bookmark
|
|
if(type == SyncBrowserDB.DEFAULT_TYPE_HISTORY){
|
|
transaction = this._db.transaction([DBOS_BOOKMARKS], 'readwrite');
|
|
objectStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
}else{
|
|
transaction = this._db.transaction([DBOS_VISITS], 'readwrite');
|
|
objectStore = transaction.objectStore(DBOS_VISITS);
|
|
}
|
|
|
|
var readRequest = objectStore.get(uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var objList = event.target.result;
|
|
if (objList) {
|
|
if(callback){
|
|
callback();
|
|
}
|
|
}else{
|
|
|
|
var db = SyncBrowserDB.db._db;
|
|
var transaction = db.transaction(DBOS_ICONS, 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to clear icons');
|
|
};
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
var request = objectStore.delete(uri);
|
|
request.onsuccess = function onSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
request.onerror = function onError(e) {
|
|
console.error('Error clearing icons object store');
|
|
};
|
|
}
|
|
};
|
|
|
|
readRequest.onerror = function onError(e) {
|
|
console.error('Error while read bookamrk or history');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Delete a topsite by URI from database.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
deleteTopsite: function db_deleteTopsite(uri, callback) {
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to delete topsite');
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var request = objectStore.delete(uri);
|
|
|
|
request.onsuccess = function onSuccess(event) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
request.onerror = function onError(e) {
|
|
console.error('Error while deleting topsite');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get bookmarks
|
|
* @param {Function} callback Runs on complete with an array of bookmarks
|
|
*/
|
|
getAllBookmarks: function db_getAllBookmarks(callback) {
|
|
var bookmarks = [];
|
|
var db = this._db;
|
|
var icons;
|
|
|
|
function makeBookmarkProcessor(bookmark) {
|
|
return function(e) {
|
|
icons = e.target.result;
|
|
if(icons){
|
|
if(icons.iconUri){
|
|
bookmark.iconUri = icons.iconUri;
|
|
|
|
}else{
|
|
bookmark.iconUri = Awesomescreen.DEFAULT_FAVICON;
|
|
}
|
|
}
|
|
bookmarks.push(bookmark);
|
|
};
|
|
}
|
|
|
|
var transaction = db.transaction([DBOS_BOOKMARKS, DBOS_ICONS]);
|
|
var bookmarksStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
var bookmarksIndex = bookmarksStore.index('timestamp');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
bookmarksIndex.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var bookmark = cursor.value;
|
|
objectStore.get(bookmark.id).onsuccess =
|
|
makeBookmarkProcessor(bookmark);
|
|
cursor.continue();
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_bookmarkTransactionComplete() {
|
|
callback(bookmarks);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get all URIs of bookmarks
|
|
* @param {Function} callback Runs on complete with an array of URIs
|
|
*/
|
|
getAllBookmarkUris: function db_getAllBookmarks(callback) {
|
|
var uris = [];
|
|
var db = this._db;
|
|
|
|
var transaction = db.transaction(DBOS_BOOKMARKS);
|
|
var objectStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
|
|
objectStore.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
uris.push(cursor.value.bmkUri);
|
|
cursor.continue();
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_bookmarkTransactionComplete() {
|
|
callback(uris);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get history by timestamp range at (start <= record.timestamp <= end)
|
|
* @param {Number} start Start timestamp
|
|
* @param {Number} end End timestamp
|
|
* @param {Boolean} startEqual Include the record equaling start timestamp
|
|
* @param {Boolean} endEqual Include the record equaling end timestamp
|
|
* @param {Function} callback Runs on complete with an array of history
|
|
*/
|
|
getHistoryByTime:
|
|
function db_getHistoryByTime(start, end, startEqual, endEqual, callback) {
|
|
var history = [];
|
|
var db = this._db;
|
|
|
|
function makeVisitProcessor(visit) {
|
|
return function(e) {
|
|
var object = e.target.result;
|
|
if(object){
|
|
visit.iconUri = object.iconUri;
|
|
}else{
|
|
visit.iconUri = Awesomescreen.DEFAULT_FAVICON;
|
|
}
|
|
history.push(visit);
|
|
};
|
|
}
|
|
|
|
var transaction = db.transaction([DBOS_VISITS, DBOS_ICONS]);
|
|
var visitsStore = transaction.objectStore(DBOS_VISITS);
|
|
var objectStore = transaction.objectStore(DBOS_ICONS);
|
|
var visitsIndex = visitsStore.index('timestamp');
|
|
var keyRange = IDBKeyRange.bound(start, end, !startEqual, !endEqual);
|
|
|
|
visitsIndex.openCursor(keyRange, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var visit = cursor.value;
|
|
objectStore.get(visit.uri).onsuccess = makeVisitProcessor(visit);
|
|
cursor.continue();
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_historyTransactionComplete() {
|
|
callback(history);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Get the timestamp of history range at
|
|
* (record.timestamp < timestamp) when direction == 'prev' && equal == false
|
|
* (record.timestamp <= timestamp) when direction == 'prev' && equal == true
|
|
* (record.timestamp > timestamp) when direction == 'next' && equal == false
|
|
* (record.timestamp >= timestamp) when direction == 'next' && equal == true
|
|
* @param {Number} timestamp The timestamp that you want to search by.
|
|
* @param {String} direction Cursor direction is the same with IndexedDB's.
|
|
* @param {Boolean} equal Want to include the record in the timestamp.
|
|
* @param {Function} callback Runs on complete with the previous/next
|
|
* timestamp of a history record.
|
|
*/
|
|
getHistoryTimestamp:
|
|
function db_getHistoryTimestamp(timestamp, direction, equal, callback) {
|
|
const DIRECTION_TYPE = ['next', 'nextunique', 'prev', 'prevunique'];
|
|
if (!DIRECTION_TYPE.some(e => e === direction)) {
|
|
console.error('Incorrect direction type:', direction);
|
|
return ;
|
|
}
|
|
var db = this._db;
|
|
var lastestTimeStampInRange = null;
|
|
|
|
var transaction = db.transaction([DBOS_VISITS]);
|
|
var visitsStore = transaction.objectStore(DBOS_VISITS);
|
|
var visitsIndex = visitsStore.index('timestamp');
|
|
var keyRange;
|
|
if (direction === 'prev' || direction === 'prevunique') {
|
|
keyRange = IDBKeyRange.upperBound(timestamp, !equal);
|
|
} else {
|
|
keyRange = IDBKeyRange.lowerBound(timestamp, !equal);
|
|
}
|
|
|
|
visitsIndex.openCursor(keyRange, direction).onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
lastestTimeStampInRange = cursor.key;
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_historyTransactionComplete() {
|
|
callback(lastestTimeStampInRange);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Init the frequency(view count) of the specified URI,
|
|
* if the URI is in DBOS_PLACES.
|
|
* @param {String} uri The URI to be init
|
|
* @param {String} title
|
|
* @param {Number} frequency View count of the specified URI
|
|
* @param {Function} callback Runs when init finishs
|
|
*/
|
|
initPlaceFrecency: function db_initPlaceFrecency(uri, title,
|
|
frecency, callback) {
|
|
// Don't assign frecency to the start page
|
|
if (uri == this.START_PAGE_URI) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
return;
|
|
}
|
|
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (!place || (place.frecency && place.frecency > frecency)) {
|
|
return;
|
|
}
|
|
|
|
place.title = title;
|
|
place.frecency = frecency;
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while saving new frecency for ' + uri);
|
|
};
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to update place: ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Update the frequency(view count) of the specified URI,
|
|
* if the URI is in DBOS_PLACES.
|
|
* @param {String} uri The URI to be updated
|
|
* @param {Function} callback Runs if the URI is the start page or
|
|
* the update process is successful
|
|
*/
|
|
updatePlaceFrecency: function db_updatePlaceFrecency(uri, callback) {
|
|
// Don't assign frecency to the start page
|
|
if (uri == this.START_PAGE_URI) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
return;
|
|
}
|
|
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (!place) {
|
|
return;
|
|
}
|
|
|
|
if (!place.frecency) {
|
|
place.frecency = 1;
|
|
} else {
|
|
if (place.frecency < 0) {
|
|
place.frecency = 0;
|
|
}
|
|
// currently just frequency
|
|
place.frecency++;
|
|
}
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while saving new frecency for ' + uri);
|
|
};
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to update place: ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Set the frequency(view count) to null of the specified URI,
|
|
* if the URI is in DBOS_PLACES.
|
|
* @param {String} uri The URI to be reset
|
|
* @param {Function} callback Runs if the reset process is successful
|
|
*/
|
|
resetPlaceFrecency: function db_resetPlaceFrecency(uri, callback) {
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (!place) {
|
|
return;
|
|
}
|
|
|
|
place.frecency = 0;
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while resetting frecency for ' + uri);
|
|
};
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to reset frecency: ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Create/Update iconUri in DBOS_PLACES object store.
|
|
* @param {String} uri URI query parameter
|
|
* @param {String} iconUri Base64 encoded image string
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updatePlaceIconUri: function db_updatePlaceIconUri(uri, iconUri, callback) {
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (place) {
|
|
place.iconUri = iconUri;
|
|
} else {
|
|
place = {
|
|
uri: uri,
|
|
title: uri,
|
|
iconUri: iconUri
|
|
};
|
|
}
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while saving iconUri for ' + uri);
|
|
};
|
|
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save iconUri for ' +
|
|
uri);
|
|
};
|
|
|
|
transaction.onsuccess = function dbTransactionSuccess(e) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Create/Update title in DBOS_PLACES object store.
|
|
* @param {String} uri URI query parameter
|
|
* @param {String} title Page title
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updatePlaceTitle: function db_updatePlaceTitle(uri, title, callback) {
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (place) {
|
|
place.title = title;
|
|
} else {
|
|
place = {
|
|
uri: uri,
|
|
title: title
|
|
};
|
|
}
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while saving title for ' + uri);
|
|
};
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save title for ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Update a screenshot of a places entry by URI.
|
|
* @param {String} uri URI query parameter
|
|
* @param {Blob} screenshot A webpage screenshot taken using
|
|
* HTMLIFrameElement.getScreenshot
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
updatePlaceScreenshot: function db_updatePlaceScreenshot(uri, screenshot,
|
|
callback) {
|
|
var transaction = this._db.transaction([DBOS_PLACES], 'readwrite');
|
|
|
|
var objectStore = transaction.objectStore(DBOS_PLACES);
|
|
var readRequest = objectStore.get(uri);
|
|
|
|
readRequest.onsuccess = function onReadSuccess(event) {
|
|
var place = event.target.result;
|
|
if (place) {
|
|
place.screenshot = screenshot;
|
|
} else {
|
|
place = {
|
|
uri: uri,
|
|
title: uri,
|
|
screenshot: screenshot
|
|
};
|
|
}
|
|
|
|
var writeRequest = objectStore.put(place);
|
|
|
|
writeRequest.onerror = function onError() {
|
|
console.error('Error while saving screenshot for ' + uri);
|
|
};
|
|
|
|
writeRequest.onsuccess = function onWriteSuccess() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to save screenshot for ' +
|
|
uri);
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Clear places and icons entries. For exceptions reset frequency only.
|
|
* @param {Array} exceptions URIs to be excluded from clearing
|
|
* @param {Function} callback Runs on success
|
|
*/
|
|
clearHistoryExcluding: function db_clearHistoryExcluding(callback) {
|
|
// Clear all visits
|
|
this.clearVisits();
|
|
|
|
var transaction = this._db.
|
|
transaction([DBOS_PLACES, DBOS_ICONS], 'readwrite');
|
|
var placesStore = transaction.objectStore(DBOS_PLACES);
|
|
var iconStore = transaction.objectStore(DBOS_ICONS);
|
|
|
|
placesStore.openCursor(null, 'prev').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var place = cursor.value;
|
|
// If not one of the exceptions then delete place and icon
|
|
placesStore.delete(place.uri);
|
|
if (place.iconUri) {
|
|
iconStore.delete(place.iconUri);
|
|
}
|
|
cursor.continue();
|
|
}
|
|
};
|
|
transaction.oncomplete = function db_bookmarkTransactionComplete() {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
},
|
|
|
|
/**
|
|
* indexedDB MaxNum Check.
|
|
* @param {type} Bookmark or History or Topsite
|
|
* @param {maxNum} Object-specific maximum number
|
|
*/
|
|
idbMaxCheck: function db_idbMaxCheck(objType, maxNum) {
|
|
var transaction = this._db.transaction([objType], 'readwrite');
|
|
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to ' + objType);
|
|
};
|
|
|
|
var objectStore = transaction.objectStore(objType);
|
|
var objectIndex = null;
|
|
|
|
//count check
|
|
var request = objectStore.count();
|
|
request.onsuccess = function onReadSuccess(event) {
|
|
var count = event.target.result;
|
|
var checkCount = count - maxNum;
|
|
if(checkCount <= 0) {
|
|
return;
|
|
}else{
|
|
switch(objType){
|
|
case DBOS_BOOKMARKS:
|
|
case DBOS_VISITS :
|
|
objectIndex = objectStore.index('timestamp');
|
|
break;
|
|
case DBOS_PLACES :
|
|
objectIndex = objectStore.index('frecency');
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
objectIndex.openCursor(null, 'next').onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var objData = cursor.value;
|
|
switch(objType){
|
|
case DBOS_BOOKMARKS:
|
|
SyncBrowserDB.removeBookmark(objData.uri);
|
|
break;
|
|
case DBOS_VISITS :
|
|
SyncBrowserDB.removeHistory(objData.uri);
|
|
break;
|
|
case DBOS_PLACES :
|
|
SyncBrowserDB.removeTopsite(objData.uri);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
checkCount -= 1;
|
|
if(checkCount > 0) {
|
|
cursor.continue();
|
|
}else{
|
|
cursor = null;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
request.onerror = function onReadError(event) {
|
|
console.error('error reading object count');
|
|
};
|
|
},
|
|
|
|
/**
|
|
* indexedDB icons MaxNum Check.
|
|
*/
|
|
iconMaxCheck: function db_iconMaxCheck(maxNum) {
|
|
var transaction = this._db.
|
|
transaction([DBOS_ICONS, DBOS_BOOKMARKS, DBOS_VISITS],'readwrite');
|
|
transaction.onerror = function dbTransactionError(e) {
|
|
console.error('Transaction error while trying to icons');
|
|
};
|
|
|
|
var iconsStore = transaction.objectStore(DBOS_ICONS);
|
|
var bookmarksStore = transaction.objectStore(DBOS_BOOKMARKS);
|
|
var visitsStore = transaction.objectStore(DBOS_VISITS);
|
|
|
|
//count check
|
|
var request = iconsStore.count();
|
|
request.onsuccess = function onReadSuccess(event) {
|
|
var count = event.target.result;
|
|
if (count > maxNum) {
|
|
iconsStore.openCursor().onsuccess =
|
|
function onSuccess(e) {
|
|
var cursor = e.target.result;
|
|
if (cursor) {
|
|
var icon = cursor.value;
|
|
var requestBookmark = bookmarksStore.get(icon.uri);
|
|
requestBookmark.onsuccess = function onReadSuccess(event) {
|
|
var bookmarks = event.target.result;
|
|
if (!bookmarks) {
|
|
var requestVisits = visitsStore.get(icon.uri);
|
|
requestVisits.onsuccess = function onReadSuccess(event) {
|
|
var visits = event.target.result;
|
|
if (!visits) {
|
|
var requestIcons = iconsStore.delete(icon.uri);
|
|
requestIcons.onerror = function onError(e) {
|
|
console.error('Error delete icons object store');
|
|
};
|
|
}
|
|
};
|
|
requestVisits.onerror = function onReadError(event) {
|
|
console.error('error reading visit');
|
|
};
|
|
}
|
|
};
|
|
requestBookmark.onerror = function onReadError(event) {
|
|
console.error('error reading bookmarks');
|
|
};
|
|
|
|
cursor.continue();
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
};
|
|
|
|
request.onerror = function onReadError(event) {
|
|
console.error('error reading object icon count');
|
|
};
|
|
}
|
|
|
|
};
|