mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 818593 - Add file size to bookmarks restore UI. r=mak
This commit is contained in:
parent
b168795293
commit
7b07fe5baf
@ -11,6 +11,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "BookmarkJSONUtils",
|
||||
"resource://gre/modules/BookmarkJSONUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
|
||||
"resource://gre/modules/PlacesBackups.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||
"resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
var PlacesOrganizer = {
|
||||
_places: null,
|
||||
@ -411,6 +413,21 @@ var PlacesOrganizer = {
|
||||
|
||||
// Populate menu with backups.
|
||||
for (let i = 0; i < backupFiles.length; i++) {
|
||||
let [size, unit] = DownloadUtils.convertByteUnits(backupFiles[i].fileSize);
|
||||
let sizeString = PlacesUtils.getFormattedString("backupFileSizeText",
|
||||
[size, unit]);
|
||||
let sizeInfo;
|
||||
let bookmarkCount = PlacesBackups.getBookmarkCountForFile(backupFiles[i]);
|
||||
if (bookmarkCount != null) {
|
||||
sizeInfo = " (" + sizeString + " - " +
|
||||
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
|
||||
bookmarkCount,
|
||||
[bookmarkCount]) +
|
||||
")";
|
||||
} else {
|
||||
sizeInfo = " (" + sizeString + ")";
|
||||
}
|
||||
|
||||
let backupDate = PlacesBackups.getDateForFile(backupFiles[i]);
|
||||
let m = restorePopup.insertBefore(document.createElement("menuitem"),
|
||||
document.getElementById("restoreFromFile"));
|
||||
@ -419,7 +436,8 @@ var PlacesOrganizer = {
|
||||
Ci.nsIScriptableDateFormat.dateFormatLong,
|
||||
backupDate.getFullYear(),
|
||||
backupDate.getMonth() + 1,
|
||||
backupDate.getDate()));
|
||||
backupDate.getDate()) +
|
||||
sizeInfo);
|
||||
m.setAttribute("value", backupFiles[i].leafName);
|
||||
m.setAttribute("oncommand",
|
||||
"PlacesOrganizer.onRestoreMenuItemClick(this);");
|
||||
@ -516,7 +534,7 @@ var PlacesOrganizer = {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
let fpCallback = function fpCallback_done(aResult) {
|
||||
if (aResult != Ci.nsIFilePicker.returnCancel) {
|
||||
BookmarkJSONUtils.exportToFile(fp.file);
|
||||
PlacesBackups.saveBookmarksToJSONFile(fp.file);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,7 @@ function run_test() {
|
||||
create_bookmarks_html("bookmarks.glue.html");
|
||||
|
||||
// Create our JSON backup copying bookmarks.glue.json to the profile folder.
|
||||
remove_all_JSON_backups();
|
||||
create_JSON_backup("bookmarks.glue.json");
|
||||
|
||||
// Remove current database file.
|
||||
|
@ -275,6 +275,7 @@ function run_test()
|
||||
{
|
||||
// Create our bookmarks.html from bookmarks.glue.html.
|
||||
create_bookmarks_html("bookmarks.glue.html");
|
||||
remove_all_JSON_backups();
|
||||
// Create our JSON backup from bookmarks.glue.json.
|
||||
create_JSON_backup("bookmarks.glue.json");
|
||||
|
||||
|
@ -43,6 +43,7 @@ function run_test() {
|
||||
|
||||
// Create our JSON backup copying bookmarks.glue.json to the profile
|
||||
// folder. It will be ignored.
|
||||
remove_all_JSON_backups();
|
||||
create_JSON_backup("bookmarks.glue.json");
|
||||
|
||||
// Remove current database file.
|
||||
|
@ -29,6 +29,8 @@ let tests = [];
|
||||
tests.push({
|
||||
description: "Export to bookmarks.html if autoExportHTML is true.",
|
||||
exec: function() {
|
||||
remove_all_JSON_backups();
|
||||
|
||||
// Sanity check: we should have bookmarks on the toolbar.
|
||||
do_check_true(bs.getIdForItemAt(bs.toolbarFolder, 0) > 0);
|
||||
|
||||
@ -43,7 +45,7 @@ tests.push({
|
||||
// Check bookmarks.html has been created.
|
||||
check_bookmarks_html();
|
||||
// Check JSON backup has been created.
|
||||
check_JSON_backup();
|
||||
check_JSON_backup(true);
|
||||
|
||||
// Check preferences have not been reverted.
|
||||
do_check_true(ps.getBoolPref(PREF_AUTO_EXPORT_HTML));
|
||||
@ -128,16 +130,10 @@ tests.push({
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
function finish_test() {
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
var testIndex = 0;
|
||||
function next_test() {
|
||||
// Remove bookmarks.html from profile.
|
||||
remove_bookmarks_html();
|
||||
// Remove JSON backups from profile.
|
||||
remove_all_JSON_backups();
|
||||
|
||||
// Execute next test.
|
||||
let test = tests.shift();
|
||||
|
@ -19,8 +19,8 @@ const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
|
||||
|
||||
let EXPECTED_NOTIFICATIONS = [
|
||||
"places-shutdown"
|
||||
, "places-will-close-connection"
|
||||
, "places-expiration-finished"
|
||||
, "places-will-close-connection"
|
||||
, "places-connection-closed"
|
||||
];
|
||||
|
||||
|
@ -7,6 +7,7 @@ this.EXPORTED_SYMBOLS = [ "BookmarkJSONUtils" ];
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
@ -513,6 +514,7 @@ BookmarkExporter.prototype = {
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
safeFileOut.init(aLocalFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
|
||||
FileUtils.MODE_TRUNCATE, parseInt("0600", 8), 0);
|
||||
let nodeCount;
|
||||
|
||||
try {
|
||||
// We need a buffered output stream for performance. See bug 202477.
|
||||
@ -525,7 +527,7 @@ BookmarkExporter.prototype = {
|
||||
createInstance(Ci.nsIConverterOutputStream);
|
||||
this._converterOut.init(bufferedOut, "utf-8", 0, 0);
|
||||
try {
|
||||
yield this._writeContentToFile();
|
||||
nodeCount = yield this._writeContentToFile();
|
||||
|
||||
// Flush the buffer and retain the target file on success only.
|
||||
bufferedOut.QueryInterface(Ci.nsISafeOutputStream).finish();
|
||||
@ -539,27 +541,34 @@ BookmarkExporter.prototype = {
|
||||
} finally {
|
||||
safeFileOut.close();
|
||||
}
|
||||
throw new Task.Result(nodeCount);
|
||||
},
|
||||
|
||||
_writeContentToFile: function BE__writeContentToFile() {
|
||||
// Weep over stream interface variance.
|
||||
let streamProxy = {
|
||||
converter: this._converterOut,
|
||||
write: function(aData, aLen) {
|
||||
this.converter.writeString(aData);
|
||||
}
|
||||
};
|
||||
return Task.spawn(function() {
|
||||
// Weep over stream interface variance.
|
||||
let streamProxy = {
|
||||
converter: this._converterOut,
|
||||
write: function(aData, aLen) {
|
||||
this.converter.writeString(aData);
|
||||
}
|
||||
};
|
||||
|
||||
// Get list of itemIds that must be excluded from the backup.
|
||||
let excludeItems = PlacesUtils.annotations.getItemsWithAnnotation(
|
||||
PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.placesRootId, false,
|
||||
false).root;
|
||||
// Get list of itemIds that must be excluded from the backup.
|
||||
let excludeItems = PlacesUtils.annotations.getItemsWithAnnotation(
|
||||
PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.placesRootId, false,
|
||||
false).root;
|
||||
// Serialize to JSON and write to stream.
|
||||
let nodeCount = yield BookmarkNode.serializeAsJSONToOutputStream(root,
|
||||
streamProxy,
|
||||
false,
|
||||
false,
|
||||
excludeItems);
|
||||
root.containerOpen = false;
|
||||
|
||||
// Serialize to JSON and write to stream.
|
||||
yield BookmarkNode.serializeAsJSONToOutputStream(root, streamProxy, false, false,
|
||||
excludeItems);
|
||||
root.containerOpen = false;
|
||||
throw new Task.Result(nodeCount);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,6 +591,7 @@ let BookmarkNode = {
|
||||
* @param aExcludeItems
|
||||
* An array of item ids that should not be written to the backup.
|
||||
* @returns Task promise
|
||||
* @resolves the number of serialized uri nodes.
|
||||
*/
|
||||
serializeAsJSONToOutputStream: function BN_serializeAsJSONToOutputStream(
|
||||
aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems) {
|
||||
@ -589,20 +599,25 @@ let BookmarkNode = {
|
||||
return Task.spawn(function() {
|
||||
// Serialize to stream
|
||||
let array = [];
|
||||
if (yield this._appendConvertedNode(aNode, null, array, aIsUICommand,
|
||||
aResolveShortcuts, aExcludeItems)) {
|
||||
let result = yield this._appendConvertedNode(aNode, null, array,
|
||||
aIsUICommand,
|
||||
aResolveShortcuts,
|
||||
aExcludeItems);
|
||||
if (result.appendedNode) {
|
||||
let json = JSON.stringify(array[0]);
|
||||
aStream.write(json, json.length);
|
||||
} else {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}.bind(this));
|
||||
throw new Task.Result(result.nodeCount);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_appendConvertedNode: function BN__appendConvertedNode(
|
||||
bNode, aIndex, aArray, aIsUICommand, aResolveShortcuts, aExcludeItems) {
|
||||
return Task.spawn(function() {
|
||||
let node = {};
|
||||
let nodeCount = 0;
|
||||
|
||||
// Set index in order received
|
||||
// XXX handy shortcut, but are there cases where we don't want
|
||||
@ -618,7 +633,7 @@ let BookmarkNode = {
|
||||
if (PlacesUtils.nodeIsURI(bNode)) {
|
||||
// Tag root accept only folder nodes
|
||||
if (parent && parent.itemId == PlacesUtils.tagsFolderId)
|
||||
throw new Task.Result(false);
|
||||
throw new Task.Result({ appendedNode: false, nodeCount: nodeCount });
|
||||
|
||||
// Check for url validity, since we can't halt while writing a backup.
|
||||
// This will throw if we try to serialize an invalid url and it does
|
||||
@ -626,14 +641,15 @@ let BookmarkNode = {
|
||||
try {
|
||||
NetUtil.newURI(bNode.uri);
|
||||
} catch (ex) {
|
||||
throw new Task.Result(false);
|
||||
throw new Task.Result({ appendedNode: false, nodeCount: nodeCount });
|
||||
}
|
||||
|
||||
yield this._addURIProperties(bNode, node, aIsUICommand);
|
||||
nodeCount++;
|
||||
} else if (PlacesUtils.nodeIsContainer(bNode)) {
|
||||
// Tag containers accept only uri nodes
|
||||
if (grandParent && grandParent.itemId == PlacesUtils.tagsFolderId)
|
||||
throw new Task.Result(false);
|
||||
throw new Task.Result({ appendedNode: false, nodeCount: nodeCount });
|
||||
|
||||
this._addContainerProperties(bNode, node, aIsUICommand,
|
||||
aResolveShortcuts);
|
||||
@ -642,19 +658,24 @@ let BookmarkNode = {
|
||||
// Tag containers accept only uri nodes
|
||||
if ((parent && parent.itemId == PlacesUtils.tagsFolderId) ||
|
||||
(grandParent && grandParent.itemId == PlacesUtils.tagsFolderId))
|
||||
throw new Task.Result(false);
|
||||
throw new Task.Result({ appendedNode: false, nodeCount: nodeCount });
|
||||
|
||||
this._addSeparatorProperties(bNode, node);
|
||||
}
|
||||
|
||||
if (!node.feedURI && node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) {
|
||||
throw new Task.Result(yield this._appendConvertedComplexNode(node, bNode, aArray, aIsUICommand,
|
||||
aResolveShortcuts, aExcludeItems));
|
||||
nodeCount += yield this._appendConvertedComplexNode(node,
|
||||
bNode,
|
||||
aArray,
|
||||
aIsUICommand,
|
||||
aResolveShortcuts,
|
||||
aExcludeItems)
|
||||
throw new Task.Result({ appendedNode: true, nodeCount: nodeCount });
|
||||
}
|
||||
|
||||
aArray.push(node);
|
||||
throw new Task.Result(true);
|
||||
}.bind(this));
|
||||
throw new Task.Result({ appendedNode: true, nodeCount: nodeCount });
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_addGenericProperties: function BN__addGenericProperties(
|
||||
@ -765,6 +786,7 @@ let BookmarkNode = {
|
||||
aExcludeItems) {
|
||||
return Task.spawn(function() {
|
||||
let repr = {};
|
||||
let nodeCount = 0;
|
||||
|
||||
for (let [name, value] in Iterator(aNode))
|
||||
repr[name] = value;
|
||||
@ -781,16 +803,17 @@ let BookmarkNode = {
|
||||
let childNode = aSourceNode.getChild(i);
|
||||
if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1)
|
||||
continue;
|
||||
yield this._appendConvertedNode(aSourceNode.getChild(i), i, children,
|
||||
aIsUICommand, aResolveShortcuts,
|
||||
aExcludeItems);
|
||||
let result = yield this._appendConvertedNode(aSourceNode.getChild(i), i, children,
|
||||
aIsUICommand, aResolveShortcuts,
|
||||
aExcludeItems);
|
||||
nodeCount += result.nodeCount;
|
||||
}
|
||||
if (!wasOpen)
|
||||
aSourceNode.containerOpen = false;
|
||||
}
|
||||
|
||||
aArray.push(repr);
|
||||
throw new Task.Result(true);
|
||||
throw new Task.Result(nodeCount);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
@ -9,11 +9,17 @@ this.EXPORTED_SYMBOLS = ["PlacesBackups"];
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
this.PlacesBackups = {
|
||||
get _filenamesRegex() {
|
||||
// Get the localized backup filename, will be used to clear out
|
||||
@ -24,7 +30,7 @@ this.PlacesBackups = {
|
||||
localizedFilename.substr(0, localizedFilename.indexOf("-"));
|
||||
delete this._filenamesRegex;
|
||||
return this._filenamesRegex =
|
||||
new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9-]+)\.(json|html)");
|
||||
new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9-]+)(_[0-9]+)*\.(json|html)");
|
||||
},
|
||||
|
||||
get folder() {
|
||||
@ -127,6 +133,7 @@ this.PlacesBackups = {
|
||||
* @param aFile
|
||||
* nsIFile where to save JSON backup.
|
||||
* @return {Promise}
|
||||
* @resolves the number of serialized uri nodes.
|
||||
*/
|
||||
saveBookmarksToJSONFile: function PB_saveBookmarksToJSONFile(aFile) {
|
||||
return Task.spawn(function() {
|
||||
@ -136,7 +143,7 @@ this.PlacesBackups = {
|
||||
throw new Error("Unable to create bookmarks backup file: " + aFile.leafName);
|
||||
}
|
||||
|
||||
yield BookmarkJSONUtils.exportToFile(aFile);
|
||||
let nodeCount = yield BookmarkJSONUtils.exportToFile(aFile);
|
||||
|
||||
if (aFile.parent.equals(this.folder)) {
|
||||
// Update internal cache.
|
||||
@ -146,21 +153,25 @@ this.PlacesBackups = {
|
||||
// we also want to copy this new backup to it.
|
||||
// This way we ensure the latest valid backup is the same saved by the
|
||||
// user. See bug 424389.
|
||||
let latestBackup = this.getMostRecent("json");
|
||||
if (!latestBackup || latestBackup != aFile) {
|
||||
let name = this.getFilenameForDate();
|
||||
let name = this.getFilenameForDate();
|
||||
let newFilename = this._appendMetaDataToFilename(name,
|
||||
{ nodeCount: nodeCount });
|
||||
|
||||
let backupFile = yield this._getBackupFileForSameDate(name);
|
||||
if (backupFile) {
|
||||
backupFile.remove(false);
|
||||
} else {
|
||||
let file = this.folder.clone();
|
||||
file.append(name);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
} else {
|
||||
// Update internal cache if we are not replacing an existing
|
||||
// backup file.
|
||||
this.entries.push(file);
|
||||
}
|
||||
aFile.copyTo(this.folder, name);
|
||||
file.append(newFilename);
|
||||
|
||||
// Update internal cache if we are not replacing an existing
|
||||
// backup file.
|
||||
this.entries.push(file);
|
||||
}
|
||||
aFile.copyTo(this.folder, newFilename);
|
||||
}
|
||||
|
||||
throw new Task.Result(nodeCount);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@ -193,7 +204,8 @@ this.PlacesBackups = {
|
||||
// the total backups after this operation does not exceed the
|
||||
// number specified in the pref.
|
||||
if (!mostRecentBackupFile ||
|
||||
mostRecentBackupFile.leafName != newBackupFilename)
|
||||
!this._isFilenameWithSameDate(mostRecentBackupFile.leafName,
|
||||
newBackupFilename))
|
||||
numberOfBackupsToDelete++;
|
||||
|
||||
while (numberOfBackupsToDelete--) {
|
||||
@ -205,20 +217,89 @@ this.PlacesBackups = {
|
||||
// Do nothing if we already have this backup or we don't want backups.
|
||||
if (aMaxBackups === 0 ||
|
||||
(mostRecentBackupFile &&
|
||||
mostRecentBackupFile.leafName == newBackupFilename))
|
||||
this._isFilenameWithSameDate(mostRecentBackupFile.leafName,
|
||||
newBackupFilename)))
|
||||
return;
|
||||
}
|
||||
|
||||
let backupFile = yield this._getBackupFileForSameDate(newBackupFilename);
|
||||
if (backupFile) {
|
||||
if (aForceBackup)
|
||||
backupFile.remove(false);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Save bookmarks to a backup file.
|
||||
let newBackupFile = this.folder.clone();
|
||||
newBackupFile.append(newBackupFilename);
|
||||
let nodeCount = yield this.saveBookmarksToJSONFile(newBackupFile);
|
||||
|
||||
if (aForceBackup && newBackupFile.exists())
|
||||
newBackupFile.remove(false);
|
||||
// Rename the filename with metadata.
|
||||
let newFilenameWithMetaData = this._appendMetaDataToFilename(
|
||||
newBackupFile.leafName,
|
||||
{ nodeCount: nodeCount });
|
||||
newBackupFile.moveTo(this.folder, newFilenameWithMetaData);
|
||||
|
||||
if (newBackupFile.exists())
|
||||
return;
|
||||
|
||||
yield this.saveBookmarksToJSONFile(newBackupFile);
|
||||
// Update internal cache.
|
||||
let newFileWithMetaData = this.folder.clone();
|
||||
newFileWithMetaData.append(newFilenameWithMetaData);
|
||||
this.entries.pop();
|
||||
this.entries.push(newFileWithMetaData);
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
_appendMetaDataToFilename:
|
||||
function PB__appendMetaDataToFilename(aFilename, aMetaData) {
|
||||
let matches = aFilename.match(this._filenamesRegex);
|
||||
let newFilename = matches[1] + "-" + matches[2] + "_" +
|
||||
aMetaData.nodeCount + "." + matches[4];
|
||||
return newFilename;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the bookmark count for backup file.
|
||||
*
|
||||
* @param aFile
|
||||
* String The backup file.
|
||||
*
|
||||
* @return the bookmark count or null.
|
||||
*/
|
||||
getBookmarkCountForFile: function PB_getBookmarkCountForFile(aFile) {
|
||||
let count = null;
|
||||
let matches = aFile.leafName.match(this._filenamesRegex);
|
||||
|
||||
if (matches && matches[3])
|
||||
count = matches[3].replace(/_/g, "");
|
||||
return count;
|
||||
},
|
||||
|
||||
_isFilenameWithSameDate:
|
||||
function PB__isFilenameWithSameDate(aSourceName, aTargetName) {
|
||||
let sourceMatches = aSourceName.match(this._filenamesRegex);
|
||||
let targetMatches = aTargetName.match(this._filenamesRegex);
|
||||
|
||||
return (sourceMatches && targetMatches &&
|
||||
sourceMatches[1] == targetMatches[1] &&
|
||||
sourceMatches[2] == targetMatches[2] &&
|
||||
sourceMatches[4] == targetMatches[4]);
|
||||
},
|
||||
|
||||
_getBackupFileForSameDate:
|
||||
function PB__getBackupFileForSameDate(aFilename) {
|
||||
return Task.spawn(function() {
|
||||
let iterator = new OS.File.DirectoryIterator(this.folder.path);
|
||||
let backupFile;
|
||||
|
||||
yield iterator.forEach(function(aEntry) {
|
||||
if (this._isFilenameWithSameDate(aEntry.name, aFilename)) {
|
||||
backupFile = new FileUtils.File(aEntry.path);
|
||||
return iterator.close();
|
||||
}
|
||||
}.bind(this));
|
||||
yield iterator.close();
|
||||
|
||||
throw new Task.Result(backupFile);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,23 @@ function run_test() {
|
||||
|
||||
// Export bookmarks to JSON.
|
||||
var backupFilename = PlacesBackups.getFilenameForDate();
|
||||
var lastBackupFile = bookmarksBackupDir.clone();
|
||||
lastBackupFile.append(backupFilename);
|
||||
if (lastBackupFile.exists())
|
||||
lastBackupFile.remove(false);
|
||||
do_check_false(lastBackupFile.exists());
|
||||
var rx = new RegExp("^" + backupFilename.replace(/\.json/, "") + "(_[0-9]+){0,1}\.json$");
|
||||
var files = bookmarksBackupDir.directoryEntries;
|
||||
var entry;
|
||||
while (files.hasMoreElements()) {
|
||||
entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (entry.leafName.match(rx))
|
||||
entry.remove(false);
|
||||
}
|
||||
|
||||
Task.spawn(function() {
|
||||
yield PlacesBackups.create(NUMBER_OF_BACKUPS);
|
||||
files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (entry.leafName.match(rx))
|
||||
lastBackupFile = entry;
|
||||
}
|
||||
do_check_true(lastBackupFile.exists());
|
||||
|
||||
// Check that last backup has been retained
|
||||
|
@ -20,11 +20,16 @@ function run_test() {
|
||||
dateObj.setYear(dateObj.getFullYear() + 1);
|
||||
let name = PlacesBackups.getFilenameForDate(dateObj);
|
||||
do_check_eq(name, "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json");
|
||||
let rx = new RegExp("^" + name.replace(/\.json/, "") + "(_[0-9]+){0,1}\.json$");
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (entry.leafName.match(rx))
|
||||
entry.remove(false);
|
||||
}
|
||||
|
||||
let futureBackupFile = bookmarksBackupDir.clone();
|
||||
futureBackupFile.append(name);
|
||||
if (futureBackupFile.exists())
|
||||
futureBackupFile.remove(false);
|
||||
do_check_false(futureBackupFile.exists());
|
||||
futureBackupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
|
||||
do_check_true(futureBackupFile.exists());
|
||||
|
||||
@ -36,8 +41,9 @@ function run_test() {
|
||||
do_check_eq(PlacesBackups.entries.length, 1);
|
||||
let mostRecentBackupFile = PlacesBackups.getMostRecent();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
let todayName = PlacesBackups.getFilenameForDate();
|
||||
do_check_eq(mostRecentBackupFile.leafName, todayName);
|
||||
let todayFilename = PlacesBackups.getFilenameForDate();
|
||||
rx = new RegExp("^" + todayFilename.replace(/\.json/, "") + "(_[0-9]+){0,1}\.json$");
|
||||
do_check_true(mostRecentBackupFile.leafName.match(rx).length > 0);
|
||||
|
||||
// Check that future backup has been removed.
|
||||
do_check_false(futureBackupFile.exists());
|
||||
|
@ -0,0 +1,57 @@
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* To confirm that metadata i.e. bookmark count is set and retrieved for
|
||||
* automatic backups.
|
||||
*/
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_saveBookmarksToJSONFile_and_create()
|
||||
{
|
||||
// Add a bookmark
|
||||
let uri = NetUtil.newURI("http://getfirefox.com/");
|
||||
let bookmarkId =
|
||||
PlacesUtils.bookmarks.insertBookmark(
|
||||
PlacesUtils.unfiledBookmarksFolderId, uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
|
||||
|
||||
// Test saveBookmarksToJSONFile()
|
||||
let backupFile = FileUtils.getFile("TmpD", ["bookmarks.json"]);
|
||||
backupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, parseInt("0600", 8));
|
||||
|
||||
let nodeCount = yield PlacesBackups.saveBookmarksToJSONFile(backupFile, true);
|
||||
do_check_true(nodeCount > 0);
|
||||
do_check_true(backupFile.exists());
|
||||
do_check_eq(backupFile.leafName, "bookmarks.json");
|
||||
|
||||
// Ensure the backup would be copied to our backups folder when the original
|
||||
// backup is saved somewhere else.
|
||||
let recentBackup = PlacesBackups.getMostRecent();
|
||||
let todayFilename = PlacesBackups.getFilenameForDate();
|
||||
do_check_eq(recentBackup.leafName,
|
||||
todayFilename.replace(/\.json/, "_" + nodeCount + ".json"));
|
||||
|
||||
// Clear all backups in our backups folder.
|
||||
yield PlacesBackups.create(0);
|
||||
do_check_eq(PlacesBackups.entries.length, 0);
|
||||
|
||||
// Test create() which saves bookmarks with metadata on the filename.
|
||||
yield PlacesBackups.create();
|
||||
do_check_eq(PlacesBackups.entries.length, 1);
|
||||
|
||||
mostRecentBackupFile = PlacesBackups.getMostRecent();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
let rx = new RegExp("^" + todayFilename.replace(/\.json/, "") + "_([0-9]+)\.json$");
|
||||
let matches = mostRecentBackupFile.leafName.match(rx);
|
||||
do_check_true(matches.length > 0 && parseInt(matches[1]) == nodeCount);
|
||||
|
||||
// Cleanup
|
||||
backupFile.remove(false);
|
||||
yield PlacesBackups.create(0);
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
});
|
||||
|
@ -29,3 +29,4 @@ tail =
|
||||
[test_675416.js]
|
||||
[test_711914.js]
|
||||
[test_protectRoots.js]
|
||||
[test_818593-store-backup-metadata.js]
|
||||
|
@ -470,18 +470,22 @@ function check_bookmarks_html() {
|
||||
function create_JSON_backup(aFilename) {
|
||||
if (!aFilename)
|
||||
do_throw("you must pass a filename to create_JSON_backup function");
|
||||
remove_all_JSON_backups();
|
||||
let bookmarksBackupDir = gProfD.clone();
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
do_check_true(bookmarksBackupDir.exists());
|
||||
}
|
||||
let profileBookmarksJSONFile = bookmarksBackupDir.clone();
|
||||
profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON);
|
||||
if (profileBookmarksJSONFile.exists()) {
|
||||
profileBookmarksJSONFile.remove();
|
||||
}
|
||||
let bookmarksJSONFile = gTestDir.clone();
|
||||
bookmarksJSONFile.append(aFilename);
|
||||
do_check_true(bookmarksJSONFile.exists());
|
||||
bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON);
|
||||
let profileBookmarksJSONFile = bookmarksBackupDir.clone();
|
||||
profileBookmarksJSONFile = bookmarksBackupDir.clone();
|
||||
profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON);
|
||||
do_check_true(profileBookmarksJSONFile.exists());
|
||||
return profileBookmarksJSONFile;
|
||||
@ -504,12 +508,30 @@ function remove_all_JSON_backups() {
|
||||
/**
|
||||
* Check a JSON backup file for today exists in the profile folder.
|
||||
*
|
||||
* @param aIsAutomaticBackup The boolean indicates whether it's an automatic
|
||||
* backup.
|
||||
* @return nsIFile object for the file.
|
||||
*/
|
||||
function check_JSON_backup() {
|
||||
let profileBookmarksJSONFile = gProfD.clone();
|
||||
profileBookmarksJSONFile.append("bookmarkbackups");
|
||||
profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON);
|
||||
function check_JSON_backup(aIsAutomaticBackup) {
|
||||
let profileBookmarksJSONFile;
|
||||
if (aIsAutomaticBackup) {
|
||||
let bookmarksBackupDir = gProfD.clone();
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
let backup_date = new Date().toLocaleFormat("%Y-%m-%d");
|
||||
let rx = new RegExp("^bookmarks-" + backup_date + "_[0-9]+\.json$");
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (entry.leafName.match(rx)) {
|
||||
profileBookmarksJSONFile = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
profileBookmarksJSONFile = gProfD.clone();
|
||||
profileBookmarksJSONFile.append("bookmarkbackups");
|
||||
profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON);
|
||||
}
|
||||
do_check_true(profileBookmarksJSONFile.exists());
|
||||
return profileBookmarksJSONFile;
|
||||
}
|
||||
|
@ -66,23 +66,40 @@ function run_test() {
|
||||
for (var i = 0; i < dates.length; i++) {
|
||||
let backupFilename;
|
||||
let shouldExist;
|
||||
let backupFile;
|
||||
if (i > Math.floor(dates.length/2)) {
|
||||
backupFilename = PREFIX + dates[i] + SUFFIX;
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
let rx = new RegExp("^" + PREFIX + dates[i] + "(_[0-9]+){0,1}" + SUFFIX + "$");
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (entry.leafName.match(rx)) {
|
||||
backupFilename = entry.leafName;
|
||||
backupFile = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
shouldExist = true;
|
||||
}
|
||||
else {
|
||||
backupFilename = LOCALIZED_PREFIX + dates[i] + SUFFIX;
|
||||
backupFile = bookmarksBackupDir.clone();
|
||||
backupFile.append(backupFilename);
|
||||
shouldExist = false;
|
||||
}
|
||||
var backupFile = bookmarksBackupDir.clone();
|
||||
backupFile.append(backupFilename);
|
||||
if (backupFile.exists() != shouldExist)
|
||||
do_throw("Backup should " + (shouldExist ? "" : "not") + " exist: " + backupFilename);
|
||||
}
|
||||
|
||||
// Cleanup backups folder.
|
||||
bookmarksBackupDir.remove(true);
|
||||
do_check_false(bookmarksBackupDir.exists());
|
||||
// XXX: Can't use bookmarksBackupDir.remove(true) because file lock happens
|
||||
// on WIN XP.
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
entry.remove(false);
|
||||
}
|
||||
do_check_false(bookmarksBackupDir.directoryEntries.hasMoreElements());
|
||||
|
||||
// Recreate the folder.
|
||||
PlacesBackups.folder;
|
||||
|
||||
|
@ -30,3 +30,10 @@ localhost=(local files)
|
||||
# before bug 445704 was fixed. It will be removed
|
||||
# in a subsequent release.
|
||||
bookmarksArchiveFilename=bookmarks-%S.json
|
||||
|
||||
# LOCALIZATION NOTE
|
||||
# The string is used for showing file size of each backup in the "fileRestorePopup" popup
|
||||
# %1$S is the file size
|
||||
# %2$S is the file size unit
|
||||
backupFileSizeText=%1$S %2$S
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user