mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge.
This commit is contained in:
commit
0eaf0df2ca
@ -53,12 +53,13 @@ Cu.import("resource:///modules/distribution.js");
|
||||
|
||||
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
|
||||
|
||||
// Check to see if bookmarks need backing up once per
|
||||
// day on 1 hour idle.
|
||||
const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
|
||||
|
||||
// Backup bookmarks once every 24 hours.
|
||||
const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
|
||||
// We try to backup bookmarks at idle times, to avoid doing that at shutdown.
|
||||
// Number of idle seconds before trying to backup bookmarks. 15 minutes.
|
||||
const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
|
||||
// Minimum interval in milliseconds between backups.
|
||||
const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000;
|
||||
// Maximum number of backups to create. Old ones will be purged.
|
||||
const BOOKMARKS_BACKUP_MAX_BACKUPS = 10;
|
||||
|
||||
// Factory object
|
||||
const BrowserGlueServiceFactory = {
|
||||
@ -76,29 +77,21 @@ const BrowserGlueServiceFactory = {
|
||||
|
||||
function BrowserGlue() {
|
||||
|
||||
this.__defineGetter__("_prefs", function() {
|
||||
delete this._prefs;
|
||||
return this._prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_prefs",
|
||||
"@mozilla.org/preferences-service;1",
|
||||
"nsIPrefBranch");
|
||||
|
||||
this.__defineGetter__("_bundleService", function() {
|
||||
delete this._bundleService;
|
||||
return this._bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_bundleService",
|
||||
"@mozilla.org/intl/stringbundle;1",
|
||||
"nsIStringBundleService");
|
||||
|
||||
this.__defineGetter__("_idleService", function() {
|
||||
delete this._idleService;
|
||||
return this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
|
||||
getService(Ci.nsIIdleService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_idleService",
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
"nsIIdleService");
|
||||
|
||||
this.__defineGetter__("_observerService", function() {
|
||||
delete this._observerService;
|
||||
return this._observerService = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_observerService",
|
||||
"@mozilla.org/observer-service;1",
|
||||
"nsIObserverService");
|
||||
|
||||
this._init();
|
||||
}
|
||||
@ -112,6 +105,10 @@ function BrowserGlue() {
|
||||
BrowserGlue.prototype = {
|
||||
|
||||
_saveSession: false,
|
||||
_isIdleObserver: false,
|
||||
_isPlacesInitObserver: false,
|
||||
_isPlacesLockedObserver: false,
|
||||
_isPlacesDatabaseLocked: false,
|
||||
|
||||
_setPrefToSaveSession: function()
|
||||
{
|
||||
@ -177,20 +174,21 @@ BrowserGlue.prototype = {
|
||||
case "places-init-complete":
|
||||
this._initPlaces();
|
||||
this._observerService.removeObserver(this, "places-init-complete");
|
||||
this._isPlacesInitObserver = false;
|
||||
// no longer needed, since history was initialized completely.
|
||||
this._observerService.removeObserver(this, "places-database-locked");
|
||||
this._isPlacesLockedObserver = false;
|
||||
break;
|
||||
case "places-database-locked":
|
||||
this._isPlacesDatabaseLocked = true;
|
||||
// stop observing, so further attempts to load history service
|
||||
// do not show the prompt.
|
||||
this._observerService.removeObserver(this, "places-database-locked");
|
||||
this._isPlacesLockedObserver = false;
|
||||
break;
|
||||
case "idle":
|
||||
if (this._idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
|
||||
// Back up bookmarks.
|
||||
this._archiveBookmarks();
|
||||
}
|
||||
if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000)
|
||||
this._backupBookmarks();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -213,7 +211,9 @@ BrowserGlue.prototype = {
|
||||
#endif
|
||||
osvr.addObserver(this, "session-save", false);
|
||||
osvr.addObserver(this, "places-init-complete", false);
|
||||
this._isPlacesInitObserver = true;
|
||||
osvr.addObserver(this, "places-database-locked", false);
|
||||
this._isPlacesLockedObserver = true;
|
||||
},
|
||||
|
||||
// cleanup (called on application shutdown)
|
||||
@ -227,12 +227,18 @@ BrowserGlue.prototype = {
|
||||
osvr.removeObserver(this, "sessionstore-windows-restored");
|
||||
osvr.removeObserver(this, "browser:purge-session-history");
|
||||
osvr.removeObserver(this, "quit-application-requested");
|
||||
osvr.removeObserver(this, "quit-application-granted");
|
||||
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
|
||||
osvr.removeObserver(this, "browser-lastwindow-close-requested");
|
||||
osvr.removeObserver(this, "browser-lastwindow-close-granted");
|
||||
#endif
|
||||
osvr.removeObserver(this, "quit-application-granted");
|
||||
osvr.removeObserver(this, "session-save");
|
||||
if (this._isIdleObserver)
|
||||
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
||||
if (this._isPlacesInitObserver)
|
||||
osvr.removeObserver(this, "places-init-complete");
|
||||
if (this._isPlacesLockedObserver)
|
||||
osvr.removeObserver(this, "places-database-locked");
|
||||
},
|
||||
|
||||
_onAppDefaults: function()
|
||||
@ -288,7 +294,8 @@ BrowserGlue.prototype = {
|
||||
_onProfileShutdown: function()
|
||||
{
|
||||
this._shutdownPlaces();
|
||||
this._idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
|
||||
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
||||
this._isIdleObserver = false;
|
||||
this.Sanitizer.onShutdown();
|
||||
},
|
||||
|
||||
@ -592,8 +599,8 @@ BrowserGlue.prototype = {
|
||||
restoreDefaultBookmarks =
|
||||
this._prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
|
||||
if (restoreDefaultBookmarks) {
|
||||
// Ensure that we already have a bookmarks backup for today
|
||||
this._archiveBookmarks();
|
||||
// Ensure that we already have a bookmarks backup for today.
|
||||
this._backupBookmarks();
|
||||
importBookmarks = true;
|
||||
}
|
||||
} catch(ex) {}
|
||||
@ -603,10 +610,10 @@ BrowserGlue.prototype = {
|
||||
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
|
||||
// get latest JSON backup
|
||||
Cu.import("resource://gre/modules/utils.js");
|
||||
var bookmarksBackupFile = PlacesUtils.getMostRecentBackup();
|
||||
if (bookmarksBackupFile && bookmarksBackupFile.leafName.match("\.json$")) {
|
||||
var bookmarksBackupFile = PlacesUtils.backups.getMostRecent("json");
|
||||
if (bookmarksBackupFile) {
|
||||
// restore from JSON backup
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(bookmarksBackupFile);
|
||||
importBookmarks = false;
|
||||
}
|
||||
else {
|
||||
@ -683,29 +690,29 @@ BrowserGlue.prototype = {
|
||||
|
||||
// Initialize bookmark archiving on idle.
|
||||
// Once a day, either on idle or shutdown, bookmarks are backed up.
|
||||
this._idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
|
||||
if (!this._isIdleObserver) {
|
||||
this._idleService.addIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
||||
this._isIdleObserver = true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Places shut-down tasks
|
||||
* - back up and archive bookmarks
|
||||
* - export bookmarks as HTML, if so configured
|
||||
* - back up bookmarks if needed.
|
||||
* - export bookmarks as HTML, if so configured.
|
||||
*
|
||||
* Note: quit-application-granted notification is received twice
|
||||
* so replace this method with a no-op when first called.
|
||||
*/
|
||||
_shutdownPlaces: function bg__shutdownPlaces() {
|
||||
// Backup and archive Places bookmarks.
|
||||
this._archiveBookmarks();
|
||||
this._backupBookmarks();
|
||||
|
||||
// Backup bookmarks to bookmarks.html to support apps that depend
|
||||
// on the legacy format.
|
||||
var autoExportHTML = false;
|
||||
try {
|
||||
autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML");
|
||||
} catch(ex) {
|
||||
Components.utils.reportError(ex);
|
||||
}
|
||||
} catch(ex) { /* Don't export */ }
|
||||
|
||||
if (autoExportHTML) {
|
||||
Cc["@mozilla.org/browser/places/import-export-service;1"].
|
||||
@ -715,23 +722,24 @@ BrowserGlue.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Back up and archive bookmarks
|
||||
* Backup bookmarks if needed.
|
||||
*/
|
||||
_archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
|
||||
_backupBookmarks: function nsBrowserGlue__backupBookmarks() {
|
||||
Cu.import("resource://gre/modules/utils.js");
|
||||
|
||||
var lastBackup = PlacesUtils.getMostRecentBackup();
|
||||
let lastBackupFile = PlacesUtils.backups.getMostRecent();
|
||||
|
||||
// Backup bookmarks if there aren't any backups or
|
||||
// they haven't been backed up in the last 24 hrs.
|
||||
if (!lastBackup ||
|
||||
Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
|
||||
var maxBackups = 5;
|
||||
// Backup bookmarks if there are no backups or the maximum interval between
|
||||
// backups elapsed.
|
||||
if (!lastBackupFile ||
|
||||
new Date() - PlacesUtils.backups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL) {
|
||||
let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
|
||||
try {
|
||||
maxBackups = this._prefs.getIntPref("browser.bookmarks.max_backups");
|
||||
} catch(ex) {}
|
||||
}
|
||||
catch(ex) { /* Use default. */ }
|
||||
|
||||
PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
|
||||
PlacesUtils.backups.create(maxBackups); // Don't force creation.
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -423,54 +423,36 @@ var PlacesOrganizer = {
|
||||
* Populates the restore menu with the dates of the backups available.
|
||||
*/
|
||||
populateRestoreMenu: function PO_populateRestoreMenu() {
|
||||
var restorePopup = document.getElementById("fileRestorePopup");
|
||||
let restorePopup = document.getElementById("fileRestorePopup");
|
||||
|
||||
var dateSvc = Cc["@mozilla.org/intl/scriptabledateformat;1"].
|
||||
let dateSvc = Cc["@mozilla.org/intl/scriptabledateformat;1"].
|
||||
getService(Ci.nsIScriptableDateFormat);
|
||||
|
||||
// remove existing menu items
|
||||
// last item is the restoreFromFile item
|
||||
// Remove existing menu items. Last item is the restoreFromFile item.
|
||||
while (restorePopup.childNodes.length > 1)
|
||||
restorePopup.removeChild(restorePopup.firstChild);
|
||||
|
||||
// get list of files
|
||||
var localizedFilename = PlacesUtils.getString("bookmarksArchiveFilename");
|
||||
var localizedFilenamePrefix = localizedFilename.substr(0, localizedFilename.indexOf("-"));
|
||||
var fileList = [];
|
||||
var files = this.bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
var f = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
var rx = new RegExp("^(bookmarks|" + localizedFilenamePrefix +
|
||||
")-([0-9]{4}-[0-9]{2}-[0-9]{2})\.json$");
|
||||
if (!f.isHidden() && f.leafName.match(rx)) {
|
||||
var date = f.leafName.match(rx)[2].replace(/-/g, "/");
|
||||
var dateObj = new Date(date);
|
||||
fileList.push({date: dateObj, filename: f.leafName});
|
||||
}
|
||||
}
|
||||
|
||||
fileList.sort(function PO_fileList_compare(a, b) {
|
||||
return b.date - a.date;
|
||||
});
|
||||
|
||||
if (fileList.length == 0)
|
||||
let backupFiles = PlacesUtils.backups.entries;
|
||||
if (backupFiles.length == 0)
|
||||
return;
|
||||
|
||||
// populate menu
|
||||
for (var i = 0; i < fileList.length; i++) {
|
||||
var m = restorePopup.insertBefore
|
||||
(document.createElement("menuitem"),
|
||||
document.getElementById("restoreFromFile"));
|
||||
// Populate menu with backups.
|
||||
for (let i = 0; i < backupFiles.length; i++) {
|
||||
let backupDate = PlacesUtils.backups.getDateForFile(backupFiles[i]);
|
||||
let m = restorePopup.insertBefore(document.createElement("menuitem"),
|
||||
document.getElementById("restoreFromFile"));
|
||||
m.setAttribute("label",
|
||||
dateSvc.FormatDate("",
|
||||
Ci.nsIScriptableDateFormat.dateFormatLong,
|
||||
fileList[i].date.getFullYear(),
|
||||
fileList[i].date.getMonth() + 1,
|
||||
fileList[i].date.getDate()));
|
||||
m.setAttribute("value", fileList[i].filename);
|
||||
backupDate.getFullYear(),
|
||||
backupDate.getMonth() + 1,
|
||||
backupDate.getDate()));
|
||||
m.setAttribute("value", backupFiles[i].leafName);
|
||||
m.setAttribute("oncommand",
|
||||
"PlacesOrganizer.onRestoreMenuItemClick(this);");
|
||||
}
|
||||
|
||||
// Add the restoreFromFile item.
|
||||
restorePopup.insertBefore(document.createElement("menuseparator"),
|
||||
document.getElementById("restoreFromFile"));
|
||||
},
|
||||
@ -479,14 +461,14 @@ var PlacesOrganizer = {
|
||||
* Called when a menuitem is selected from the restore menu.
|
||||
*/
|
||||
onRestoreMenuItemClick: function PO_onRestoreMenuItemClick(aMenuItem) {
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var bookmarksFile = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
bookmarksFile.append("bookmarkbackups");
|
||||
bookmarksFile.append(aMenuItem.getAttribute("value"));
|
||||
if (!bookmarksFile.exists())
|
||||
return;
|
||||
this.restoreBookmarksFromFile(bookmarksFile);
|
||||
let backupName = aMenuItem.getAttribute("value");
|
||||
let backupFiles = PlacesUtils.backups.entries;
|
||||
for (let i = 0; i < backupFiles.length; i++) {
|
||||
if (backupFiles[i].leafName == backupName) {
|
||||
this.restoreBookmarksFromFile(backupFiles[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -529,7 +511,7 @@ var PlacesOrganizer = {
|
||||
return;
|
||||
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(aFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(aFile);
|
||||
}
|
||||
catch(ex) {
|
||||
this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreParseError"));
|
||||
@ -562,30 +544,10 @@ var PlacesOrganizer = {
|
||||
var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
|
||||
fp.displayDirectory = backupsDir;
|
||||
|
||||
fp.defaultString = PlacesUtils.getBackupFilename();
|
||||
fp.defaultString = PlacesUtils.backups.getFilenameForDate();
|
||||
|
||||
if (fp.show() != Ci.nsIFilePicker.returnCancel) {
|
||||
PlacesUtils.backupBookmarksToFile(fp.file);
|
||||
|
||||
// copy new backup to /backups dir (bug 424389)
|
||||
var latestBackup = PlacesUtils.getMostRecentBackup();
|
||||
if (!latestBackup || latestBackup != fp.file) {
|
||||
latestBackup.remove(false);
|
||||
var name = PlacesUtils.getBackupFilename();
|
||||
fp.file.copyTo(this.bookmarksBackupDir, name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get bookmarksBackupDir() {
|
||||
delete this.bookmarksBackupDir;
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists())
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
return this.bookmarksBackupDir = bookmarksBackupDir;
|
||||
if (fp.show() != Ci.nsIFilePicker.returnCancel)
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(fp.file);
|
||||
},
|
||||
|
||||
_paneDisabled: false,
|
||||
|
@ -157,10 +157,14 @@ const FILENAME_BOOKMARKS_HTML = "bookmarks.html";
|
||||
let backup_date = new Date().toLocaleFormat("%Y-%m-%d");
|
||||
const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json";
|
||||
|
||||
// Smart bookmarks constants
|
||||
// Smart bookmarks constants.
|
||||
const SMART_BOOKMARKS_VERSION = 2;
|
||||
const SMART_BOOKMARKS_ON_TOOLBAR = 1;
|
||||
const SMART_BOOKMARKS_ON_MENU = 2;
|
||||
const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator.
|
||||
|
||||
// Default bookmarks constants.
|
||||
const DEFAULT_BOOKMARKS_ON_TOOLBAR = 2;
|
||||
const DEFAULT_BOOKMARKS_ON_MENU = 3;
|
||||
|
||||
/**
|
||||
* Creates a bookmarks.html file in the profile folder from a given source file.
|
||||
|
@ -99,11 +99,11 @@ function run_test() {
|
||||
// 3. import bookmarks.exported.json
|
||||
// 4. run the test-suite
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
LOG("exported json");
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
LOG("imported json");
|
||||
validate();
|
||||
|
@ -80,10 +80,10 @@ var tests = [
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.json");
|
||||
addBookmarks();
|
||||
PlacesUtils.backupBookmarksToFile(this.file);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(this.file);
|
||||
remove_all_bookmarks();
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
@ -100,7 +100,7 @@ var tests = [
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.json");
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
@ -118,7 +118,7 @@ var tests = [
|
||||
this.file = dirSvc.get("ProfD", Ci.nsILocalFile);
|
||||
this.file.append("this file doesn't exist because nobody created it");
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
|
||||
do_throw(" Restore should have failed");
|
||||
}
|
||||
catch (e) {}
|
||||
|
@ -75,16 +75,16 @@ tests.push({
|
||||
do_check_eq(bs.getIdForItemAt(bs.toolbarFolder, 0), -1);
|
||||
// Sanity check: we should not have any bookmark on the menu.
|
||||
do_check_eq(bs.getIdForItemAt(bs.bookmarksMenuFolder, 0), -1);
|
||||
|
||||
|
||||
// Set preferences.
|
||||
ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
|
||||
// Force nsBrowserGlue::_initPlaces().
|
||||
os.notifyObservers(null, TOPIC_PLACES_INIT_COMPLETE, null);
|
||||
|
||||
// Count items on toolbar.
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR);
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
|
||||
// Count items on menu (+1 for the separator).
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + 1);
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
|
||||
|
||||
// Check version has been updated.
|
||||
do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION), SMART_BOOKMARKS_VERSION);
|
||||
@ -113,9 +113,9 @@ tests.push({
|
||||
os.notifyObservers(null, TOPIC_PLACES_INIT_COMPLETE, null);
|
||||
|
||||
// Count items on toolbar.
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR);
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
|
||||
// Count items on menu (+1 for the separator).
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + 1);
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
|
||||
|
||||
// check smart bookmark has been replaced, itemId has changed.
|
||||
itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
|
||||
@ -138,15 +138,15 @@ tests.push({
|
||||
// Set preferences.
|
||||
ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
|
||||
// Remove toolbar's smart bookmarks
|
||||
bs.removeFolderChildren(bs.toolbarFolder);
|
||||
bs.removeItem(bs.getIdForItemAt(bs.toolbarFolder, 0));
|
||||
|
||||
// Force nsBrowserGlue::_initPlaces().
|
||||
os.notifyObservers(null, TOPIC_PLACES_INIT_COMPLETE, null);
|
||||
|
||||
// Count items on toolbar, we should not have recreated the smart bookmark.
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), 0);
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), DEFAULT_BOOKMARKS_ON_TOOLBAR);
|
||||
// Count items on menu (+1 for the separator).
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + 1);
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
|
||||
|
||||
// Check version has been updated.
|
||||
do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION), SMART_BOOKMARKS_VERSION);
|
||||
@ -167,9 +167,9 @@ tests.push({
|
||||
os.notifyObservers(null, TOPIC_PLACES_INIT_COMPLETE, null);
|
||||
|
||||
// Count items on toolbar, we should not have recreated the smart bookmark.
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR);
|
||||
do_check_eq(countFolderChildren(bs.toolbarFolder), SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
|
||||
// Count items on menu (+1 for the separator).
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + 1);
|
||||
do_check_eq(countFolderChildren(bs.bookmarksMenuFolder), SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
|
||||
|
||||
// Check version has been updated.
|
||||
do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION), SMART_BOOKMARKS_VERSION);
|
||||
@ -193,23 +193,19 @@ function countFolderChildren(aFolderItemId) {
|
||||
function finish_test() {
|
||||
// Clean up database from all bookmarks.
|
||||
remove_all_bookmarks();
|
||||
// Simulate application closing to remove the idle observer and avoid leaks.
|
||||
os.notifyObservers(null, "quit-application-granted", null);
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
var testIndex = 0;
|
||||
function next_test() {
|
||||
// Simulate application closing to remove the idle observer and avoid leaks.
|
||||
os.notifyObservers(null, "quit-application-granted", null);
|
||||
|
||||
// nsBrowserGlue stops observing topics after first notification,
|
||||
// so we add back the observer to test additional runs.
|
||||
os.addObserver(bg, TOPIC_PLACES_INIT_COMPLETE, false);
|
||||
|
||||
// Execute next test.
|
||||
var test = tests.shift();
|
||||
dump("\nTEST " + (++testIndex) + ": " + test.description);
|
||||
let test = tests.shift();
|
||||
print("\nTEST " + (++testIndex) + ": " + test.description);
|
||||
test.exec();
|
||||
}
|
||||
|
||||
|
@ -1865,8 +1865,7 @@ nsDocument::Init()
|
||||
|
||||
NS_NewCSSLoader(this, &mCSSLoader);
|
||||
NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
|
||||
// Assume we're not HTML and not quirky, until we know otherwise
|
||||
mCSSLoader->SetCaseSensitive(PR_TRUE);
|
||||
// Assume we're not quirky, until we know otherwise
|
||||
mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
|
||||
mNodeInfoManager = new nsNodeInfoManager();
|
||||
|
@ -2683,6 +2683,10 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
// anonymous content that the document is changing.
|
||||
document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
|
||||
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
document->ForgetLink(this);
|
||||
}
|
||||
|
||||
document->ClearBoxObjectFor(this);
|
||||
}
|
||||
|
||||
@ -4294,6 +4298,20 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
||||
"Don't call SetAttr with unknown namespace");
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
|
||||
// XLink URI(s) might be changing. Drop the link from the map. If it
|
||||
// is still style relevant it will be re-added by
|
||||
// nsStyleUtil::IsLink. Make sure to keep the style system
|
||||
// consistent so this remains true! In particular if the style system
|
||||
// were to get smarter and not restyling an XLink element if the href
|
||||
// doesn't change in a "significant" way, we'd need to do the same
|
||||
// significance check here.
|
||||
if (doc) {
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString oldValue;
|
||||
PRBool modification = PR_FALSE;
|
||||
PRBool hasListeners = aNotify &&
|
||||
@ -4608,6 +4626,12 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
|
||||
if (document && kNameSpaceID_XLink == aNameSpaceID &&
|
||||
nsGkAtoms::href == aName) {
|
||||
// XLink URI might be changing.
|
||||
document->ForgetLink(this);
|
||||
}
|
||||
|
||||
// When notifying, make sure to keep track of states whose value
|
||||
// depends solely on the value of an attribute.
|
||||
PRUint32 stateMask;
|
||||
|
@ -274,10 +274,8 @@ nsHTMLDocument::Init()
|
||||
nsresult rv = nsDocument::Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now reset the case-sensitivity of the CSSLoader, since we default
|
||||
// to being HTML, not XHTML. Also, reset the compatibility mode to
|
||||
// match our compat mode.
|
||||
CSSLoader()->SetCaseSensitive(!IsHTML());
|
||||
// Now reset the compatibility mode of the CSSLoader
|
||||
// to match our compat mode.
|
||||
CSSLoader()->SetCompatibilityMode(mCompatMode);
|
||||
|
||||
PrePopulateIdentifierMap();
|
||||
@ -682,7 +680,6 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
}
|
||||
#endif
|
||||
|
||||
CSSLoader()->SetCaseSensitive(!IsHTML());
|
||||
CSSLoader()->SetCompatibilityMode(mCompatMode);
|
||||
|
||||
PRBool needsParser = PR_TRUE;
|
||||
|
@ -103,57 +103,6 @@ nsMathMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsMathMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
{
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsMathMLElementBase::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMathMLElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
|
||||
// XLink URI(s) might be changing. Drop the link from the map. If it
|
||||
// is still style relevant it will be re-added by
|
||||
// nsStyleUtil::IsLink. Make sure to keep the style system
|
||||
// consistent so this remains true! In particular if the style system
|
||||
// were to get smarter and not restyling an XLink element if the href
|
||||
// doesn't change in a "significant" way, we'd need to do the same
|
||||
// significance check here.
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
return nsMathMLElementBase::SetAttr(aNamespaceID, aName, aPrefix, aValue,
|
||||
aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMathMLElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
// XLink URI might be changing.
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
return nsMathMLElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMathMLElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
|
@ -70,16 +70,6 @@ public:
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
|
||||
virtual nsresult SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
PRBool aNotify);
|
||||
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
|
@ -130,6 +130,7 @@ _TEST_FILES += \
|
||||
bug504613.ogv \
|
||||
bug504644.ogv \
|
||||
bug506094.ogv \
|
||||
bug516323.ogv \
|
||||
dirac.ogg \
|
||||
seek.ogv \
|
||||
short-video.ogv \
|
||||
|
BIN
content/media/test/bug516323.ogv
Normal file
BIN
content/media/test/bug516323.ogv
Normal file
Binary file not shown.
@ -41,6 +41,8 @@ var gPlayTests = [
|
||||
{ name:"short-video.ogv", type:"video/ogg", duration:1.081 },
|
||||
// First Theora data packet is zero bytes.
|
||||
{ name:"bug504613.ogv", type:"video/ogg" },
|
||||
// Multiple audio streams.
|
||||
{ name:"bug516323.ogv", type:"video/ogg", duration:4.424 },
|
||||
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
@ -122,57 +122,6 @@ nsSVGAElement::GetTarget(nsIDOMSVGAnimatedString * *aTarget)
|
||||
//----------------------------------------------------------------------
|
||||
// nsIContent methods
|
||||
|
||||
void
|
||||
nsSVGAElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
{
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
nsIDocument *doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGAElementBase::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGAElement::SetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
|
||||
nsIAtom *aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
|
||||
// XLink URI(s) might be changing. Drop the link from the map. If it
|
||||
// is still style relevant it will be re-added by
|
||||
// nsStyleUtil::IsLink. Make sure to keep the style system
|
||||
// consistent so this remains true! In particular if the style system
|
||||
// were to get smarter and not restyling an XLink element if the href
|
||||
// doesn't change in a "significant" way, we'd need to do the same
|
||||
// significance check here.
|
||||
nsIDocument *doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
return nsSVGAElementBase::SetAttr(aNamespaceID, aName, aPrefix, aValue,
|
||||
aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGAElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
|
||||
nsIDocument *doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
// XLink URI might be changing.
|
||||
doc->ForgetLink(this);
|
||||
}
|
||||
}
|
||||
|
||||
return nsSVGAElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
|
||||
}
|
||||
|
||||
nsLinkState
|
||||
nsSVGAElement::GetLinkState() const
|
||||
{
|
||||
|
@ -75,13 +75,6 @@ public:
|
||||
NS_IMETHOD LinkRemoved() { return NS_OK; }
|
||||
|
||||
// nsIContent
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
virtual nsresult SetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
|
||||
nsIAtom *aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
|
||||
PRBool aNotify);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsLink(nsIURI** aURI) const;
|
||||
virtual void GetLinkTarget(nsAString& aTarget);
|
||||
|
@ -313,7 +313,6 @@ protected:
|
||||
if (!sCSSParser) {
|
||||
CallCreateInstance(kCSSParserCID, &sCSSParser);
|
||||
if (sCSSParser) {
|
||||
sCSSParser->SetCaseSensitive(PR_TRUE);
|
||||
sCSSParser->SetQuirkMode(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -460,9 +460,7 @@ gfxMacPlatformFontList::InitSingleFaceList()
|
||||
gfxFontEntry *fontEntry = LookupLocalFont(nsnull, singleFaceFonts[i]);
|
||||
if (fontEntry) {
|
||||
nsAutoString familyName, key;
|
||||
if (!GetStandardFamilyName(singleFaceFonts[i], familyName)) {
|
||||
familyName = singleFaceFonts[i];
|
||||
}
|
||||
familyName = singleFaceFonts[i];
|
||||
GenerateFontListKey(familyName, key);
|
||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontlist-singleface) family name: %s, key: %s\n",
|
||||
NS_ConvertUTF16toUTF8(familyName).get(), NS_ConvertUTF16toUTF8(key).get()));
|
||||
|
@ -223,7 +223,7 @@ function run_int64_tests(library) {
|
||||
// here, since it's binary-compatible.)
|
||||
var test_ui64_ui64 = library.declare("test_i64_i64", Types.DEFAULT, Types.UINT64, Types.UINT64);
|
||||
#ifndef XP_WIN
|
||||
do_check_eq(test_ui64_ui64(0xffffffffffff000), 0xfffffffffffff000);
|
||||
do_check_eq(test_ui64_ui64(0xfffffffffffff000), 0xfffffffffffff000);
|
||||
#endif
|
||||
do_check_throws(function () { test_ui64_ui64(0x10000000000000000); }, TypeError);
|
||||
do_check_throws(function () { test_ui64_ui64(-1); }, TypeError);
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "nsIDOMHTMLTableCaptionElem.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
@ -1712,6 +1713,7 @@ nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
|
||||
nsCOMPtr<nsIAtom> attrName;
|
||||
PRInt32 attrNameSpace = kNameSpaceID_None;
|
||||
nsAutoString contentString(data.mContent.mString);
|
||||
|
||||
PRInt32 barIndex = contentString.FindChar('|'); // CSS namespace delimiter
|
||||
if (-1 != barIndex) {
|
||||
nsAutoString nameSpaceVal;
|
||||
@ -1720,10 +1722,16 @@ nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
|
||||
attrNameSpace = nameSpaceVal.ToInteger(&error, 10);
|
||||
contentString.Cut(0, barIndex + 1);
|
||||
if (contentString.Length()) {
|
||||
if (mDocument->IsHTML() && aParentContent->IsNodeOfType(nsINode::eHTML)) {
|
||||
ToLowerCase(contentString);
|
||||
}
|
||||
attrName = do_GetAtom(contentString);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mDocument->IsHTML() && aParentContent->IsNodeOfType(nsINode::eHTML)) {
|
||||
ToLowerCase(contentString);
|
||||
}
|
||||
attrName = do_GetAtom(contentString);
|
||||
}
|
||||
|
||||
@ -1736,7 +1744,7 @@ nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
|
||||
attrNameSpace, attrName, getter_AddRefs(content));
|
||||
return content.forget();
|
||||
}
|
||||
|
||||
|
||||
case eStyleContentType_Counter:
|
||||
case eStyleContentType_Counters:
|
||||
{
|
||||
|
@ -5304,7 +5304,8 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
|
||||
CanvasFrame* canvasFrame =
|
||||
do_QueryFrame(rootScrollableFrame->GetScrolledFrame());
|
||||
if (canvasFrame) {
|
||||
canvasArea = canvasFrame->CanvasArea();
|
||||
canvasArea =
|
||||
canvasFrame->CanvasArea() + builder.ToReferenceFrame(canvasFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,7 @@ _TEST_FILES = \
|
||||
test_bug435293-skew.html \
|
||||
test_bug495648.xul \
|
||||
test_bug514127.html \
|
||||
test_bug518777.html \
|
||||
test_scrolling.html \
|
||||
$(NULL)
|
||||
# test_bug396024.html is currently disabled because it interacts badly with
|
||||
|
52
layout/base/tests/test_bug518777.html
Normal file
52
layout/base/tests/test_bug518777.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=518777
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 518777</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518777">Mozilla Bug 518777</a></p>
|
||||
|
||||
<!--
|
||||
iframe source is
|
||||
<html><body onload='window.scrollTo(0,99999999); document.documentElement.offsetWidth; window.parent.dotest();' style='background: rgb(0,0,255); width: 100px; height: 50100px;'></body></html>
|
||||
-->
|
||||
<iframe id="source" width="50" height="50"
|
||||
src="data:text/html,%3Chtml%3E%3Cbody%20onload%3D%27window.scrollTo%280%2C99999999%29%3B%20document.documentElement.offsetWidth%3B%20window.parent.dotest%28%29%3B%27%20style%3D%27background%3A%20rgb%280%2C0%2C255%29%3B%20width%3A%20100px%3B%20height%3A%2050100px%3B%27%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
|
||||
<canvas id="scratch" width="50" height="50"></canvas>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 518777 **/
|
||||
|
||||
function dotest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var canvas = document.getElementById('scratch');
|
||||
var source = document.getElementById('source').contentWindow;
|
||||
var context = canvas.getContext("2d");
|
||||
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
context.drawWindow(source, 25, 25, canvas.width, canvas.height,
|
||||
"transparent");
|
||||
|
||||
var data = context.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||
var failed = false;
|
||||
for (var i = 0; i < data.length; i+=4) {
|
||||
if (data[i] != 0 || data[i+1] != 0 || data[i+2] != 255 || data[i+3] != 255) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(!failed, "all pixels blue");
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -304,6 +304,7 @@ nsBlockFrame::Destroy()
|
||||
nsLineList* overflowLines = RemoveOverflowLines();
|
||||
if (overflowLines) {
|
||||
nsLineBox::DeleteLineList(presContext, *overflowLines);
|
||||
delete overflowLines;
|
||||
}
|
||||
|
||||
{
|
||||
@ -2117,6 +2118,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||
// stored in the property (because the property has the
|
||||
// invariant that the list is never empty).
|
||||
nextInFlow->SetOverflowLines(overflowLines);
|
||||
} else {
|
||||
delete overflowLines;
|
||||
}
|
||||
collectOverflowFloats = PR_TRUE;
|
||||
}
|
||||
@ -2552,8 +2555,12 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
||||
aState.FreeLineBox(fromLine);
|
||||
|
||||
// Put any remaining overflow lines back.
|
||||
if (aFromOverflowLine && !fromLineList->empty()) {
|
||||
aFromContainer->SetOverflowLines(fromLineList);
|
||||
if (aFromOverflowLine) {
|
||||
if (!fromLineList->empty()) {
|
||||
aFromContainer->SetOverflowLines(fromLineList);
|
||||
} else {
|
||||
delete fromLineList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5312,6 +5319,8 @@ found_frame:;
|
||||
line = lineList->erase(line);
|
||||
if (!lineList->empty()) {
|
||||
SetOverflowLines(lineList);
|
||||
} else {
|
||||
delete lineList;
|
||||
}
|
||||
}
|
||||
cur->Destroy(presShell);
|
||||
@ -5448,6 +5457,8 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext,
|
||||
if (!lineList->empty()) {
|
||||
nsresult rv = SetOverflowLines(lineList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
delete lineList;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
7
layout/reftests/bugs/507762-1-ref.html
Normal file
7
layout/reftests/bugs/507762-1-ref.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<body>
|
||||
<span style="background-color: green">text</span>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/bugs/507762-1.html
Normal file
23
layout/reftests/bugs/507762-1.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
@namespace url(test);
|
||||
div {
|
||||
background-color: red;
|
||||
}
|
||||
div[mixedCase=true] {
|
||||
background-color: green !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function f() {
|
||||
var elem = document.createElementNS("test","div");
|
||||
elem.setAttribute("mixedCase",true);
|
||||
elem.appendChild(document.createTextNode("text"));
|
||||
document.getElementsByTagName("body")[0].appendChild(elem); }
|
||||
</script>
|
||||
</head>
|
||||
<body onload="f();">
|
||||
</body>
|
||||
</html>
|
7
layout/reftests/bugs/507762-2-ref.html
Normal file
7
layout/reftests/bugs/507762-2-ref.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<body>
|
||||
<div style="background-color: green">text</div>
|
||||
</body>
|
||||
</html>
|
22
layout/reftests/bugs/507762-2.html
Normal file
22
layout/reftests/bugs/507762-2.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
div {
|
||||
background-color: red;
|
||||
}
|
||||
div[mixedCase=true] {
|
||||
background-color: green !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function f() {
|
||||
var elem = document.createElement("div");
|
||||
elem.setAttribute("mixedcase",true);
|
||||
elem.appendChild(document.createTextNode("text"));
|
||||
document.getElementsByTagName("body")[0].appendChild(elem); }
|
||||
</script>
|
||||
</head>
|
||||
<body onload="f();">
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/bugs/507762-3.html
Normal file
23
layout/reftests/bugs/507762-3.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
@namespace url(test);
|
||||
div {
|
||||
background-color: green;
|
||||
}
|
||||
div[dir=RTL ]
|
||||
{background-color: red !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function f() {
|
||||
var elem = document.createElementNS("test","div");
|
||||
elem.setAttribute("dir","rtl");
|
||||
elem.appendChild(document.createTextNode("text"));
|
||||
document.getElementsByTagName("body")[0].appendChild(elem); }
|
||||
</script>
|
||||
</head>
|
||||
<body onload="f();">
|
||||
</body>
|
||||
</html>
|
22
layout/reftests/bugs/507762-4.html
Normal file
22
layout/reftests/bugs/507762-4.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
div {
|
||||
background-color: red;
|
||||
}
|
||||
div[dir=ltr]
|
||||
{background-color: green !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function f() {
|
||||
var elem = document.createElement("div");
|
||||
elem.setAttribute("dir","LTR");
|
||||
elem.appendChild(document.createTextNode("text"));
|
||||
document.getElementsByTagName("body")[0].appendChild(elem); }
|
||||
</script>
|
||||
</head>
|
||||
<body onload="f();">
|
||||
</body>
|
||||
</html>
|
@ -1309,6 +1309,10 @@ fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") == 488692-1.html 488692-1-ref.html # needs
|
||||
== 507187-1.html 507187-1-ref.html
|
||||
== 507487-1.html 507487-1-ref.html
|
||||
== 507487-2.xhtml 507487-2-ref.xhtml
|
||||
== 507762-1.html 507762-1-ref.html
|
||||
== 507762-2.html 507762-2-ref.html
|
||||
== 507762-3.html 507762-1-ref.html
|
||||
== 507762-4.html 507762-2-ref.html
|
||||
== 508919-1.xhtml 508919-1-ref.xhtml
|
||||
== 509155-1.xhtml 509155-1-ref.xhtml
|
||||
== 512410.html 512410-ref.html
|
||||
|
@ -274,7 +274,6 @@ nsCOMArray<nsICSSParser>* CSSLoaderImpl::gParsers = nsnull;
|
||||
|
||||
CSSLoaderImpl::CSSLoaderImpl(void)
|
||||
: mDocument(nsnull),
|
||||
mCaseSensitive(PR_FALSE),
|
||||
mEnabled(PR_TRUE),
|
||||
mCompatMode(eCompatibility_FullStandards),
|
||||
mDatasToNotifyOn(0)
|
||||
@ -331,13 +330,6 @@ CSSLoaderImpl::DropDocumentReference(void)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::SetCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
mCaseSensitive = aCaseSensitive;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::SetCompatibilityMode(nsCompatibility aCompatMode)
|
||||
{
|
||||
@ -431,7 +423,6 @@ CSSLoaderImpl::GetParserFor(nsICSSStyleSheet* aSheet,
|
||||
}
|
||||
|
||||
if (*aParser) {
|
||||
(*aParser)->SetCaseSensitive(mCaseSensitive);
|
||||
(*aParser)->SetQuirkMode(mCompatMode == eCompatibility_NavQuirks);
|
||||
if (aSheet) {
|
||||
(*aParser)->SetStyleSheet(aSheet);
|
||||
|
@ -318,7 +318,6 @@ public:
|
||||
NS_IMETHOD Init(nsIDocument* aDocument);
|
||||
NS_IMETHOD DropDocumentReference(void);
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive);
|
||||
NS_IMETHOD SetCompatibilityMode(nsCompatibility aCompatMode);
|
||||
NS_IMETHOD SetPreferredSheet(const nsAString& aTitle);
|
||||
NS_IMETHOD GetPreferredSheet(nsAString& aTitle);
|
||||
@ -494,7 +493,6 @@ private:
|
||||
PRPackedBool mSyncCallback;
|
||||
#endif
|
||||
|
||||
PRPackedBool mCaseSensitive; // is document CSS case sensitive
|
||||
PRPackedBool mEnabled; // is enabled to load new styles
|
||||
nsCompatibility mCompatMode;
|
||||
nsString mPreferredSheet; // title of preferred sheet
|
||||
|
@ -161,8 +161,6 @@ public:
|
||||
|
||||
NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet);
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive);
|
||||
|
||||
NS_IMETHOD SetQuirkMode(PRBool aQuirkMode);
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
@ -625,9 +623,6 @@ protected:
|
||||
// ignore CSS comments.
|
||||
PRPackedBool mHTMLMediaMode : 1;
|
||||
|
||||
// True if tagnames and attributes are case-sensitive
|
||||
PRPackedBool mCaseSensitive : 1;
|
||||
|
||||
// This flag is set when parsing a non-box shorthand; it's used to not apply
|
||||
// some quirks during shorthand parsing
|
||||
PRPackedBool mParsingCompoundProperty : 1;
|
||||
@ -728,7 +723,6 @@ CSSParserImpl::CSSParserImpl()
|
||||
mNavQuirkMode(PR_FALSE),
|
||||
mUnsafeRulesEnabled(PR_FALSE),
|
||||
mHTMLMediaMode(PR_FALSE),
|
||||
mCaseSensitive(PR_FALSE),
|
||||
mParsingCompoundProperty(PR_FALSE),
|
||||
mUnresolvablePrefixException(PR_FALSE)
|
||||
#ifdef DEBUG
|
||||
@ -762,14 +756,6 @@ CSSParserImpl::SetStyleSheet(nsICSSStyleSheet* aSheet)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSParserImpl::SetCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
NS_ASSERTION(aCaseSensitive == PR_TRUE || aCaseSensitive == PR_FALSE, "bad PRBool value");
|
||||
mCaseSensitive = aCaseSensitive;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSParserImpl::SetQuirkMode(PRBool aQuirkMode)
|
||||
{
|
||||
@ -2709,7 +2695,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
|
||||
aSelector.SetTag(mToken.mIdent, mCaseSensitive);
|
||||
aSelector.SetTag(mToken.mIdent);
|
||||
}
|
||||
else if (mToken.IsSymbol('*')) { // universal selector
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
@ -2747,8 +2733,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||
}
|
||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
|
||||
aSelector.SetTag(mToken.mIdent, mCaseSensitive);
|
||||
aSelector.SetTag(mToken.mIdent);
|
||||
}
|
||||
else if (mToken.IsSymbol('*')) { // universal selector
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
@ -2762,7 +2747,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||
}
|
||||
else { // was element name
|
||||
SetDefaultNamespaceOnSelector(aSelector);
|
||||
aSelector.SetTag(buffer, mCaseSensitive);
|
||||
aSelector.SetTag(buffer);
|
||||
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
}
|
||||
@ -2781,7 +2766,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||
}
|
||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
aSelector.SetTag(mToken.mIdent, mCaseSensitive);
|
||||
aSelector.SetTag(mToken.mIdent);
|
||||
}
|
||||
else if (mToken.IsSymbol('*')) { // universal selector
|
||||
aDataMask |= SEL_MASK_ELEM;
|
||||
@ -2883,9 +2868,6 @@ CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||
return eSelectorParsingStatus_Error;
|
||||
}
|
||||
|
||||
if (! mCaseSensitive) {
|
||||
ToLowerCase(attr);
|
||||
}
|
||||
if (! GetToken(PR_TRUE)) { // premature EOF
|
||||
REPORT_UNEXPECTED_EOF(PEAttSelInnerEOF);
|
||||
return eSelectorParsingStatus_Error;
|
||||
@ -2939,11 +2921,12 @@ CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||
if (mToken.IsSymbol(']')) {
|
||||
PRBool isCaseSensitive = PR_TRUE;
|
||||
|
||||
// If we're parsing a style sheet for an HTML document, and
|
||||
// the attribute selector is for a non-namespaced attribute,
|
||||
// then check to see if it's one of the known attributes whose
|
||||
// VALUE is case-insensitive.
|
||||
if (!mCaseSensitive && nameSpaceID == kNameSpaceID_None) {
|
||||
// For cases when this style sheet is applied to an HTML
|
||||
// element in an HTML document, and the attribute selector is
|
||||
// for a non-namespaced attribute, then check to see if it's
|
||||
// one of the known attributes whose VALUE is
|
||||
// case-insensitive.
|
||||
if (nameSpaceID == kNameSpaceID_None) {
|
||||
static const char* caseInsensitiveHTMLAttribute[] = {
|
||||
// list based on http://www.w3.org/TR/html4/
|
||||
"lang",
|
||||
@ -4708,13 +4691,7 @@ CSSParserImpl::ParseAttr(nsCSSValue& aValue)
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (eCSSToken_Ident == mToken.mType) {
|
||||
if (mCaseSensitive) {
|
||||
attr.Append(mToken.mIdent);
|
||||
} else {
|
||||
nsAutoString buffer;
|
||||
ToLowerCase(mToken.mIdent, buffer);
|
||||
attr.Append(buffer);
|
||||
}
|
||||
attr.Append(mToken.mIdent);
|
||||
}
|
||||
else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||
@ -4723,12 +4700,7 @@ CSSParserImpl::ParseAttr(nsCSSValue& aValue)
|
||||
}
|
||||
}
|
||||
else { // no namespace
|
||||
if (mCaseSensitive) {
|
||||
attr = holdIdent;
|
||||
}
|
||||
else {
|
||||
ToLowerCase(holdIdent, attr);
|
||||
}
|
||||
attr = holdIdent;
|
||||
}
|
||||
}
|
||||
else if (mToken.IsSymbol('*')) { // namespace wildcard
|
||||
@ -4743,13 +4715,7 @@ CSSParserImpl::ParseAttr(nsCSSValue& aValue)
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (eCSSToken_Ident == mToken.mType) {
|
||||
if (mCaseSensitive) {
|
||||
attr.Append(mToken.mIdent);
|
||||
} else {
|
||||
nsAutoString buffer;
|
||||
ToLowerCase(mToken.mIdent, buffer);
|
||||
attr.Append(buffer);
|
||||
}
|
||||
attr.Append(mToken.mIdent);
|
||||
}
|
||||
else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||
|
@ -1167,7 +1167,7 @@ IsSignificantChild(nsIContent* aChild, PRBool aTextIsSignificant,
|
||||
// whose namespace and name match those of aAttrSelector. This function
|
||||
// performs comparisons on the value only, based on aAttrSelector->mFunction.
|
||||
static PRBool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
|
||||
const nsString& aValue)
|
||||
const nsString& aValue, PRBool isHTML)
|
||||
{
|
||||
NS_PRECONDITION(aAttrSelector, "Must have an attribute selector");
|
||||
|
||||
@ -1183,9 +1183,11 @@ static PRBool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
|
||||
|
||||
const nsDefaultStringComparator defaultComparator;
|
||||
const nsCaseInsensitiveStringComparator ciComparator;
|
||||
const nsStringComparator& comparator = aAttrSelector->mCaseSensitive
|
||||
const nsStringComparator& comparator =
|
||||
(aAttrSelector->mCaseSensitive || !isHTML)
|
||||
? static_cast<const nsStringComparator&>(defaultComparator)
|
||||
: static_cast<const nsStringComparator&>(ciComparator);
|
||||
|
||||
switch (aAttrSelector->mFunction) {
|
||||
case NS_ATTR_FUNC_EQUALS:
|
||||
return aValue.Equals(aAttrSelector->mValue, comparator);
|
||||
@ -1234,18 +1236,13 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
data.mNameSpaceID != aSelector->mNameSpace))
|
||||
return PR_FALSE;
|
||||
|
||||
if (aSelector->mLowercaseTag) {
|
||||
//If we tested that this is an HTML node in a text/html document and
|
||||
//had some tweaks in RuleHash, we could remove case-sensitivity from
|
||||
//style sheets.
|
||||
if (data.mIsHTMLContent) {
|
||||
if (data.mContentTag != aSelector->mLowercaseTag)
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
if (data.mContentTag != aSelector->mCasedTag)
|
||||
return PR_FALSE;
|
||||
}
|
||||
const PRBool isHTML =
|
||||
data.mIsHTMLContent && data.mContent->GetOwnerDoc()->IsHTML();
|
||||
|
||||
if (aSelector->mLowercaseTag &&
|
||||
(isHTML ? aSelector->mLowercaseTag : aSelector->mCasedTag) !=
|
||||
data.mContentTag) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
@ -1679,8 +1676,11 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
"aAttribute is set!");
|
||||
result = PR_TRUE;
|
||||
nsAttrSelector* attr = aSelector->mAttrList;
|
||||
nsIAtom* matchAttribute;
|
||||
|
||||
do {
|
||||
if (attr->mAttr == aAttribute) {
|
||||
matchAttribute = isHTML ? attr->mLowercaseAttr : attr->mCasedAttr;
|
||||
if (matchAttribute == aAttribute) {
|
||||
// XXX we should really have a namespace, not just an attr
|
||||
// name, in HasAttributeDependentStyle!
|
||||
result = PR_TRUE;
|
||||
@ -1701,7 +1701,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
const nsAttrName* attrName =
|
||||
data.mContent->GetAttrNameAt(i);
|
||||
NS_ASSERTION(attrName, "GetAttrCount lied or GetAttrNameAt failed");
|
||||
if (attrName->LocalName() != attr->mAttr) {
|
||||
if (attrName->LocalName() != matchAttribute) {
|
||||
continue;
|
||||
}
|
||||
if (attr->mFunction == NS_ATTR_FUNC_SET) {
|
||||
@ -1714,7 +1714,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
data.mContent->GetAttr(attrName->NamespaceID(),
|
||||
attrName->LocalName(), value);
|
||||
NS_ASSERTION(hasAttr, "GetAttrNameAt lied");
|
||||
result = AttrMatchesValue(attr, value);
|
||||
result = AttrMatchesValue(attr, value, isHTML);
|
||||
}
|
||||
|
||||
// At this point |result| has been set by us
|
||||
@ -1730,10 +1730,11 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
else if (attr->mFunction == NS_ATTR_FUNC_EQUALS) {
|
||||
result =
|
||||
data.mContent->
|
||||
AttrValueIs(attr->mNameSpace, attr->mAttr, attr->mValue,
|
||||
attr->mCaseSensitive ? eCaseMatters : eIgnoreCase);
|
||||
AttrValueIs(attr->mNameSpace, matchAttribute, attr->mValue,
|
||||
(!isHTML || attr->mCaseSensitive) ? eCaseMatters
|
||||
: eIgnoreCase);
|
||||
}
|
||||
else if (!data.mContent->HasAttr(attr->mNameSpace, attr->mAttr)) {
|
||||
else if (!data.mContent->HasAttr(attr->mNameSpace, matchAttribute)) {
|
||||
result = PR_FALSE;
|
||||
}
|
||||
else if (attr->mFunction != NS_ATTR_FUNC_SET) {
|
||||
@ -1741,9 +1742,9 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
#ifdef DEBUG
|
||||
PRBool hasAttr =
|
||||
#endif
|
||||
data.mContent->GetAttr(attr->mNameSpace, attr->mAttr, value);
|
||||
data.mContent->GetAttr(attr->mNameSpace, matchAttribute, value);
|
||||
NS_ASSERTION(hasAttr, "HasAttr lied");
|
||||
result = AttrMatchesValue(attr, value);
|
||||
result = AttrMatchesValue(attr, value, isHTML);
|
||||
}
|
||||
|
||||
attr = attr->mNext;
|
||||
@ -2326,7 +2327,8 @@ AddRule(RuleValue* aRuleInfo, void* aCascade)
|
||||
// Build mAttributeSelectors.
|
||||
for (nsAttrSelector *attr = negation->mAttrList; attr;
|
||||
attr = attr->mNext) {
|
||||
nsTArray<nsCSSSelector*> *array = cascade->AttributeListFor(attr->mAttr);
|
||||
nsTArray<nsCSSSelector*> *array =
|
||||
cascade->AttributeListFor(attr->mCasedAttr);
|
||||
if (!array)
|
||||
return PR_FALSE;
|
||||
array->AppendElement(selector);
|
||||
|
@ -199,36 +199,47 @@ nsPseudoClassList::~nsPseudoClassList(void)
|
||||
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr)
|
||||
: mValue(),
|
||||
mNext(nsnull),
|
||||
mAttr(nsnull),
|
||||
mLowercaseAttr(nsnull),
|
||||
mCasedAttr(nsnull),
|
||||
mNameSpace(aNameSpace),
|
||||
mFunction(NS_ATTR_FUNC_SET),
|
||||
mCaseSensitive(1)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAttrSelector);
|
||||
|
||||
mAttr = do_GetAtom(aAttr);
|
||||
nsAutoString lowercase;
|
||||
ToLowerCase(aAttr, lowercase);
|
||||
|
||||
mCasedAttr = do_GetAtom(aAttr);
|
||||
mLowercaseAttr = do_GetAtom(lowercase);
|
||||
}
|
||||
|
||||
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
|
||||
const nsString& aValue, PRBool aCaseSensitive)
|
||||
: mValue(aValue),
|
||||
mNext(nsnull),
|
||||
mAttr(nsnull),
|
||||
mLowercaseAttr(nsnull),
|
||||
mCasedAttr(nsnull),
|
||||
mNameSpace(aNameSpace),
|
||||
mFunction(aFunction),
|
||||
mCaseSensitive(aCaseSensitive)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAttrSelector);
|
||||
|
||||
mAttr = do_GetAtom(aAttr);
|
||||
nsAutoString lowercase;
|
||||
ToLowerCase(aAttr, lowercase);
|
||||
|
||||
mCasedAttr = do_GetAtom(aAttr);
|
||||
mLowercaseAttr = do_GetAtom(lowercase);
|
||||
}
|
||||
|
||||
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aAttr,
|
||||
PRUint8 aFunction, const nsString& aValue,
|
||||
PRBool aCaseSensitive)
|
||||
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aLowercaseAttr,
|
||||
nsIAtom* aCasedAttr, PRUint8 aFunction,
|
||||
const nsString& aValue, PRBool aCaseSensitive)
|
||||
: mValue(aValue),
|
||||
mNext(nsnull),
|
||||
mAttr(aAttr),
|
||||
mLowercaseAttr(aLowercaseAttr),
|
||||
mCasedAttr(aCasedAttr),
|
||||
mNameSpace(aNameSpace),
|
||||
mFunction(aFunction),
|
||||
mCaseSensitive(aCaseSensitive)
|
||||
@ -240,7 +251,8 @@ nsAttrSelector*
|
||||
nsAttrSelector::Clone(PRBool aDeep) const
|
||||
{
|
||||
nsAttrSelector *result =
|
||||
new nsAttrSelector(mNameSpace, mAttr, mFunction, mValue, mCaseSensitive);
|
||||
new nsAttrSelector(mNameSpace, mLowercaseAttr, mCasedAttr,
|
||||
mFunction, mValue, mCaseSensitive);
|
||||
|
||||
if (aDeep)
|
||||
NS_CSS_CLONE_LIST_MEMBER(nsAttrSelector, this, mNext, result, (PR_FALSE));
|
||||
@ -337,7 +349,7 @@ void nsCSSSelector::SetNameSpace(PRInt32 aNameSpace)
|
||||
mNameSpace = aNameSpace;
|
||||
}
|
||||
|
||||
void nsCSSSelector::SetTag(const nsString& aTag, PRBool aCaseMatters)
|
||||
void nsCSSSelector::SetTag(const nsString& aTag)
|
||||
{
|
||||
if (aTag.IsEmpty()) {
|
||||
mLowercaseTag = mCasedTag = nsnull;
|
||||
@ -346,14 +358,9 @@ void nsCSSSelector::SetTag(const nsString& aTag, PRBool aCaseMatters)
|
||||
|
||||
mCasedTag = do_GetAtom(aTag);
|
||||
|
||||
if (aCaseMatters) {
|
||||
mLowercaseTag = mCasedTag;
|
||||
}
|
||||
else {
|
||||
nsAutoString lowercase(aTag);
|
||||
ToLowerCase(lowercase);
|
||||
mLowercaseTag = do_GetAtom(lowercase);
|
||||
}
|
||||
nsAutoString lowercase;
|
||||
ToLowerCase(aTag, lowercase);
|
||||
mLowercaseTag = do_GetAtom(lowercase);
|
||||
}
|
||||
|
||||
void nsCSSSelector::AddID(const nsString& aID)
|
||||
@ -657,7 +664,7 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
|
||||
}
|
||||
}
|
||||
// Append the attribute name
|
||||
list->mAttr->ToString(temp);
|
||||
list->mCasedAttr->ToString(temp);
|
||||
aString.Append(temp);
|
||||
|
||||
if (list->mFunction != NS_ATTR_FUNC_SET) {
|
||||
|
@ -72,7 +72,6 @@ public:
|
||||
NS_IMETHOD Init(nsIDocument* aDocument) = 0;
|
||||
NS_IMETHOD DropDocumentReference(void) = 0; // notification that doc is going away
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive) = 0;
|
||||
NS_IMETHOD SetCompatibilityMode(nsCompatibility aCompatMode) = 0;
|
||||
NS_IMETHOD SetPreferredSheet(const nsAString& aTitle) = 0;
|
||||
NS_IMETHOD GetPreferredSheet(nsAString& aTitle) = 0;
|
||||
|
@ -74,9 +74,6 @@ public:
|
||||
// out an existing stylesheet reference.
|
||||
NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet) = 0;
|
||||
|
||||
// Set whether or not tags & classes are case sensitive or uppercased
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive) = 0;
|
||||
|
||||
// Set whether or not to emulate Nav quirks
|
||||
NS_IMETHOD SetQuirkMode(PRBool aQuirkMode) = 0;
|
||||
|
||||
|
@ -121,7 +121,8 @@ public:
|
||||
nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr);
|
||||
nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
|
||||
const nsString& aValue, PRBool aCaseSensitive);
|
||||
nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aAttr, PRUint8 aFunction,
|
||||
nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aLowercaseAttr,
|
||||
nsIAtom* aCasedAttr, PRUint8 aFunction,
|
||||
const nsString& aValue, PRBool aCaseSensitive);
|
||||
~nsAttrSelector(void);
|
||||
|
||||
@ -130,10 +131,12 @@ public:
|
||||
|
||||
nsString mValue;
|
||||
nsAttrSelector* mNext;
|
||||
nsCOMPtr<nsIAtom> mAttr;
|
||||
nsCOMPtr<nsIAtom> mLowercaseAttr;
|
||||
nsCOMPtr<nsIAtom> mCasedAttr;
|
||||
PRInt32 mNameSpace;
|
||||
PRUint8 mFunction;
|
||||
PRPackedBool mCaseSensitive;
|
||||
PRPackedBool mCaseSensitive; // If we are in an HTML document,
|
||||
// is the value case sensitive?
|
||||
private:
|
||||
nsAttrSelector* Clone(PRBool aDeep) const;
|
||||
|
||||
@ -152,7 +155,7 @@ public:
|
||||
|
||||
void Reset(void);
|
||||
void SetNameSpace(PRInt32 aNameSpace);
|
||||
void SetTag(const nsString& aTag, PRBool aCaseSensitive);
|
||||
void SetTag(const nsString& aTag);
|
||||
void AddID(const nsString& aID);
|
||||
void AddClass(const nsString& aClass);
|
||||
void AddPseudoClass(nsIAtom* aPseudoClass);
|
||||
|
@ -12,4 +12,6 @@ from git://git.xiph.org/libfishsound.git
|
||||
endian.patch is applied to fix Bug 45269.
|
||||
|
||||
bug487519.patch: Fixes for bug487519
|
||||
trac497.patch: Annodex trac ticket 497 fix and mozilla bug 462141.
|
||||
fishsound_reset.patch: Fixes bug 516323.
|
||||
|
||||
|
12
media/libfishsound/fishsound_reset.patch
Normal file
12
media/libfishsound/fishsound_reset.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff --git a/media/libfishsound/src/libfishsound/fishsound_vorbis.c b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
|
||||
--- a/media/libfishsound/src/libfishsound/fishsound_vorbis.c
|
||||
+++ b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
|
||||
@@ -412,7 +412,7 @@
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
-
|
||||
+ fsv->packetno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -290,7 +290,9 @@ fish_sound_comment_next_byname (FishSound * fsound,
|
||||
int
|
||||
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
#if FS_ENCODE
|
||||
FishSoundComment * new_comment;
|
||||
#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@ -317,7 +319,9 @@ int
|
||||
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
const char * value)
|
||||
{
|
||||
#if FS_ENCODE
|
||||
FishSoundComment * comment;
|
||||
#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@ -346,7 +350,9 @@ fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
int
|
||||
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
#if FS_ENCODE
|
||||
FishSoundComment * v_comment;
|
||||
#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@ -372,8 +378,11 @@ fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
|
||||
int
|
||||
fish_sound_comment_remove_byname (FishSound * fsound, char * name)
|
||||
{
|
||||
#if FS_ENCODE
|
||||
FishSoundComment * comment;
|
||||
int i, ret = 0;
|
||||
int i;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
|
@ -412,7 +412,7 @@ fs_vorbis_reset (FishSound * fsound)
|
||||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
|
||||
fsv->packetno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
47
media/libfishsound/trac497.patch
Normal file
47
media/libfishsound/trac497.patch
Normal file
@ -0,0 +1,47 @@
|
||||
diff --git a/media/libfishsound/src/libfishsound/fishsound_comments.c b/media/libfishsound/src/libfishsound/fishsound_comments.c
|
||||
index b71164f..414e210 100644
|
||||
--- a/media/libfishsound/src/libfishsound/fishsound_comments.c
|
||||
+++ b/media/libfishsound/src/libfishsound/fishsound_comments.c
|
||||
@@ -290,7 +290,9 @@ fish_sound_comment_next_byname (FishSound * fsound,
|
||||
int
|
||||
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
+#if FS_ENCODE
|
||||
FishSoundComment * new_comment;
|
||||
+#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@@ -317,7 +319,9 @@ int
|
||||
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
const char * value)
|
||||
{
|
||||
+#if FS_ENCODE
|
||||
FishSoundComment * comment;
|
||||
+#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@@ -346,7 +350,9 @@ fish_sound_comment_add_byname (FishSound * fsound, const char * name,
|
||||
int
|
||||
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
|
||||
{
|
||||
+#if FS_ENCODE
|
||||
FishSoundComment * v_comment;
|
||||
+#endif
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
||||
@@ -372,8 +378,11 @@ fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
|
||||
int
|
||||
fish_sound_comment_remove_byname (FishSound * fsound, char * name)
|
||||
{
|
||||
+#if FS_ENCODE
|
||||
FishSoundComment * comment;
|
||||
- int i, ret = 0;
|
||||
+ int i;
|
||||
+#endif
|
||||
+ int ret = 0;
|
||||
|
||||
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
|
||||
|
@ -41,3 +41,6 @@ cp $1/src/libfishsound/debug.h ./src/libfishsound/debug.h
|
||||
cp $1/AUTHORS ./AUTHORS
|
||||
patch -p3 <endian.patch
|
||||
patch -p3 <bug487519.patch
|
||||
patch -p3 <trac497.patch
|
||||
patch -p3 <fishsound_reset.patch
|
||||
|
||||
|
@ -36,3 +36,4 @@ handle-read-errors.patch: Make oggplay_initialise() handle closing of stream
|
||||
while reading. Prevents infinite loop. Further fix
|
||||
to 17ef4ca82df28.
|
||||
|
||||
fishsound_reset.patch: Fixes bug 516323.
|
||||
|
24
media/liboggplay/fishsound_reset.patch
Normal file
24
media/liboggplay/fishsound_reset.patch
Normal file
@ -0,0 +1,24 @@
|
||||
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
|
||||
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
|
||||
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
|
||||
@@ -166,6 +166,20 @@ oggplay_seek_cleanup(OggPlay* me, ogg_in
|
||||
|
||||
*p = trash;
|
||||
|
||||
+ if (milliseconds == 0) {
|
||||
+ for (i = 0; i < me->num_tracks; i++) {
|
||||
+ OggPlayDecode *track = me->decode_data[i];
|
||||
+ FishSound *sound_handle;
|
||||
+ OggPlayAudioDecode *audio_decode;
|
||||
+ if (track->content_type != OGGZ_CONTENT_VORBIS) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ audio_decode = (OggPlayAudioDecode*)track;
|
||||
+ sound_handle = audio_decode->sound_handle;
|
||||
+ fish_sound_reset(sound_handle);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return E_OGGPLAY_OK;
|
||||
}
|
||||
|
@ -166,6 +166,20 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
|
||||
|
||||
*p = trash;
|
||||
|
||||
if (milliseconds == 0) {
|
||||
for (i = 0; i < me->num_tracks; i++) {
|
||||
OggPlayDecode *track = me->decode_data[i];
|
||||
FishSound *sound_handle;
|
||||
OggPlayAudioDecode *audio_decode;
|
||||
if (track->content_type != OGGZ_CONTENT_VORBIS) {
|
||||
continue;
|
||||
}
|
||||
audio_decode = (OggPlayAudioDecode*)track;
|
||||
sound_handle = audio_decode->sound_handle;
|
||||
fish_sound_reset(sound_handle);
|
||||
}
|
||||
}
|
||||
|
||||
return E_OGGPLAY_OK;
|
||||
}
|
||||
|
||||
|
@ -58,4 +58,4 @@ patch -p3 < bug500311.patch
|
||||
patch -p3 < faster_seek.patch
|
||||
patch -p3 < fix-17ef4ca82df28.patch
|
||||
patch -p3 < handle-read-errors.patch
|
||||
|
||||
patch -p3 < fishsound_reset.patch
|
||||
|
@ -42,3 +42,4 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
@ -63,11 +63,11 @@ PR_BEGIN_EXTERN_C
|
||||
** The format of the version string is
|
||||
** "<major version>.<minor version>[.<patch level>] [<Beta>]"
|
||||
*/
|
||||
#define PR_VERSION "4.8.1 Beta 2"
|
||||
#define PR_VERSION "4.8.1"
|
||||
#define PR_VMAJOR 4
|
||||
#define PR_VMINOR 8
|
||||
#define PR_VPATCH 1
|
||||
#define PR_BETA PR_TRUE
|
||||
#define PR_BETA PR_FALSE
|
||||
|
||||
/*
|
||||
** PRVersionCheck
|
||||
|
@ -1146,8 +1146,10 @@ LoginManagerStorage_mozStorage.prototype = {
|
||||
this._base64checked = true;
|
||||
// Ignore failures, will try again next session...
|
||||
|
||||
this.log("Reencrypting Base64 logins");
|
||||
this._dbConnection.beginTransaction();
|
||||
try {
|
||||
let [logins, ids] = this._searchLogins({ encType: 0 });
|
||||
let [logins, ids] = this._searchLogins({ encType: ENCTYPE_BASE64 });
|
||||
|
||||
if (!logins.length)
|
||||
return;
|
||||
@ -1157,10 +1159,37 @@ LoginManagerStorage_mozStorage.prototype = {
|
||||
if (userCanceled)
|
||||
return;
|
||||
|
||||
for each (let login in logins)
|
||||
this.modifyLogin(login, login);
|
||||
let encUsername, encPassword, stmt;
|
||||
for each (let login in logins) {
|
||||
[encUsername, encPassword, userCanceled] = this._encryptLogin(login);
|
||||
if (userCanceled)
|
||||
throw "User canceled master password entry, login not modified.";
|
||||
let query =
|
||||
"UPDATE moz_logins " +
|
||||
"SET encryptedUsername = :encryptedUsername, " +
|
||||
"encryptedPassword = :encryptedPassword, " +
|
||||
"encType = :encType " +
|
||||
"WHERE guid = :guid";
|
||||
let params = {
|
||||
encryptedUsername: encUsername,
|
||||
encryptedPassword: encPassword,
|
||||
encType: ENCTYPE_SDR,
|
||||
guid: login.guid
|
||||
};
|
||||
try {
|
||||
stmt = this._dbCreateStatement(query, params);
|
||||
stmt.execute();
|
||||
} catch (e) {
|
||||
// Ignore singular errors, continue trying to update others.
|
||||
this.log("_reencryptBase64Logins caught error: " + e);
|
||||
} finally {
|
||||
stmt.reset();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.log("_reencryptBase64Logins caught error: " + e);
|
||||
this.log("_reencryptBase64Logins failed: " + e);
|
||||
} finally {
|
||||
this._dbConnection.commitTransaction();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -322,6 +322,10 @@ function nsPlacesAutoComplete()
|
||||
"LEFT JOIN moz_places_temp h_t ON h_t.id = i.place_id " +
|
||||
"LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) "+
|
||||
"WHERE IFNULL(h_t.url, h.url) NOTNULL " +
|
||||
"AND AUTOCOMPLETE_MATCH(:searchString, 0 /* url */, " +
|
||||
"IFNULL(bookmark, 1 /* title */), tags, " +
|
||||
"6 /* visit_count */, 7 /* typed */, parent, " +
|
||||
":matchBehavior, :searchBehavior) " +
|
||||
"ORDER BY rank DESC, IFNULL(h_t.frecency, h.frecency) DESC"
|
||||
);
|
||||
});
|
||||
@ -352,6 +356,9 @@ function nsPlacesAutoComplete()
|
||||
//// Initialization
|
||||
|
||||
// load preferences
|
||||
this._prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch(kBrowserUrlbarBranch);
|
||||
this._loadPrefs(true);
|
||||
|
||||
// register observers
|
||||
@ -481,8 +488,11 @@ nsPlacesAutoComplete.prototype = {
|
||||
if (this._matchBehavior == MATCH_BOUNDARY_ANYWHERE &&
|
||||
this._result.matchCount < this._maxRichResults && !this._secondPass) {
|
||||
this._secondPass = true;
|
||||
let query = this._getBoundSearchQuery(MATCH_ANYWHERE, this._searchTokens);
|
||||
this._executeQueries([query]);
|
||||
let queries = [
|
||||
this._getBoundAdaptiveQuery(MATCH_ANYWHERE),
|
||||
this._getBoundSearchQuery(MATCH_ANYWHERE, this._searchTokens),
|
||||
];
|
||||
this._executeQueries(queries);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -498,11 +508,8 @@ nsPlacesAutoComplete.prototype = {
|
||||
this._os.removeObserver(this, kQuitApplication);
|
||||
|
||||
// Remove our preference observer.
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch(kBrowserUrlbarBranch).
|
||||
QueryInterface(Ci.nsIPrefBranch2);
|
||||
prefs.removeObserver("", this);
|
||||
this._prefs.removeObserver("", this);
|
||||
delete this._prefs;
|
||||
|
||||
// Finalize the statements that we have used.
|
||||
let stmts = [
|
||||
@ -643,9 +650,7 @@ nsPlacesAutoComplete.prototype = {
|
||||
*/
|
||||
_loadPrefs: function PAC_loadPrefs(aRegisterObserver)
|
||||
{
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch(kBrowserUrlbarBranch);
|
||||
let self = this;
|
||||
function safeGetter(aName, aDefault) {
|
||||
let types = {
|
||||
boolean: "Bool",
|
||||
@ -658,7 +663,7 @@ nsPlacesAutoComplete.prototype = {
|
||||
|
||||
// If the pref isn't set, we want to use the default.
|
||||
try {
|
||||
return prefs["get" + type + "Pref"](aName);
|
||||
return self._prefs["get" + type + "Pref"](aName);
|
||||
}
|
||||
catch (e) {
|
||||
return aDefault;
|
||||
@ -689,7 +694,7 @@ nsPlacesAutoComplete.prototype = {
|
||||
|
||||
// register observer
|
||||
if (aRegisterObserver) {
|
||||
let pb = prefs.QueryInterface(Ci.nsIPrefBranch2);
|
||||
let pb = this._prefs.QueryInterface(Ci.nsIPrefBranch2);
|
||||
pb.addObserver("", this, false);
|
||||
}
|
||||
},
|
||||
@ -829,13 +834,19 @@ nsPlacesAutoComplete.prototype = {
|
||||
*
|
||||
* @return the bound adaptive query.
|
||||
*/
|
||||
_getBoundAdaptiveQuery: function PAC_getBoundAdaptiveQuery()
|
||||
_getBoundAdaptiveQuery: function PAC_getBoundAdaptiveQuery(aMatchBehavior)
|
||||
{
|
||||
// If we were not given a match behavior, use the stored match behavior.
|
||||
if (arguments.length == 0)
|
||||
aMatchBehavior = this._matchBehavior;
|
||||
|
||||
let query = this._adaptiveQuery;
|
||||
let (params = query.params) {
|
||||
params.parent = this._bs.tagsFolder;
|
||||
params.search_string = this._currentSearchString;
|
||||
params.query_type = kQueryTypeFiltered;
|
||||
params.matchBehavior = aMatchBehavior;
|
||||
params.searchBehavior = this._behavior;
|
||||
}
|
||||
|
||||
return query;
|
||||
@ -900,7 +911,8 @@ nsPlacesAutoComplete.prototype = {
|
||||
// the result does not fall into any of those, it just gets the favicon.
|
||||
if (!style) {
|
||||
// It is possible that we already have a style set (from a keyword
|
||||
// search), so only set it if we haven't already done so.
|
||||
// search or because of the user's preferences), so only set it if we
|
||||
// haven't already done so.
|
||||
if (showTags)
|
||||
style = "tag";
|
||||
else if (entryParentId)
|
||||
|
@ -159,6 +159,12 @@ var PlacesUtils = {
|
||||
getService(Ci.nsITaggingService);
|
||||
},
|
||||
|
||||
get observerSvc() {
|
||||
delete this.observerSvc;
|
||||
return this.observerSvc = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes a URI from a spec.
|
||||
* @param aSpec
|
||||
@ -278,9 +284,7 @@ var PlacesUtils = {
|
||||
this.annotations.addObserver(this, false);
|
||||
|
||||
// observe shutdown, so we can remove the anno observer
|
||||
const os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.addObserver(this, "xpcom-shutdown", false);
|
||||
this.observerSvc.addObserver(this, "xpcom-shutdown", false);
|
||||
|
||||
var readOnly = this.annotations.getItemsWithAnnotation(READ_ONLY_ANNO, {});
|
||||
this.__defineGetter__("_readOnly", function() readOnly);
|
||||
@ -294,9 +298,7 @@ var PlacesUtils = {
|
||||
observe: function PU_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
this.annotations.removeObserver(this);
|
||||
const os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.removeObserver(this, "xpcom-shutdown");
|
||||
this.observerSvc.removeObserver(this, "xpcom-shutdown");
|
||||
}
|
||||
},
|
||||
|
||||
@ -1170,62 +1172,6 @@ var PlacesUtils = {
|
||||
return urls;
|
||||
},
|
||||
|
||||
/**
|
||||
* Restores bookmarks/tags from a JSON file.
|
||||
* WARNING: This method *removes* any bookmarks in the collection before
|
||||
* restoring from the file.
|
||||
*
|
||||
* @param aFile
|
||||
* nsIFile of bookmarks in JSON format to be restored.
|
||||
*/
|
||||
restoreBookmarksFromJSONFile:
|
||||
function PU_restoreBookmarksFromJSONFile(aFile) {
|
||||
var failed = false;
|
||||
var obsServ = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obsServ.notifyObservers(null,
|
||||
RESTORE_BEGIN_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
|
||||
try {
|
||||
// open file stream
|
||||
var stream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
stream.init(aFile, 0x01, 0, 0);
|
||||
var converted = Cc["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Ci.nsIConverterInputStream);
|
||||
converted.init(stream, "UTF-8", 8192,
|
||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
|
||||
// read in contents
|
||||
var str = {};
|
||||
var jsonStr = "";
|
||||
while (converted.readString(8192, str) != 0)
|
||||
jsonStr += str.value;
|
||||
converted.close();
|
||||
|
||||
if (jsonStr.length == 0)
|
||||
return; // empty file
|
||||
|
||||
this.restoreBookmarksFromJSONString(jsonStr, true);
|
||||
}
|
||||
catch (exc) {
|
||||
failed = true;
|
||||
obsServ.notifyObservers(null,
|
||||
RESTORE_FAILED_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
Components.utils.reportError("Bookmarks JSON restore failed: " + exc);
|
||||
throw exc;
|
||||
}
|
||||
finally {
|
||||
if (!failed) {
|
||||
obsServ.notifyObservers(null,
|
||||
RESTORE_SUCCESS_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Import bookmarks from a JSON string.
|
||||
* Note: any item annotated with "places/excludeFromBackup" won't be removed
|
||||
@ -1702,197 +1648,318 @@ var PlacesUtils = {
|
||||
},
|
||||
|
||||
/**
|
||||
* backupBookmarksToFile()
|
||||
*
|
||||
* Serializes bookmarks using JSON, and writes to the supplied file.
|
||||
* Note: any item that should not be backed up must be annotated with
|
||||
* "places/excludeFromBackup".
|
||||
*
|
||||
* @param aFile
|
||||
* nsIFile where to save JSON backup.
|
||||
* Helper to create and manage backups.
|
||||
*/
|
||||
backupBookmarksToFile: function PU_backupBookmarksToFile(aFile) {
|
||||
if (aFile.exists() && !aFile.isWritable())
|
||||
return; // XXX
|
||||
backups: {
|
||||
|
||||
// init stream
|
||||
var stream = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
stream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);
|
||||
|
||||
// utf-8 converter stream
|
||||
var converter = Cc["@mozilla.org/intl/converter-output-stream;1"].
|
||||
createInstance(Ci.nsIConverterOutputStream);
|
||||
converter.init(stream, "UTF-8", 0, 0x0000);
|
||||
|
||||
// weep over stream interface variance
|
||||
var streamProxy = {
|
||||
converter: converter,
|
||||
write: function(aData, aLen) {
|
||||
this.converter.writeString(aData);
|
||||
}
|
||||
};
|
||||
|
||||
// Get itemIds to be exluded from the backup
|
||||
var excludeItems = this.annotations
|
||||
.getItemsWithAnnotation(EXCLUDE_FROM_BACKUP_ANNO, {});
|
||||
|
||||
// query places root
|
||||
var options = this.history.getNewQueryOptions();
|
||||
options.expandQueries = false;
|
||||
var query = this.history.getNewQuery();
|
||||
query.setFolders([this.placesRootId], 1);
|
||||
var result = this.history.executeQuery(query, options);
|
||||
result.root.containerOpen = true;
|
||||
// serialize as JSON, write to stream
|
||||
this.serializeNodeAsJSONToOutputStream(result.root, streamProxy,
|
||||
false, false, excludeItems);
|
||||
result.root.containerOpen = false;
|
||||
|
||||
// close converter and stream
|
||||
converter.close();
|
||||
stream.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a filename for bookmarks backup files.
|
||||
*
|
||||
* @param [optional] aDateObj Date object used to build the filename.
|
||||
* Will use current date if empty.
|
||||
* @return A bookmarks backup filename.
|
||||
*/
|
||||
getBackupFilename:
|
||||
function PU_getBackupFilename(aDateObj) {
|
||||
if (!aDateObj)
|
||||
aDateObj = new Date();
|
||||
// Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
|
||||
// and makes the alphabetical order of multiple backup files more useful.
|
||||
var date = aDateObj.toLocaleFormat("%Y-%m-%d");
|
||||
return "bookmarks-" + date + ".json";
|
||||
},
|
||||
|
||||
/**
|
||||
* ArchiveBookmarksFile()
|
||||
*
|
||||
* Creates a dated backup once a day in <profile>/bookmarkbackups.
|
||||
* Stores the bookmarks using JSON.
|
||||
* Note: any item that should not be backed up must be annotated with
|
||||
* "places/excludeFromBackup".
|
||||
*
|
||||
* @param int aNumberOfBackups - the maximum number of backups to keep
|
||||
*
|
||||
* @param bool aForceArchive - forces creating an archive even if one was
|
||||
* already created that day (overwrites)
|
||||
*/
|
||||
archiveBookmarksFile:
|
||||
function PU_archiveBookmarksFile(aNumberOfBackups, aForceArchive) {
|
||||
// get/create backups directory
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var bookmarksBackupDir = dirService.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
if (!bookmarksBackupDir.exists())
|
||||
return; // unable to create directory!
|
||||
}
|
||||
|
||||
// Construct the new leafname.
|
||||
var date = new Date();
|
||||
var backupFilename = this.getBackupFilename(date);
|
||||
var backupFile = null;
|
||||
if (!aForceArchive) {
|
||||
var backupFileNames = [];
|
||||
var backupFilenamePrefix = backupFilename.substr(0, backupFilename.indexOf("-"));
|
||||
|
||||
// Get the localized backup filename, to clear out
|
||||
get _filenamesRegex() {
|
||||
// Get the localized backup filename, will be used to clear out
|
||||
// old backups with a localized name (bug 445704).
|
||||
var localizedFilename = this.getFormattedString("bookmarksArchiveFilename", [date]);
|
||||
var localizedFilenamePrefix = localizedFilename.substr(0, localizedFilename.indexOf("-"));
|
||||
var rx = new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9-]+)\.(json|html)");
|
||||
let localizedFilename =
|
||||
PlacesUtils.getFormattedString("bookmarksArchiveFilename", [new Date()]);
|
||||
let localizedFilenamePrefix =
|
||||
localizedFilename.substr(0, localizedFilename.indexOf("-"));
|
||||
delete this._filenamesRegex;
|
||||
return this._filenamesRegex =
|
||||
new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9-]+)\.(json|html)");
|
||||
},
|
||||
|
||||
var entries = bookmarksBackupDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
var entry = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
var backupName = entry.leafName;
|
||||
get folder() {
|
||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
let bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
if (!bookmarksBackupDir.exists())
|
||||
throw("Unable to create bookmarks backup folder");
|
||||
}
|
||||
delete this.folder;
|
||||
return this.folder = bookmarksBackupDir;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cache current backups in a sorted (by date DESC) array.
|
||||
*/
|
||||
get entries() {
|
||||
delete this.entries;
|
||||
this.entries = [];
|
||||
let files = this.folder.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
// A valid backup is any file that matches either the localized or
|
||||
// not-localized filename (bug 445704).
|
||||
var matches = backupName.match(rx);
|
||||
if (matches) {
|
||||
if (backupName == backupFilename)
|
||||
backupFile = entry;
|
||||
backupFileNames.push({ filename: backupName, date: matches[2] });
|
||||
let matches = entry.leafName.match(this._filenamesRegex);
|
||||
if (!entry.isHidden() && matches) {
|
||||
// Remove bogus backups in future dates.
|
||||
if (this.getDateForFile(entry) > new Date()) {
|
||||
entry.remove(false);
|
||||
continue;
|
||||
}
|
||||
this.entries.push(entry);
|
||||
}
|
||||
}
|
||||
this.entries.sort(function compare(a, b) {
|
||||
aDate = PlacesUtils.backups.getDateForFile(a);
|
||||
bDate = PlacesUtils.backups.getDateForFile(b);
|
||||
return aDate < bDate ? 1 : aDate > bDate ? -1 : 0;
|
||||
});
|
||||
return this.entries;
|
||||
},
|
||||
|
||||
var numberOfBackupsToDelete = 0;
|
||||
if (aNumberOfBackups > -1)
|
||||
numberOfBackupsToDelete = backupFileNames.length - aNumberOfBackups;
|
||||
/**
|
||||
* Creates a filename for bookmarks backup files.
|
||||
*
|
||||
* @param [optional] aDateObj
|
||||
* Date object used to build the filename.
|
||||
* Will use current date if empty.
|
||||
* @return A bookmarks backup filename.
|
||||
*/
|
||||
getFilenameForDate:
|
||||
function PU_B_getFilenameForDate(aDateObj) {
|
||||
let dateObj = aDateObj || new Date();
|
||||
// Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
|
||||
// and makes the alphabetical order of multiple backup files more useful.
|
||||
return "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json";
|
||||
},
|
||||
|
||||
if (numberOfBackupsToDelete > 0) {
|
||||
// If we don't have today's backup, remove one more so that
|
||||
// the total backups after this operation does not exceed the
|
||||
// number specified in the pref.
|
||||
if (!backupFile)
|
||||
numberOfBackupsToDelete++;
|
||||
backupFileNames.sort(function compare(a, b) {
|
||||
return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
|
||||
});
|
||||
while (numberOfBackupsToDelete--) {
|
||||
let backupFile = bookmarksBackupDir.clone();
|
||||
backupFile.append(backupFileNames[0].filename);
|
||||
backupFile.remove(false);
|
||||
backupFileNames.shift();
|
||||
}
|
||||
/**
|
||||
* Creates a Date object from a backup file. The date is the backup
|
||||
* creation date.
|
||||
*
|
||||
* @param aBackupFile
|
||||
* nsIFile of the backup.
|
||||
* @return A Date object for the backup's creation time.
|
||||
*/
|
||||
getDateForFile:
|
||||
function PU_B_getDateForFile(aBackupFile) {
|
||||
let filename = aBackupFile.leafName;
|
||||
let matches = filename.match(this._filenamesRegex);
|
||||
if (!matches)
|
||||
do_throw("Invalid backup file name: " + filename);
|
||||
return new Date(matches[2].replace(/-/g, "/"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the most recent backup file.
|
||||
*
|
||||
* @param [optional] aFileExt
|
||||
* Force file extension. Either "html" or "json".
|
||||
* Will check for both if not defined.
|
||||
* @returns nsIFile backup file
|
||||
*/
|
||||
getMostRecent:
|
||||
function PU__B_getMostRecent(aFileExt) {
|
||||
let fileExt = aFileExt || "(json|html)";
|
||||
for (let i = 0; i < this.entries.length; i++) {
|
||||
let rx = new RegExp("\." + fileExt + "$");
|
||||
if (this.entries[i].leafName.match(rx))
|
||||
return this.entries[i];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// do nothing if we either have today's backup already
|
||||
// or the user has set the pref to zero.
|
||||
if (backupFile || aNumberOfBackups == 0)
|
||||
/**
|
||||
* saveBookmarksToJSONFile()
|
||||
*
|
||||
* Serializes bookmarks using JSON, and writes to the supplied file.
|
||||
* Note: any item that should not be backed up must be annotated with
|
||||
* "places/excludeFromBackup".
|
||||
*
|
||||
* @param aFile
|
||||
* nsIFile where to save JSON backup.
|
||||
*/
|
||||
saveBookmarksToJSONFile:
|
||||
function PU_B_saveBookmarksToFile(aFile) {
|
||||
if (!aFile.exists())
|
||||
aFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
|
||||
if (!aFile.exists() || !aFile.isWritable()) {
|
||||
Cu.reportError("Unable to create bookmarks backup file: " + aFile.leafName);
|
||||
return;
|
||||
}
|
||||
|
||||
this._writeBackupFile(aFile);
|
||||
|
||||
if (aFile.parent.equals(this.folder)) {
|
||||
// Update internal cache.
|
||||
this.entries.push(aFile);
|
||||
}
|
||||
else {
|
||||
// If we are saving to a folder different than our backups folder, then
|
||||
// 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.
|
||||
var latestBackup = this.getMostRecent("json");
|
||||
if (!latestBackup || latestBackup != aFile) {
|
||||
let name = this.getFilenameForDate();
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_writeBackupFile:
|
||||
function PU_B__writeBackupFile(aFile) {
|
||||
// Init stream.
|
||||
let stream = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
stream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);
|
||||
|
||||
// UTF-8 converter stream.
|
||||
let converter = Cc["@mozilla.org/intl/converter-output-stream;1"].
|
||||
createInstance(Ci.nsIConverterOutputStream);
|
||||
converter.init(stream, "UTF-8", 0, 0x0000);
|
||||
|
||||
// Weep over stream interface variance.
|
||||
let streamProxy = {
|
||||
converter: converter,
|
||||
write: function(aData, aLen) {
|
||||
this.converter.writeString(aData);
|
||||
}
|
||||
};
|
||||
|
||||
// Get list of itemIds that must be exluded from the backup.
|
||||
let excludeItems =
|
||||
PlacesUtils.annotations.getItemsWithAnnotation(EXCLUDE_FROM_BACKUP_ANNO, {});
|
||||
|
||||
// Query the Places root.
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = false;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.placesRootId], 1);
|
||||
let root = PlacesUtils.history.executeQuery(query, options).root;
|
||||
root.containerOpen = true;
|
||||
// Serialize to JSON and write to stream.
|
||||
PlacesUtils.serializeNodeAsJSONToOutputStream(root, streamProxy,
|
||||
false, false, excludeItems);
|
||||
root.containerOpen = false;
|
||||
|
||||
// Close converter and stream.
|
||||
converter.close();
|
||||
stream.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* create()
|
||||
*
|
||||
* Creates a dated backup in <profile>/bookmarkbackups.
|
||||
* Stores the bookmarks using JSON.
|
||||
* Note: any item that should not be backed up must be annotated with
|
||||
* "places/excludeFromBackup".
|
||||
*
|
||||
* @param [optional] int aMaxBackups
|
||||
* The maximum number of backups to keep.
|
||||
*
|
||||
* @param [optional] bool aForceBackup
|
||||
* Forces creating a backup even if one was already
|
||||
* created that day (overwrites).
|
||||
*/
|
||||
create:
|
||||
function PU_B_create(aMaxBackups, aForceBackup) {
|
||||
// Construct the new leafname.
|
||||
let newBackupFilename = this.getFilenameForDate();
|
||||
let mostRecentBackupFile = this.getMostRecent();
|
||||
|
||||
if (!aForceBackup) {
|
||||
let numberOfBackupsToDelete = 0;
|
||||
if (aMaxBackups !== undefined && aMaxBackups > -1)
|
||||
numberOfBackupsToDelete = this.entries.length - aMaxBackups;
|
||||
|
||||
if (numberOfBackupsToDelete > 0) {
|
||||
// If we don't have today's backup, remove one more so that
|
||||
// the total backups after this operation does not exceed the
|
||||
// number specified in the pref.
|
||||
if (!mostRecentBackupFile ||
|
||||
mostRecentBackupFile.leafName != newBackupFilename)
|
||||
numberOfBackupsToDelete++;
|
||||
|
||||
while (numberOfBackupsToDelete--) {
|
||||
let oldestBackup = this.entries.pop();
|
||||
oldestBackup.remove(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Do nothing if we already have this backup or we don't want backups.
|
||||
if (aMaxBackups === 0 ||
|
||||
(mostRecentBackupFile &&
|
||||
mostRecentBackupFile.leafName == newBackupFilename))
|
||||
return;
|
||||
}
|
||||
|
||||
let newBackupFile = this.folder.clone();
|
||||
newBackupFile.append(newBackupFilename);
|
||||
|
||||
if (aForceBackup && newBackupFile.exists())
|
||||
newBackupFile.remove(false);
|
||||
|
||||
if (newBackupFile.exists())
|
||||
return;
|
||||
|
||||
this.saveBookmarksToJSONFile(newBackupFile);
|
||||
},
|
||||
|
||||
/**
|
||||
* Restores bookmarks and tags from a JSON file.
|
||||
* WARNING: This method *removes* any bookmarks in the collection before
|
||||
* restoring from the file.
|
||||
*
|
||||
* @param aFile
|
||||
* nsIFile of bookmarks in JSON format to be restored.
|
||||
*/
|
||||
restoreBookmarksFromJSONFile:
|
||||
function PU_B_restoreBookmarksFromJSONFile(aFile) {
|
||||
let failed = false;
|
||||
PlacesUtils.observerSvc.notifyObservers(null,
|
||||
RESTORE_BEGIN_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
|
||||
try {
|
||||
// open file stream
|
||||
var stream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
stream.init(aFile, 0x01, 0, 0);
|
||||
var converted = Cc["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Ci.nsIConverterInputStream);
|
||||
converted.init(stream, "UTF-8", 8192,
|
||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
|
||||
// read in contents
|
||||
var str = {};
|
||||
var jsonStr = "";
|
||||
while (converted.readString(8192, str) != 0)
|
||||
jsonStr += str.value;
|
||||
converted.close();
|
||||
|
||||
if (jsonStr.length == 0)
|
||||
return; // empty file
|
||||
|
||||
PlacesUtils.restoreBookmarksFromJSONString(jsonStr, true);
|
||||
}
|
||||
catch (exc) {
|
||||
failed = true;
|
||||
PlacesUtils.observerSvc.notifyObservers(null,
|
||||
RESTORE_FAILED_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
Components.utils.reportError("Bookmarks JSON restore failed: " + exc);
|
||||
throw exc;
|
||||
}
|
||||
finally {
|
||||
if (!failed) {
|
||||
PlacesUtils.observerSvc.notifyObservers(null,
|
||||
RESTORE_SUCCESS_NSIOBSERVER_TOPIC,
|
||||
RESTORE_NSIOBSERVER_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backupFile = bookmarksBackupDir.clone();
|
||||
backupFile.append(backupFilename);
|
||||
|
||||
if (aForceArchive && backupFile.exists())
|
||||
backupFile.remove(false);
|
||||
|
||||
if (!backupFile.exists())
|
||||
backupFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
|
||||
|
||||
this.backupBookmarksToFile(backupFile);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the most recent backup file.
|
||||
* @returns nsIFile backup file
|
||||
*/
|
||||
getMostRecentBackup: function PU_getMostRecentBackup() {
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var bookmarksBackupDir = dirService.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists())
|
||||
return null;
|
||||
|
||||
var backups = [];
|
||||
var entries = bookmarksBackupDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
var entry = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (!entry.isHidden() && entry.leafName.match(/^bookmarks-.+(html|json)?$/))
|
||||
backups.push(entry.leafName);
|
||||
}
|
||||
|
||||
if (backups.length == 0)
|
||||
return null;
|
||||
|
||||
backups.sort();
|
||||
var filename = backups.pop();
|
||||
|
||||
var backupFile = bookmarksBackupDir.clone();
|
||||
backupFile.append(filename);
|
||||
return backupFile;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1900,6 +1967,6 @@ var PlacesUtils = {
|
||||
* this method is called by browser.js in delayed startup.
|
||||
*/
|
||||
startPlacesDBUtils: function PU_startPlacesDBUtils() {
|
||||
Components.utils.import("resource://gre/modules/PlacesDBUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesDBUtils.jsm");
|
||||
}
|
||||
};
|
||||
|
@ -239,7 +239,7 @@ function run_test() {
|
||||
|
||||
// export json to file
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
// clean
|
||||
@ -249,7 +249,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
@ -157,14 +157,14 @@ function run_test() {
|
||||
test.populate();
|
||||
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) {
|
||||
do_throw("couldn't export to file: " + ex);
|
||||
}
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) {
|
||||
do_throw("couldn't import the exported file: " + ex);
|
||||
}
|
||||
@ -180,7 +180,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) {
|
||||
do_throw("couldn't import the exported file: " + ex);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ function run_test() {
|
||||
});
|
||||
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
tests.forEach(function(aTest) {
|
||||
@ -188,7 +188,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile, excludedItemsFromRestore);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile, excludedItemsFromRestore);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
@ -108,7 +108,7 @@ function run_test() {
|
||||
|
||||
// export json to file
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
// clean
|
||||
@ -118,7 +118,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
@ -130,7 +130,7 @@ function run_test() {
|
||||
|
||||
// export json to file
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
// clean
|
||||
@ -140,7 +140,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
@ -151,7 +151,7 @@ function run_test() {
|
||||
|
||||
// export json to file
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
// clean
|
||||
@ -161,7 +161,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
@ -40,17 +40,9 @@ Components.utils.import("resource://gre/modules/utils.js");
|
||||
|
||||
const NUMBER_OF_BACKUPS = 1;
|
||||
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
function run_test() {
|
||||
// Get bookmarkBackups directory
|
||||
var bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (!bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
do_check_true(bookmarksBackupDir.exists());
|
||||
}
|
||||
var bookmarksBackupDir = PlacesUtils.backups.folder;
|
||||
|
||||
// Create an html dummy backup in the past
|
||||
var htmlBackupFile = bookmarksBackupDir.clone();
|
||||
@ -70,15 +62,14 @@ function run_test() {
|
||||
jsonBackupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
|
||||
do_check_true(jsonBackupFile.exists());
|
||||
|
||||
// Export bookmarks
|
||||
var date = new Date().toLocaleFormat("%Y-%m-%d");
|
||||
var backupFilename = "bookmarks-" + date + ".json";
|
||||
// Export bookmarks to JSON.
|
||||
var backupFilename = PlacesUtils.backups.getFilenameForDate();
|
||||
var lastBackupFile = bookmarksBackupDir.clone();
|
||||
lastBackupFile.append(backupFilename);
|
||||
if (lastBackupFile.exists())
|
||||
lastBackupFile.remove(false);
|
||||
do_check_false(lastBackupFile.exists());
|
||||
PlacesUtils.archiveBookmarksFile(NUMBER_OF_BACKUPS);
|
||||
PlacesUtils.backups.create(NUMBER_OF_BACKUPS);
|
||||
do_check_true(lastBackupFile.exists());
|
||||
|
||||
// Check that last backup has been retained
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Bug 466303 code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Components.utils.import("resource://gre/modules/utils.js");
|
||||
|
||||
function run_test() {
|
||||
let bookmarksBackupDir = PlacesUtils.backups.folder;
|
||||
// Remove all files from backups folder.
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
entry.remove(false);
|
||||
}
|
||||
|
||||
// Create a json dummy backup in the future.
|
||||
let dateObj = new Date();
|
||||
dateObj.setYear(dateObj.getFullYear() + 1);
|
||||
let name = PlacesUtils.backups.getFilenameForDate(dateObj);
|
||||
do_check_eq(name, "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json");
|
||||
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());
|
||||
|
||||
do_check_eq(PlacesUtils.backups.entries.length, 0);
|
||||
|
||||
PlacesUtils.backups.create();
|
||||
|
||||
// Check that a backup for today has been created.
|
||||
do_check_eq(PlacesUtils.backups.entries.length, 1);
|
||||
let mostRecentBackupFile = PlacesUtils.backups.getMostRecent();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
let todayName = PlacesUtils.backups.getFilenameForDate();
|
||||
do_check_eq(mostRecentBackupFile.leafName, todayName);
|
||||
|
||||
// Check that future backup has been removed.
|
||||
do_check_false(futureBackupFile.exists());
|
||||
|
||||
// Cleanup.
|
||||
mostRecentBackupFile.remove(false);
|
||||
do_check_false(mostRecentBackupFile.exists());
|
||||
}
|
@ -96,7 +96,7 @@ function run_test() {
|
||||
|
||||
// export json to file
|
||||
try {
|
||||
PlacesUtils.backupBookmarksToFile(jsonFile);
|
||||
PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
// clean
|
||||
@ -106,7 +106,7 @@ function run_test() {
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
|
||||
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
|
BIN
toolkit/components/places/tests/unit/places.sparse.sqlite
Normal file
BIN
toolkit/components/places/tests/unit/places.sparse.sqlite
Normal file
Binary file not shown.
@ -58,8 +58,15 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
let histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory);
|
||||
let bsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
let tsvc = Cc["@mozilla.org/browser/tagging-service;1"].
|
||||
getService(Ci.nsITaggingService);
|
||||
let obs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
|
||||
const PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC = "places-autocomplete-feedback-updated";
|
||||
|
||||
@ -119,7 +126,7 @@ AutoCompleteInput.prototype = {
|
||||
/**
|
||||
* Checks that autocomplete results are ordered correctly
|
||||
*/
|
||||
function ensure_results(uris, searchTerm)
|
||||
function ensure_results(expected, searchTerm)
|
||||
{
|
||||
let controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Components.interfaces.nsIAutoCompleteController);
|
||||
@ -133,9 +140,11 @@ function ensure_results(uris, searchTerm)
|
||||
input.onSearchComplete = function() {
|
||||
do_check_eq(controller.searchStatus,
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH);
|
||||
do_check_eq(controller.matchCount, uris.length);
|
||||
do_check_eq(controller.matchCount, expected.length);
|
||||
for (let i = 0; i < controller.matchCount; i++) {
|
||||
do_check_eq(controller.getValueAt(i), uris[i].spec);
|
||||
print("Testing for '" + expected[i].uri.spec + "' got '" + controller.getValueAt(i) + "'");
|
||||
do_check_eq(controller.getValueAt(i), expected[i].uri.spec);
|
||||
do_check_eq(controller.getStyleAt(i), expected[i].style);
|
||||
}
|
||||
|
||||
if (tests.length)
|
||||
@ -152,7 +161,7 @@ function ensure_results(uris, searchTerm)
|
||||
/**
|
||||
* Bump up the rank for an uri
|
||||
*/
|
||||
function setCountRank(aURI, aCount, aRank, aSearch)
|
||||
function setCountRank(aURI, aCount, aRank, aSearch, aBookmark)
|
||||
{
|
||||
// Bump up the visit count for the uri
|
||||
for (let i = 0; i < aCount; i++)
|
||||
@ -175,6 +184,16 @@ function setCountRank(aURI, aCount, aRank, aSearch)
|
||||
for (let i = 0; i < aRank; i++) {
|
||||
obs.notifyObservers(thing, "autocomplete-will-enter-text", null);
|
||||
}
|
||||
|
||||
// If this is supposed to be a bookmark, add it.
|
||||
if (aBookmark) {
|
||||
bsvc.insertBookmark(bsvc.unfiledBookmarksFolder, aURI, bsvc.DEFAULT_INDEX,
|
||||
"test_book");
|
||||
|
||||
// And add the tag if we need to.
|
||||
if (aBookmark == "tag")
|
||||
tsvc.tagURI(aURI, "test_tag");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,15 +219,14 @@ let s1 = "si";
|
||||
let s2 = "site";
|
||||
|
||||
let observer = {
|
||||
uriA: null,
|
||||
uriB: null,
|
||||
results: null,
|
||||
search: null,
|
||||
runCount: -1,
|
||||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
if (PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC == aTopic &&
|
||||
!(--this.runCount)) {
|
||||
ensure_results([this.uriA, this.uriB], this.search);
|
||||
ensure_results(this.results, this.search);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -221,14 +239,30 @@ function prepTest(name) {
|
||||
print("Test " + name);
|
||||
bhist.removeAllPages();
|
||||
observer.runCount = -1;
|
||||
|
||||
// Remove all bookmarks and tags.
|
||||
bsvc.removeFolderChildren(bsvc.unfiledBookmarksFolder);
|
||||
bsvc.removeFolderChildren(bsvc.tagsFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the result object for a given URI that will be passed to ensure_results.
|
||||
*/
|
||||
function makeResult(aURI) {
|
||||
return {
|
||||
uri: aURI,
|
||||
style: "favicon",
|
||||
};
|
||||
}
|
||||
|
||||
let tests = [
|
||||
// Test things without a search term
|
||||
function() {
|
||||
prepTest("0 same count, diff rank, same term; no search");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c1, s2);
|
||||
@ -236,8 +270,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("1 same count, diff rank, same term; no search");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c2, s2);
|
||||
@ -245,8 +281,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("2 diff count, same rank, same term; no search");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri1, c1, c1, s2);
|
||||
@ -254,8 +292,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("3 diff count, same rank, same term; no search");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri1, c2, c1, s2);
|
||||
@ -265,8 +305,10 @@ let tests = [
|
||||
// Test things with a search term (exact match one, partial other)
|
||||
function() {
|
||||
prepTest("4 same count, same rank, diff term; one exact/one partial search");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri1, c1, c1, s1);
|
||||
@ -274,8 +316,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("5 same count, same rank, diff term; one exact/one partial search");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri1, c1, c1, s2);
|
||||
@ -285,8 +329,10 @@ let tests = [
|
||||
// Test things with a search term (exact match both)
|
||||
function() {
|
||||
prepTest("6 same count, diff rank, same term; both exact search");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c1, s1);
|
||||
@ -294,8 +340,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("7 same count, diff rank, same term; both exact search");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c2, s1);
|
||||
@ -305,8 +353,10 @@ let tests = [
|
||||
// Test things with a search term (partial match both)
|
||||
function() {
|
||||
prepTest("8 same count, diff rank, same term; both partial search");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c1, s2);
|
||||
@ -314,8 +364,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("9 same count, diff rank, same term; both partial search");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c2, s2);
|
||||
@ -323,8 +375,10 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("10 same count, same rank, same term, decay first; exact match");
|
||||
observer.uriA = uri2;
|
||||
observer.uriB = uri1;
|
||||
observer.results = [
|
||||
makeResult(uri2),
|
||||
makeResult(uri1),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri1, c1, c1, s1);
|
||||
@ -333,18 +387,47 @@ let tests = [
|
||||
},
|
||||
function() {
|
||||
prepTest("11 same count, same rank, same term, decay second; exact match");
|
||||
observer.uriA = uri1;
|
||||
observer.uriB = uri2;
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s1;
|
||||
observer.runCount = c1 + c1;
|
||||
setCountRank(uri2, c1, c1, s1);
|
||||
doAdaptiveDecay();
|
||||
setCountRank(uri1, c1, c1, s1);
|
||||
},
|
||||
// Test that bookmarks or tags are hidden if the preferences are set right.
|
||||
function() {
|
||||
prepTest("12 same count, diff rank, same term; no search; history only");
|
||||
prefs.setIntPref("browser.urlbar.matchBehavior",
|
||||
Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY);
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c1, s2, "bookmark");
|
||||
setCountRank(uri2, c1, c2, s2);
|
||||
},
|
||||
function() {
|
||||
prepTest("13 same count, diff rank, same term; no search; history only with tag");
|
||||
prefs.setIntPref("browser.urlbar.matchBehavior",
|
||||
Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY);
|
||||
observer.results = [
|
||||
makeResult(uri1),
|
||||
makeResult(uri2),
|
||||
];
|
||||
observer.search = s0;
|
||||
observer.runCount = c1 + c2;
|
||||
setCountRank(uri1, c1, c1, s2, "tag");
|
||||
setCountRank(uri2, c1, c2, s2);
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Test adapative autocomplete
|
||||
* Test adaptive autocomplete
|
||||
*/
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
@ -66,15 +66,7 @@ function run_test() {
|
||||
dates.sort();
|
||||
|
||||
// Get and cleanup the backups folder.
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
if (bookmarksBackupDir.exists()) {
|
||||
bookmarksBackupDir.remove(true);
|
||||
do_check_false(bookmarksBackupDir.exists());
|
||||
}
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
|
||||
var bookmarksBackupDir = PlacesUtils.backups.folder;
|
||||
|
||||
// Fake backups are created backwards to ensure we won't consider file
|
||||
// creation time.
|
||||
@ -98,7 +90,7 @@ function run_test() {
|
||||
return LOCALIZED_PREFIX + aValue;
|
||||
}
|
||||
|
||||
PlacesUtils.archiveBookmarksFile(Math.floor(dates.length/2));
|
||||
PlacesUtils.backups.create(Math.floor(dates.length/2));
|
||||
// Add today's backup.
|
||||
dates.push(dateObj.toLocaleFormat("%Y-%m-%d"));
|
||||
|
||||
@ -123,5 +115,6 @@ function run_test() {
|
||||
// Cleanup backups folder.
|
||||
bookmarksBackupDir.remove(true);
|
||||
do_check_false(bookmarksBackupDir.exists());
|
||||
bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
|
||||
// Recreate the folder.
|
||||
PlacesUtils.backups.folder;
|
||||
}
|
@ -37,23 +37,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const LAST_VACUUM_PREF = "last_vacuum";
|
||||
const VACUUM_THRESHOLD = 0.1;
|
||||
const PLACES_VACUUM_STARTING_TOPIC = "places-vacuum-starting";
|
||||
|
||||
function getDBVacuumRatio() {
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let freelistStmt = dbConn.createStatement("PRAGMA freelist_count");
|
||||
freelistStmt.executeStep();
|
||||
let freelistCount = freelistStmt.row.freelist_count;
|
||||
@ -67,31 +58,7 @@ function getDBVacuumRatio() {
|
||||
return ratio;
|
||||
}
|
||||
|
||||
function generateSparseDB(aType) {
|
||||
let limit = 0;
|
||||
if (aType == "low")
|
||||
limit = 10;
|
||||
else if (aType == "high")
|
||||
limit = 200;
|
||||
|
||||
let batch = {
|
||||
runBatched: function batch_runBatched() {
|
||||
for (let i = 0; i < limit; i++) {
|
||||
hs.addVisit(uri("http://" + i + ".mozilla.com/"),
|
||||
Date.now() * 1000 + i, null, hs.TRANSITION_TYPED, false, 0);
|
||||
}
|
||||
for (let i = 0; i < limit; i++) {
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
uri("http://" + i + "." + i + ".mozilla.com/"),
|
||||
bs.DEFAULT_INDEX, "bookmark " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
hs.runInBatchMode(batch, null);
|
||||
bh.removeAllPages();
|
||||
bs.removeFolderChildren(bs.unfiledBookmarksFolder);
|
||||
}
|
||||
|
||||
/* Only low ratio tests. Stop at first vacuum. */
|
||||
var gTests = [
|
||||
{
|
||||
desc: "Low ratio, last vacuum today",
|
||||
@ -113,28 +80,24 @@ var gTests = [
|
||||
elapsedDays: 61,
|
||||
vacuum: true
|
||||
},
|
||||
|
||||
{
|
||||
desc: "High ratio, last vacuum today",
|
||||
ratio: "high",
|
||||
elapsedDays: 0,
|
||||
vacuum: false
|
||||
},
|
||||
];
|
||||
|
||||
var observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
function run_test() {
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
|
||||
function run_test() {
|
||||
// This test is disabled for now, generateSparseDB is randomly failing.
|
||||
return;
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
while (gTests.length) {
|
||||
observer.vacuum = false;
|
||||
@ -142,13 +105,9 @@ function run_test() {
|
||||
print("PLACES TEST: " + test.desc);
|
||||
let ratio = getDBVacuumRatio();
|
||||
if (test.ratio == "high") {
|
||||
if (ratio < VACUUM_THRESHOLD)
|
||||
generateSparseDB("high");
|
||||
do_check_true(getDBVacuumRatio() > VACUUM_THRESHOLD);
|
||||
do_throw("This test only supports low ratio cases");
|
||||
}
|
||||
else if (test.ratio == "low") {
|
||||
if (ratio == 0)
|
||||
generateSparseDB("low");
|
||||
do_check_true(getDBVacuumRatio() < VACUUM_THRESHOLD);
|
||||
}
|
||||
print("current ratio is " + getDBVacuumRatio());
|
||||
|
@ -37,23 +37,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const LAST_VACUUM_PREF = "last_vacuum";
|
||||
const VACUUM_THRESHOLD = 0.1;
|
||||
const PLACES_VACUUM_STARTING_TOPIC = "places-vacuum-starting";
|
||||
|
||||
function getDBVacuumRatio() {
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let freelistStmt = dbConn.createStatement("PRAGMA freelist_count");
|
||||
freelistStmt.executeStep();
|
||||
let freelistCount = freelistStmt.row.freelist_count;
|
||||
@ -67,32 +58,14 @@ function getDBVacuumRatio() {
|
||||
return ratio;
|
||||
}
|
||||
|
||||
function generateSparseDB(aType) {
|
||||
let limit = 0;
|
||||
if (aType == "low")
|
||||
limit = 10;
|
||||
else if (aType == "high")
|
||||
limit = 200;
|
||||
|
||||
let batch = {
|
||||
runBatched: function batch_runBatched() {
|
||||
for (let i = 0; i < limit; i++) {
|
||||
hs.addVisit(uri("http://" + i + ".mozilla.com/"),
|
||||
Date.now() * 1000 + i, null, hs.TRANSITION_TYPED, false, 0);
|
||||
}
|
||||
for (let i = 0; i < limit; i++) {
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
uri("http://" + i + "." + i + ".mozilla.com/"),
|
||||
bs.DEFAULT_INDEX, "bookmark " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
hs.runInBatchMode(batch, null);
|
||||
bh.removeAllPages();
|
||||
bs.removeFolderChildren(bs.unfiledBookmarksFolder);
|
||||
}
|
||||
|
||||
/* Only high ratio tests. Stop at first vacuum. */
|
||||
var gTests = [
|
||||
{
|
||||
desc: "High ratio, last vacuum today",
|
||||
ratio: "high",
|
||||
elapsedDays: 0,
|
||||
vacuum: false
|
||||
},
|
||||
{
|
||||
desc: "High ratio, last vacuum two months ago",
|
||||
ratio: "high",
|
||||
@ -101,19 +74,25 @@ var gTests = [
|
||||
},
|
||||
];
|
||||
|
||||
var observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
function run_test() {
|
||||
let sparseDB = do_get_file("places.sparse.sqlite");
|
||||
sparseDB.copyTo(do_get_profile(), "places.sqlite");
|
||||
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
|
||||
function run_test() {
|
||||
// This test is disabled for now, generateSparseDB is randomly failing.
|
||||
return;
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
while (gTests.length) {
|
||||
observer.vacuum = false;
|
||||
@ -121,14 +100,10 @@ function run_test() {
|
||||
print("PLACES TEST: " + test.desc);
|
||||
let ratio = getDBVacuumRatio();
|
||||
if (test.ratio == "high") {
|
||||
if (ratio < VACUUM_THRESHOLD)
|
||||
generateSparseDB("high");
|
||||
do_check_true(getDBVacuumRatio() > VACUUM_THRESHOLD);
|
||||
}
|
||||
else if (test.ratio == "low") {
|
||||
if (ratio == 0)
|
||||
generateSparseDB("low");
|
||||
do_check_true(getDBVacuumRatio() < VACUUM_THRESHOLD);
|
||||
do_throw("This test only supports high ratio cases");
|
||||
}
|
||||
print("current ratio is " + getDBVacuumRatio());
|
||||
prefs.setIntPref(LAST_VACUUM_PREF, ((Date.now() / 1000) - (test.elapsedDays * 24 * 60 * 60)));
|
||||
|
@ -37,23 +37,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const LAST_VACUUM_PREF = "last_vacuum";
|
||||
const VACUUM_THRESHOLD = 0.1;
|
||||
const PLACES_VACUUM_STARTING_TOPIC = "places-vacuum-starting";
|
||||
|
||||
function getDBVacuumRatio() {
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let freelistStmt = dbConn.createStatement("PRAGMA freelist_count");
|
||||
freelistStmt.executeStep();
|
||||
let freelistCount = freelistStmt.row.freelist_count;
|
||||
@ -67,31 +58,7 @@ function getDBVacuumRatio() {
|
||||
return ratio;
|
||||
}
|
||||
|
||||
function generateSparseDB(aType) {
|
||||
let limit = 0;
|
||||
if (aType == "low")
|
||||
limit = 10;
|
||||
else if (aType == "high")
|
||||
limit = 200;
|
||||
|
||||
let batch = {
|
||||
runBatched: function batch_runBatched() {
|
||||
for (let i = 0; i < limit; i++) {
|
||||
hs.addVisit(uri("http://" + i + ".mozilla.com/"),
|
||||
Date.now() * 1000 + i, null, hs.TRANSITION_TYPED, false, 0);
|
||||
}
|
||||
for (let i = 0; i < limit; i++) {
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
uri("http://" + i + "." + i + ".mozilla.com/"),
|
||||
bs.DEFAULT_INDEX, "bookmark " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
hs.runInBatchMode(batch, null);
|
||||
bh.removeAllPages();
|
||||
bs.removeFolderChildren(bs.unfiledBookmarksFolder);
|
||||
}
|
||||
|
||||
/* Only high ratio tests. Stop at first vacuum. */
|
||||
var gTests = [
|
||||
{
|
||||
desc: "High ratio, last vacuum two months ago",
|
||||
@ -101,19 +68,25 @@ var gTests = [
|
||||
},
|
||||
];
|
||||
|
||||
var observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
function run_test() {
|
||||
let sparseDB = do_get_file("places.sparse.sqlite");
|
||||
sparseDB.copyTo(do_get_profile(), "places.sqlite");
|
||||
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let observer = {
|
||||
vacuum: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == PLACES_VACUUM_STARTING_TOPIC) {
|
||||
this.vacuum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
os.addObserver(observer, PLACES_VACUUM_STARTING_TOPIC, false);
|
||||
|
||||
function run_test() {
|
||||
// This test is disabled for now, generateSparseDB is randomly failing.
|
||||
return;
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
while (gTests.length) {
|
||||
observer.vacuum = false;
|
||||
@ -121,14 +94,10 @@ function run_test() {
|
||||
print("PLACES TEST: " + test.desc);
|
||||
let ratio = getDBVacuumRatio();
|
||||
if (test.ratio == "high") {
|
||||
if (ratio < VACUUM_THRESHOLD)
|
||||
generateSparseDB("high");
|
||||
do_check_true(getDBVacuumRatio() > VACUUM_THRESHOLD);
|
||||
}
|
||||
else if (test.ratio == "low") {
|
||||
if (ratio == 0)
|
||||
generateSparseDB("low");
|
||||
do_check_true(getDBVacuumRatio() < VACUUM_THRESHOLD);
|
||||
do_throw("This test only supports high ratio cases");
|
||||
}
|
||||
print("current ratio is " + getDBVacuumRatio());
|
||||
prefs.setIntPref(LAST_VACUUM_PREF, ((Date.now() / 1000) - (test.elapsedDays * 24 * 60 * 60)));
|
||||
|
@ -165,9 +165,9 @@ function commonDialogOnLoad()
|
||||
|
||||
// set the icon
|
||||
var iconElement = document.getElementById("info.icon");
|
||||
var iconClass = gCommonDialogParam.GetString(2);
|
||||
if (iconClass)
|
||||
iconElement.classList.add(iconClass);
|
||||
var iconClasses = gCommonDialogParam.GetString(2);
|
||||
if (iconClasses)
|
||||
iconElement.className += " " + iconClasses;
|
||||
|
||||
switch (nButtons) {
|
||||
case 4:
|
||||
|
@ -98,12 +98,15 @@ interface nsIXULWindow : nsISupports
|
||||
|
||||
/**
|
||||
* Move the window to a centered position.
|
||||
* @param aRelative the window relative to which the window is moved.
|
||||
* See screen parameter for details. if null, the
|
||||
* window is centered relative to the main screen.
|
||||
* @param aRelative If not null, the window relative to which the window is
|
||||
* moved. See aScreen parameter for details.
|
||||
* @param aScreen PR_TRUE to center the window relative to the screen
|
||||
* containing aRelative. PR_FALSE to center it relative
|
||||
* to aRelative itself.
|
||||
* containing aRelative if aRelative is not null. If
|
||||
* aRelative is null then relative to the screen of the
|
||||
* opener window if it was initialized by passing it to
|
||||
* nsWebShellWindow::Initialize. Failing that relative to
|
||||
* the main screen.
|
||||
* PR_FALSE to center it relative to aRelative itself.
|
||||
* @param aAlert PR_TRUE to move the window to an alert position,
|
||||
* generally centered horizontally and 1/3 down from the top.
|
||||
*/
|
||||
|
@ -238,7 +238,10 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// the addref resulting from this is the owning addref for this window
|
||||
RegisterTopLevelWindow(*aResult);
|
||||
(*aResult)->SetZLevel(CalculateWindowZLevel(aParent, aChromeMask));
|
||||
nsCOMPtr<nsIXULWindow> parent;
|
||||
if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
|
||||
parent = aParent;
|
||||
(*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask));
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -295,6 +298,10 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
nsCOMPtr<nsIXULWindow> parent;
|
||||
if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
|
||||
parent = aParent;
|
||||
|
||||
nsRefPtr<nsWebShellWindow> window = new nsWebShellWindow(aChromeMask);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
@ -319,7 +326,7 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
|
||||
PRUint32 sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
if (aParent && ((aChromeMask & sheetMask) == sheetMask))
|
||||
if (parent && ((aChromeMask & sheetMask) == sheetMask))
|
||||
widgetInitData.mWindowType = eWindowType_sheet;
|
||||
#endif
|
||||
|
||||
@ -361,18 +368,21 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
|
||||
window->SetIntrinsicallySized(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult rv = window->Initialize(aParent, aAppShell, aUrl,
|
||||
PRBool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
|
||||
|
||||
nsresult rv = window->Initialize(parent, center ? aParent : nsnull,
|
||||
aAppShell, aUrl,
|
||||
aInitialWidth, aInitialHeight,
|
||||
aIsHiddenWindow, widgetInitData);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
window.swap(*aResult); // transfer reference
|
||||
if (aParent)
|
||||
aParent->AddChildWindow(*aResult);
|
||||
if (parent)
|
||||
parent->AddChildWindow(*aResult);
|
||||
|
||||
if (aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN)
|
||||
rv = (*aResult)->Center(aParent, aParent ? PR_FALSE : PR_TRUE, PR_FALSE);
|
||||
if (center)
|
||||
rv = (*aResult)->Center(parent, parent ? PR_FALSE : PR_TRUE, PR_FALSE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -150,7 +150,8 @@ NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsXULWindow)
|
||||
|
||||
nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
|
||||
nsIAppShell* aShell, nsIURI* aUrl,
|
||||
nsIXULWindow* aOpener,
|
||||
nsIAppShell* aShell, nsIURI* aUrl,
|
||||
PRInt32 aInitialWidth,
|
||||
PRInt32 aInitialHeight,
|
||||
PRBool aIsHiddenWindow,
|
||||
@ -160,7 +161,18 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
|
||||
mIsHiddenWindow = aIsHiddenWindow;
|
||||
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aOpener));
|
||||
if (base) {
|
||||
rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
|
||||
&mOpenerScreenRect.y,
|
||||
&mOpenerScreenRect.width,
|
||||
&mOpenerScreenRect.height);
|
||||
if (NS_FAILED(rv)) {
|
||||
mOpenerScreenRect.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: need to get the default window size from prefs...
|
||||
// Doesn't come from prefs... will come from CSS/XUL/RDF
|
||||
nsIntRect r(0, 0, aInitialWidth, aInitialHeight);
|
||||
|
@ -62,8 +62,8 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsWebShellWindow methods...
|
||||
nsresult Initialize(nsIXULWindow * aParent, nsIAppShell* aShell,
|
||||
nsIURI* aUrl,
|
||||
nsresult Initialize(nsIXULWindow * aParent, nsIXULWindow * aOpener,
|
||||
nsIAppShell* aShell, nsIURI* aUrl,
|
||||
PRInt32 aInitialWidth, PRInt32 aInitialHeight,
|
||||
PRBool aIsHiddenWindow,
|
||||
nsWidgetInitData& widgetInitData);
|
||||
|
@ -685,8 +685,15 @@ NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, PRBool aScreen, PRBoo
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!aRelative)
|
||||
screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
|
||||
if (!aRelative) {
|
||||
if (!mOpenerScreenRect.IsEmpty()) {
|
||||
screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
|
||||
mOpenerScreenRect.width, mOpenerScreenRect.height,
|
||||
getter_AddRefs(screen));
|
||||
} else {
|
||||
screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
|
||||
}
|
||||
}
|
||||
|
||||
if (aScreen && screen) {
|
||||
screen->GetAvailRect(&left, &top, &width, &height);
|
||||
@ -1691,13 +1698,9 @@ NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(PRInt32 aChromeFlags,
|
||||
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
|
||||
|
||||
// Just do a normal create of a window and return.
|
||||
//XXXTAB remove this when appshell talks in terms of nsIXULWindow
|
||||
nsCOMPtr<nsIXULWindow> parent;
|
||||
if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
|
||||
parent = this;
|
||||
|
||||
nsCOMPtr<nsIXULWindow> newWindow;
|
||||
appShell->CreateTopLevelWindow(parent, nsnull, aChromeFlags,
|
||||
appShell->CreateTopLevelWindow(this, nsnull, aChromeFlags,
|
||||
nsIAppShellService::SIZE_TO_CONTENT,
|
||||
nsIAppShellService::SIZE_TO_CONTENT,
|
||||
aAppShell, getter_AddRefs(newWindow));
|
||||
@ -1719,10 +1722,6 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags,
|
||||
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
|
||||
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIXULWindow> parent;
|
||||
if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
|
||||
parent = this;
|
||||
|
||||
// We need to create a new top level window and then enter a nested
|
||||
// loop. Eventually the new window will be told that it has loaded,
|
||||
// at which time we know it is safe to spin out of the nested loop
|
||||
@ -1747,9 +1746,9 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags,
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIXULWindow> newWindow;
|
||||
appShell->CreateTopLevelWindow(parent, uri,
|
||||
aChromeFlags, 615, 480, aAppShell,
|
||||
getter_AddRefs(newWindow));
|
||||
appShell->CreateTopLevelWindow(this, uri,
|
||||
aChromeFlags, 615, 480, aAppShell,
|
||||
getter_AddRefs(newWindow));
|
||||
|
||||
NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -68,11 +68,11 @@
|
||||
// nsXULWindow
|
||||
|
||||
#define NS_XULWINDOW_IMPL_CID \
|
||||
{ /* 2a38ef7e-3174-44ad-a785-b5a863cf5588 */ \
|
||||
0x2a38ef7e, \
|
||||
0x3174, \
|
||||
0x44ad, \
|
||||
{ 0xa7, 0x85, 0xb5, 0xa8, 0x63, 0xcf, 0x55, 0x88 } \
|
||||
{ /* 8eaec2f3-ed02-4be2-8e0f-342798477298 */ \
|
||||
0x8eaec2f3, \
|
||||
0xed02, \
|
||||
0x4be2, \
|
||||
{ 0x8e, 0x0f, 0x34, 0x27, 0x98, 0x47, 0x72, 0x98 } \
|
||||
}
|
||||
|
||||
class nsContentShellInfo;
|
||||
@ -177,6 +177,7 @@ protected:
|
||||
PRUint32 mAppPerDev; // sometimes needed when we can't get
|
||||
// it from the widget
|
||||
nsString mTitle;
|
||||
nsIntRect mOpenerScreenRect; // the screen rect of the opener
|
||||
|
||||
nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user