Backed out 2 changesets (bug 1236916) for causing xpcshell failures on test_Safari_bookmarks.js
Backed out changeset 539dfe08bec7 (bug 1236916) Backed out changeset a0b5a7ade705 (bug 1236916)
This commit is contained in:
@@ -15,23 +15,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
PropertyListUtils: "resource://gre/modules/PropertyListUtils.sys.mjs",
|
PropertyListUtils: "resource://gre/modules/PropertyListUtils.sys.mjs",
|
||||||
});
|
});
|
||||||
|
|
||||||
// NSDate epoch is Jan 1, 2001 UTC
|
|
||||||
const NS_DATE_EPOCH_MS = new Date("2001-01-01T00:00:00-00:00").getTime();
|
|
||||||
|
|
||||||
// Convert NSDate timestamp to UNIX timestamp.
|
|
||||||
function parseNSDate(cocoaDateStr) {
|
|
||||||
let asDouble = parseFloat(cocoaDateStr);
|
|
||||||
if (!isNaN(asDouble)) {
|
|
||||||
return new Date(NS_DATE_EPOCH_MS + asDouble * 1000);
|
|
||||||
}
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert UNIX timestamp to NSDate timestamp.
|
|
||||||
function msToNSDate(ms) {
|
|
||||||
return parseFloat(ms - NS_DATE_EPOCH_MS) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Bookmarks(aBookmarksFile) {
|
function Bookmarks(aBookmarksFile) {
|
||||||
this._file = aBookmarksFile;
|
this._file = aBookmarksFile;
|
||||||
}
|
}
|
||||||
@@ -346,86 +329,82 @@ Bookmarks.prototype = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
async function GetHistoryResource() {
|
function History(aHistoryFile) {
|
||||||
let dbPath = FileUtils.getDir(
|
this._file = aHistoryFile;
|
||||||
"ULibDir",
|
}
|
||||||
["Safari", "History.db"],
|
History.prototype = {
|
||||||
false
|
type: MigrationUtils.resourceTypes.HISTORY,
|
||||||
).path;
|
|
||||||
let maxAge = msToNSDate(
|
|
||||||
Date.now() - MigrationUtils.HISTORY_MAX_AGE_IN_MILLISECONDS
|
|
||||||
);
|
|
||||||
|
|
||||||
let countQuery = `
|
// Helper method for converting the visit date property to a PRTime value.
|
||||||
SELECT COUNT(*)
|
// The visit date is stored as a string, so it's not read as a Date
|
||||||
FROM history_items LEFT JOIN history_visits
|
// object by PropertyListUtils.
|
||||||
ON history_items.id = history_visits.history_item
|
_parseCocoaDate: function H___parseCocoaDate(aCocoaDateStr) {
|
||||||
WHERE history_visits.visit_time > ${maxAge}
|
let asDouble = parseFloat(aCocoaDateStr);
|
||||||
LIMIT 1;`;
|
if (!isNaN(asDouble)) {
|
||||||
let selectQuery = `
|
// reference date of NSDate.
|
||||||
SELECT
|
let date = new Date("1 January 2001, GMT");
|
||||||
history_items.url as history_url,
|
date.setMilliseconds(asDouble * 1000);
|
||||||
history_visits.title as history_title,
|
return date;
|
||||||
history_visits.visit_time as history_time
|
}
|
||||||
FROM history_items LEFT JOIN history_visits
|
return new Date();
|
||||||
ON history_items.id = history_visits.history_item
|
},
|
||||||
WHERE history_visits.visit_time > ${maxAge};`;
|
|
||||||
|
|
||||||
let countResult = await MigrationUtils.getRowsFromDBWithoutLocks(
|
|
||||||
dbPath,
|
|
||||||
"Safari history",
|
|
||||||
countQuery
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!countResult[0].getResultByName("COUNT(*)")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: MigrationUtils.resourceTypes.HISTORY,
|
|
||||||
|
|
||||||
async migrate(callback) {
|
|
||||||
callback(await this._migrate());
|
|
||||||
},
|
|
||||||
|
|
||||||
async _migrate() {
|
|
||||||
let historyRows;
|
|
||||||
|
|
||||||
|
migrate: function H_migrate(aCallback) {
|
||||||
|
lazy.PropertyListUtils.read(this._file, aDict => {
|
||||||
try {
|
try {
|
||||||
historyRows = await MigrationUtils.getRowsFromDBWithoutLocks(
|
if (!aDict) {
|
||||||
dbPath,
|
throw new Error("Could not read history property list");
|
||||||
"Safari history",
|
|
||||||
selectQuery
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!historyRows.length) {
|
|
||||||
console.log("No history found");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (!aDict.has("WebHistoryDates")) {
|
||||||
|
throw new Error("Unexpected history-property list format");
|
||||||
|
}
|
||||||
|
|
||||||
|
let pageInfos = [];
|
||||||
|
let entries = aDict.get("WebHistoryDates");
|
||||||
|
let failedOnce = false;
|
||||||
|
for (let entry of entries) {
|
||||||
|
if (entry.has("lastVisitedDate")) {
|
||||||
|
let date = this._parseCocoaDate(entry.get("lastVisitedDate"));
|
||||||
|
try {
|
||||||
|
pageInfos.push({
|
||||||
|
url: new URL(entry.get("")),
|
||||||
|
title: entry.get("title"),
|
||||||
|
visits: [
|
||||||
|
{
|
||||||
|
// Safari's History file contains only top-level urls. It does not
|
||||||
|
// distinguish between typed urls and linked urls.
|
||||||
|
transition: lazy.PlacesUtils.history.TRANSITIONS.LINK,
|
||||||
|
date,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
// Safari's History file may contain malformed URIs which
|
||||||
|
// will be ignored.
|
||||||
|
console.error(ex);
|
||||||
|
failedOnce = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pageInfos.length) {
|
||||||
|
// If we failed at least once, then we didn't succeed in importing,
|
||||||
|
// otherwise we didn't actually have anything to import, so we'll
|
||||||
|
// report it as a success.
|
||||||
|
aCallback(!failedOnce);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MigrationUtils.insertVisitsWrapper(pageInfos).then(
|
||||||
|
() => aCallback(true),
|
||||||
|
() => aCallback(false)
|
||||||
|
);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error(ex);
|
console.error(ex);
|
||||||
return false;
|
aCallback(false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
let pageInfos = [];
|
},
|
||||||
for (let row of historyRows) {
|
};
|
||||||
pageInfos.push({
|
|
||||||
title: row.getResultByName("history_title"),
|
|
||||||
url: new URL(row.getResultByName("history_url")),
|
|
||||||
visits: [
|
|
||||||
{
|
|
||||||
transition: lazy.PlacesUtils.history.TRANSITIONS.TYPED,
|
|
||||||
date: parseNSDate(row.getResultByName("history_time")),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await MigrationUtils.insertVisitsWrapper(pageInfos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safari's preferences property list is independently used for three purposes:
|
* Safari's preferences property list is independently used for three purposes:
|
||||||
@@ -518,7 +497,7 @@ export class SafariProfileMigrator extends MigratorBase {
|
|||||||
return "chrome://browser/content/migration/brands/safari.png";
|
return "chrome://browser/content/migration/brands/safari.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
async getResources() {
|
getResources() {
|
||||||
let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
|
let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
|
||||||
if (!profileDir.exists()) {
|
if (!profileDir.exists()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -533,6 +512,7 @@ export class SafariProfileMigrator extends MigratorBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pushProfileFileResource("History.plist", History);
|
||||||
pushProfileFileResource("Bookmarks.plist", Bookmarks);
|
pushProfileFileResource("Bookmarks.plist", Bookmarks);
|
||||||
|
|
||||||
// The Reading List feature was introduced at the same time in Windows and
|
// The Reading List feature was introduced at the same time in Windows and
|
||||||
@@ -547,11 +527,7 @@ export class SafariProfileMigrator extends MigratorBase {
|
|||||||
resources.push(new SearchStrings(prefs));
|
resources.push(new SearchStrings(prefs));
|
||||||
}
|
}
|
||||||
|
|
||||||
resources.push(GetHistoryResource());
|
return resources;
|
||||||
|
|
||||||
resources = await Promise.all(resources);
|
|
||||||
|
|
||||||
return resources.filter(r => r != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLastUsedDate() {
|
async getLastUsedDate() {
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const HISTORY_TEMPLATE_FILE_PATH = "Library/Safari/HistoryTemplate.db";
|
|
||||||
const HISTORY_FILE_PATH = "Library/Safari/History.db";
|
|
||||||
|
|
||||||
// We want this to be some recent time, so we'll always add some time to our
|
|
||||||
// dates to keep them ~ five days ago.
|
|
||||||
const MS_FROM_REFERENCE_TIME =
|
|
||||||
new Date() - new Date("May 31, 2023 00:00:00 UTC");
|
|
||||||
|
|
||||||
const TEST_URLS = [
|
|
||||||
{
|
|
||||||
url: "http://example.com/",
|
|
||||||
title: "Example Domain",
|
|
||||||
time: 706743588.04751,
|
|
||||||
jsTime: 1685050788047 + MS_FROM_REFERENCE_TIME,
|
|
||||||
visits: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "http://mozilla.org/",
|
|
||||||
title: "",
|
|
||||||
time: 706743581.133386,
|
|
||||||
jsTime: 1685050781133 + MS_FROM_REFERENCE_TIME,
|
|
||||||
visits: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "https://www.mozilla.org/en-CA/",
|
|
||||||
title: "Internet for people, not profit - Mozilla",
|
|
||||||
time: 706743581.133679,
|
|
||||||
jsTime: 1685050781133 + MS_FROM_REFERENCE_TIME,
|
|
||||||
visits: 1,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
async function setupHistoryFile() {
|
|
||||||
removeHistoryFile();
|
|
||||||
let file = do_get_file(HISTORY_TEMPLATE_FILE_PATH);
|
|
||||||
file.copyTo(file.parent, "History.db");
|
|
||||||
await updateVisitTimes();
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeHistoryFile() {
|
|
||||||
let file = do_get_file(HISTORY_FILE_PATH, true);
|
|
||||||
try {
|
|
||||||
file.remove(false);
|
|
||||||
} catch (ex) {
|
|
||||||
// It is ok if this doesn't exist.
|
|
||||||
if (ex.result != Cr.NS_ERROR_FILE_NOT_FOUND) {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateVisitTimes() {
|
|
||||||
let cocoaDifference = MS_FROM_REFERENCE_TIME / 1000;
|
|
||||||
let historyFile = do_get_file(HISTORY_FILE_PATH);
|
|
||||||
let dbConn = await Sqlite.openConnection({ path: historyFile.path });
|
|
||||||
await dbConn.execute(
|
|
||||||
"UPDATE history_visits SET visit_time = visit_time + :difference;",
|
|
||||||
{ difference: cocoaDifference }
|
|
||||||
);
|
|
||||||
await dbConn.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
add_setup(async function setup() {
|
|
||||||
registerFakePath("ULibDir", do_get_file("Library/"));
|
|
||||||
await setupHistoryFile();
|
|
||||||
registerCleanupFunction(async () => {
|
|
||||||
await PlacesUtils.history.clear();
|
|
||||||
removeHistoryFile();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function testHistoryImport() {
|
|
||||||
await PlacesUtils.history.clear();
|
|
||||||
|
|
||||||
let migrator = await MigrationUtils.getMigrator("safari");
|
|
||||||
await promiseMigration(migrator, MigrationUtils.resourceTypes.HISTORY);
|
|
||||||
|
|
||||||
for (let urlInfo of TEST_URLS) {
|
|
||||||
let entry = await PlacesUtils.history.fetch(urlInfo.url, {
|
|
||||||
includeVisits: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.equal(entry.url, urlInfo.url, "Should have the correct URL");
|
|
||||||
Assert.equal(entry.title, urlInfo.title, "Should have the correct title");
|
|
||||||
Assert.equal(
|
|
||||||
entry.visits.length,
|
|
||||||
urlInfo.visits,
|
|
||||||
"Should have the correct number of visits"
|
|
||||||
);
|
|
||||||
Assert.equal(
|
|
||||||
entry.visits[0].date.getTime(),
|
|
||||||
urlInfo.jsTime,
|
|
||||||
"Should have the correct date"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -53,5 +53,3 @@ skip-if = os != "win"
|
|||||||
skip-if = !debug && os == "mac" #Bug 1558330
|
skip-if = !debug && os == "mac" #Bug 1558330
|
||||||
[test_Safari_bookmarks.js]
|
[test_Safari_bookmarks.js]
|
||||||
skip-if = os != "mac"
|
skip-if = os != "mac"
|
||||||
[test_Safari_history.js]
|
|
||||||
skip-if = os != "mac"
|
|
||||||
|
|||||||
@@ -531,16 +531,6 @@ add_task(async function test_aboutwelcome_embedded_migration() {
|
|||||||
true /* wantsUntrusted */
|
true /* wantsUntrusted */
|
||||||
);
|
);
|
||||||
let selector = shadow.querySelector("#browser-profile-selector");
|
let selector = shadow.querySelector("#browser-profile-selector");
|
||||||
|
|
||||||
// The migration wizard programmatically focuses the selector after
|
|
||||||
// the selection page is shown using an rAF. If we click the button
|
|
||||||
// before that occurs, then the focus can shift after the panel opens
|
|
||||||
// which will cause it to immediately close again. So we wait for the
|
|
||||||
// selection button to gain focus before continuing.
|
|
||||||
if (!selector.matches(":focus")) {
|
|
||||||
await ContentTaskUtils.waitForEvent(selector, "focus");
|
|
||||||
}
|
|
||||||
|
|
||||||
selector.click();
|
selector.click();
|
||||||
await shown;
|
await shown;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user