Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
shindli 2018-03-15 12:18:31 +02:00
Родитель 3a631decc0 9bfc016707
Коммит b5ff200fa2
176 изменённых файлов: 7136 добавлений и 4165 удалений

Просмотреть файл

@ -17,7 +17,7 @@ add_task(async function() {
// function.
let acc = await new Promise(resolve => {
let intervalId = setInterval(() => {
let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
let tabAcc = accService.getAccessibleFor(gBrowser.selectedTab);
if (tabAcc) {
clearInterval(intervalId);
resolve(tabAcc);

Просмотреть файл

@ -20,7 +20,7 @@ add_task(async function() {
// function.
let acc = await new Promise(resolve => {
let intervalId = setInterval(() => {
let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
let tabAcc = accService.getAccessibleFor(gBrowser.selectedTab);
if (tabAcc) {
clearInterval(intervalId);
resolve(tabAcc);

Просмотреть файл

@ -20,7 +20,7 @@ add_task(async function() {
// function.
let acc = await new Promise(resolve => {
let intervalId = setInterval(() => {
let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
let tabAcc = accService.getAccessibleFor(gBrowser.selectedTab);
if (tabAcc) {
clearInterval(intervalId);
resolve(tabAcc);

Просмотреть файл

@ -36,13 +36,6 @@
// Hacky stuffs
// This is the hacks needed to use a searchbar without browser.js.
function getBrowser()
{
return {
mCurrentBrowser: { engines: new Array() }
};
}
var BrowserSearch = {
updateOpenSearchBadge: function() {}
};

Просмотреть файл

@ -63,12 +63,6 @@
}
// This is the hacks needed to use a searchbar without browser.js.
function getBrowser()
{
return {
mCurrentBrowser: { engines: new Array() }
};
}
var BrowserSearch = {
updateOpenSearchBadge: function() {}
};

Просмотреть файл

@ -1398,18 +1398,7 @@ var BookmarkingUI = {
MOBILE_BOOKMARKS_PREF: "browser.bookmarks.showMobileBookmarks",
_shouldShowMobileBookmarks() {
try {
return Services.prefs.getBoolPref(this.MOBILE_BOOKMARKS_PREF);
} catch (e) {}
// No pref set (or invalid pref set), look for a mobile bookmarks left pane query.
const organizerQueryAnno = "PlacesOrganizer/OrganizerQuery";
const mobileBookmarksAnno = "MobileBookmarks";
let shouldShow = PlacesUtils.annotations.getItemsWithAnnotation(organizerQueryAnno, {}).filter(
id => PlacesUtils.annotations.getItemAnnotation(id, organizerQueryAnno) == mobileBookmarksAnno
).length > 0;
// Sync will change this pref if/when it adds a mobile bookmarks query.
Services.prefs.setBoolPref(this.MOBILE_BOOKMARKS_PREF, shouldShow);
return shouldShow;
return Services.prefs.getBoolPref(this.MOBILE_BOOKMARKS_PREF, false);
},
_initMobileBookmarks(mobileMenuItem) {

Просмотреть файл

@ -27,16 +27,6 @@ window._gBrowser = {
this._setupInitialBrowserAndTab();
// Hook up the event listeners to the first browser
var tabListener = new TabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true, false);
const nsIWebProgress = Ci.nsIWebProgress;
const filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(nsIWebProgress);
filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL);
this._tabListeners.set(this.mCurrentTab, tabListener);
this._tabFilters.set(this.mCurrentTab, filter);
this.webProgress.addProgressListener(filter, nsIWebProgress.NOTIFY_ALL);
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
this.mPanelContainer.style.backgroundColor = "-moz-default-background-color";
} else if (Services.prefs.getIntPref("browser.display.document_color_use") == 2) {
@ -60,8 +50,8 @@ window._gBrowser = {
// which does asynchronous tab switching.
this.mPanelContainer.classList.add("tabbrowser-tabpanels");
} else {
this._outerWindowIDBrowserMap.set(this.mCurrentBrowser.outerWindowID,
this.mCurrentBrowser);
this._outerWindowIDBrowserMap.set(this.selectedBrowser.outerWindowID,
this.selectedBrowser);
}
messageManager.addMessageListener("DOMWindowFocus", this);
messageManager.addMessageListener("RefreshBlocker:Blocked", this);
@ -257,16 +247,16 @@ window._gBrowser = {
},
get popupAnchor() {
if (this.mCurrentTab._popupAnchor) {
return this.mCurrentTab._popupAnchor;
if (this.selectedTab._popupAnchor) {
return this.selectedTab._popupAnchor;
}
let stack = this.mCurrentBrowser.parentNode;
let stack = this.selectedBrowser.parentNode;
// Create an anchor for the popup
let popupAnchor = document.createElementNS(this._XUL_NS, "hbox");
popupAnchor.className = "popup-anchor";
popupAnchor.hidden = true;
stack.appendChild(popupAnchor);
return this.mCurrentTab._popupAnchor = popupAnchor;
return this.selectedTab._popupAnchor = popupAnchor;
},
set selectedTab(val) {
@ -279,11 +269,11 @@ window._gBrowser = {
},
get selectedTab() {
return this.mCurrentTab;
return this._selectedTab;
},
get selectedBrowser() {
return this.mCurrentBrowser;
return this._selectedBrowser;
},
get initialBrowser() {
@ -293,7 +283,7 @@ window._gBrowser = {
_setupInitialBrowserAndTab() {
let browser = this.initialBrowser;
this.mCurrentBrowser = browser;
this._selectedBrowser = browser;
browser.permanentKey = {};
browser.droppedLinkHandler = handleDroppedLink;
@ -304,7 +294,7 @@ window._gBrowser = {
browser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
let tab = this.tabs[0];
this.mCurrentTab = tab;
this._selectedTab = tab;
let uniqueId = this._generateUniquePanelID();
this.mPanelContainer.childNodes[0].id = uniqueId;
@ -314,6 +304,15 @@ window._gBrowser = {
tab._fullyOpen = true;
tab.linkedBrowser = browser;
this._tabForBrowser.set(browser, tab);
// Hook the browser up with a progress listener.
let tabListener = new TabProgressListener(tab, browser, true, false);
let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
filter.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL);
this._tabListeners.set(tab, tabListener);
this._tabFilters.set(tab, filter);
browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
},
/**
@ -321,38 +320,38 @@ window._gBrowser = {
* MAKE SURE TO ADD IT HERE AS WELL.
*/
get canGoBack() {
return this.mCurrentBrowser.canGoBack;
return this.selectedBrowser.canGoBack;
},
get canGoForward() {
return this.mCurrentBrowser.canGoForward;
return this.selectedBrowser.canGoForward;
},
goBack() {
return this.mCurrentBrowser.goBack();
return this.selectedBrowser.goBack();
},
goForward() {
return this.mCurrentBrowser.goForward();
return this.selectedBrowser.goForward();
},
reload() {
return this.mCurrentBrowser.reload();
return this.selectedBrowser.reload();
},
reloadWithFlags(aFlags) {
return this.mCurrentBrowser.reloadWithFlags(aFlags);
return this.selectedBrowser.reloadWithFlags(aFlags);
},
stop() {
return this.mCurrentBrowser.stop();
return this.selectedBrowser.stop();
},
/**
* throws exception for unknown schemes
*/
loadURI(aURI, aReferrerURI, aCharset) {
return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
return this.selectedBrowser.loadURI(aURI, aReferrerURI, aCharset);
},
/**
@ -364,112 +363,112 @@ window._gBrowser = {
// (b) loadURIWithFlags(aURI, { flags: aFlags, ... })
// Forwarding it as (a) here actually supports both (a) and (b),
// so you can call us either way too.
return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
return this.selectedBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
},
goHome() {
return this.mCurrentBrowser.goHome();
return this.selectedBrowser.goHome();
},
gotoIndex(aIndex) {
return this.mCurrentBrowser.gotoIndex(aIndex);
return this.selectedBrowser.gotoIndex(aIndex);
},
set homePage(val) {
this.mCurrentBrowser.homePage = val;
this.selectedBrowser.homePage = val;
return val;
},
get homePage() {
return this.mCurrentBrowser.homePage;
return this.selectedBrowser.homePage;
},
get currentURI() {
return this.mCurrentBrowser.currentURI;
return this.selectedBrowser.currentURI;
},
get finder() {
return this.mCurrentBrowser.finder;
return this.selectedBrowser.finder;
},
get docShell() {
return this.mCurrentBrowser.docShell;
return this.selectedBrowser.docShell;
},
get webNavigation() {
return this.mCurrentBrowser.webNavigation;
return this.selectedBrowser.webNavigation;
},
get webBrowserFind() {
return this.mCurrentBrowser.webBrowserFind;
return this.selectedBrowser.webBrowserFind;
},
get webProgress() {
return this.mCurrentBrowser.webProgress;
return this.selectedBrowser.webProgress;
},
get contentWindow() {
return this.mCurrentBrowser.contentWindow;
return this.selectedBrowser.contentWindow;
},
get contentWindowAsCPOW() {
return this.mCurrentBrowser.contentWindowAsCPOW;
return this.selectedBrowser.contentWindowAsCPOW;
},
get sessionHistory() {
return this.mCurrentBrowser.sessionHistory;
return this.selectedBrowser.sessionHistory;
},
get markupDocumentViewer() {
return this.mCurrentBrowser.markupDocumentViewer;
return this.selectedBrowser.markupDocumentViewer;
},
get contentDocument() {
return this.mCurrentBrowser.contentDocument;
return this.selectedBrowser.contentDocument;
},
get contentDocumentAsCPOW() {
return this.mCurrentBrowser.contentDocumentAsCPOW;
return this.selectedBrowser.contentDocumentAsCPOW;
},
get contentTitle() {
return this.mCurrentBrowser.contentTitle;
return this.selectedBrowser.contentTitle;
},
get contentPrincipal() {
return this.mCurrentBrowser.contentPrincipal;
return this.selectedBrowser.contentPrincipal;
},
get securityUI() {
return this.mCurrentBrowser.securityUI;
return this.selectedBrowser.securityUI;
},
set fullZoom(val) {
this.mCurrentBrowser.fullZoom = val;
this.selectedBrowser.fullZoom = val;
},
get fullZoom() {
return this.mCurrentBrowser.fullZoom;
return this.selectedBrowser.fullZoom;
},
set textZoom(val) {
this.mCurrentBrowser.textZoom = val;
this.selectedBrowser.textZoom = val;
},
get textZoom() {
return this.mCurrentBrowser.textZoom;
return this.selectedBrowser.textZoom;
},
get isSyntheticDocument() {
return this.mCurrentBrowser.isSyntheticDocument;
return this.selectedBrowser.isSyntheticDocument;
},
set userTypedValue(val) {
return this.mCurrentBrowser.userTypedValue = val;
return this.selectedBrowser.userTypedValue = val;
},
get userTypedValue() {
return this.mCurrentBrowser.userTypedValue;
return this.selectedBrowser.userTypedValue;
},
isFindBarInitialized(aTab) {
@ -660,11 +659,11 @@ window._gBrowser = {
},
getBrowserContainer(aBrowser) {
return (aBrowser || this.mCurrentBrowser).parentNode.parentNode;
return (aBrowser || this.selectedBrowser).parentNode.parentNode;
},
getTabModalPromptBox(aBrowser) {
let browser = (aBrowser || this.mCurrentBrowser);
let browser = (aBrowser || this.selectedBrowser);
if (!browser.tabModalPromptBox) {
browser.tabModalPromptBox = new TabModalPromptBox(browser);
}
@ -699,9 +698,9 @@ window._gBrowser = {
}
}
aBrowser = aBrowser || this.mCurrentBrowser;
aBrowser = aBrowser || this.selectedBrowser;
if (aCallGlobalListeners && aBrowser == this.mCurrentBrowser) {
if (aCallGlobalListeners && aBrowser == this.selectedBrowser) {
callListeners(this.mProgressListeners, aArguments);
}
@ -884,13 +883,14 @@ window._gBrowser = {
},
updateTitlebar() {
document.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
document.title = this.getWindowTitleForBrowser(this.selectedBrowser);
},
updateCurrentBrowser(aForceUpdate) {
var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
if (this.selectedBrowser == newBrowser && !aForceUpdate) {
return;
}
if (!aForceUpdate) {
document.commandDispatcher.lock();
@ -921,7 +921,7 @@ window._gBrowser = {
}
}
var oldTab = this.mCurrentTab;
let oldTab = this.selectedTab;
// Preview mode should not reset the owner
if (!this._previewMode && !oldTab.selected)
@ -934,7 +934,7 @@ window._gBrowser = {
}
this._lastRelatedTabMap = new WeakMap();
var oldBrowser = this.mCurrentBrowser;
let oldBrowser = this.selectedBrowser;
if (!gMultiProcessBrowser) {
oldBrowser.removeAttribute("primary");
@ -947,12 +947,12 @@ window._gBrowser = {
var updateBlockedPopups = false;
if ((oldBrowser.blockedPopups && !newBrowser.blockedPopups) ||
(!oldBrowser.blockedPopups && newBrowser.blockedPopups))
(!oldBrowser.blockedPopups && newBrowser.blockedPopups))
updateBlockedPopups = true;
this.mCurrentBrowser = newBrowser;
this.mCurrentTab = this.tabContainer.selectedItem;
this.showTab(this.mCurrentTab);
this._selectedBrowser = newBrowser;
this._selectedTab = this.tabContainer.selectedItem;
this.showTab(this.selectedTab);
gURLBar.setAttribute("switchingtabs", "true");
window.addEventListener("MozAfterPaint", function() {
@ -962,13 +962,13 @@ window._gBrowser = {
this._appendStatusPanel();
if (updateBlockedPopups)
this.mCurrentBrowser.updateBlockedPopups();
this.selectedBrowser.updateBlockedPopups();
// Update the URL bar.
var loc = this.mCurrentBrowser.currentURI;
let loc = this.selectedBrowser.currentURI;
var webProgress = this.mCurrentBrowser.webProgress;
var securityUI = this.mCurrentBrowser.securityUI;
let webProgress = this.selectedBrowser.webProgress;
let securityUI = this.selectedBrowser.securityUI;
this._callProgressListeners(null, "onLocationChange",
[webProgress, null, loc, 0],
@ -982,7 +982,7 @@ window._gBrowser = {
true, false);
}
var listener = this._tabListeners.get(this.mCurrentTab);
let listener = this._tabListeners.get(this.selectedTab);
if (listener && listener.mStateFlags) {
this._callProgressListeners(null, "onUpdateCurrentBrowser",
[listener.mStateFlags, listener.mStatus,
@ -991,8 +991,8 @@ window._gBrowser = {
}
if (!this._previewMode) {
this.mCurrentTab.updateLastAccessed();
this.mCurrentTab.removeAttribute("unread");
this.selectedTab.updateLastAccessed();
this.selectedTab.removeAttribute("unread");
oldTab.updateLastAccessed();
let oldFindBar = oldTab._findBar;
@ -1003,22 +1003,22 @@ window._gBrowser = {
this.updateTitlebar();
this.mCurrentTab.removeAttribute("titlechanged");
this.mCurrentTab.removeAttribute("attention");
this.selectedTab.removeAttribute("titlechanged");
this.selectedTab.removeAttribute("attention");
// The tab has been selected, it's not unselected anymore.
// (1) Call the current tab's finishUnselectedTabHoverTimer()
// to save a telemetry record.
// (2) Call the current browser's unselectedTabHover() with false
// to dispatch an event.
this.mCurrentTab.finishUnselectedTabHoverTimer();
this.mCurrentBrowser.unselectedTabHover(false);
this.selectedTab.finishUnselectedTabHoverTimer();
this.selectedBrowser.unselectedTabHover(false);
}
// If the new tab is busy, and our current state is not busy, then
// we need to fire a start to all progress listeners.
const nsIWebProgressListener = Ci.nsIWebProgressListener;
if (this.mCurrentTab.hasAttribute("busy") && !this.mIsBusy) {
if (this.selectedTab.hasAttribute("busy") && !this.mIsBusy) {
this.mIsBusy = true;
this._callProgressListeners(null, "onStateChange",
[webProgress, null,
@ -1029,7 +1029,7 @@ window._gBrowser = {
// If the new tab is not busy, and our current state is busy, then
// we need to fire a stop to all progress listeners.
if (!this.mCurrentTab.hasAttribute("busy") && this.mIsBusy) {
if (!this.selectedTab.hasAttribute("busy") && this.mIsBusy) {
this.mIsBusy = false;
this._callProgressListeners(null, "onStateChange",
[webProgress, null,
@ -1050,10 +1050,10 @@ window._gBrowser = {
previousTab: oldTab
}
});
this.mCurrentTab.dispatchEvent(event);
this.selectedTab.dispatchEvent(event);
this._tabAttrModified(oldTab, ["selected"]);
this._tabAttrModified(this.mCurrentTab, ["selected"]);
this._tabAttrModified(this.selectedTab, ["selected"]);
if (oldBrowser != newBrowser &&
oldBrowser.getInPermitUnload) {
@ -1082,8 +1082,8 @@ window._gBrowser = {
}
if (!gMultiProcessBrowser) {
this._adjustFocusBeforeTabSwitch(oldTab, this.mCurrentTab);
this._adjustFocusAfterTabSwitch(this.mCurrentTab);
this._adjustFocusBeforeTabSwitch(oldTab, this.selectedTab);
this._adjustFocusAfterTabSwitch(this.selectedTab);
}
}
@ -1096,7 +1096,7 @@ window._gBrowser = {
// session to allow the user to easily drag the selected tab.
// This is currently only supported on Windows.
oldTab.removeAttribute("touchdownstartsdrag");
this.mCurrentTab.setAttribute("touchdownstartsdrag", "true");
this.selectedTab.setAttribute("touchdownstartsdrag", "true");
if (!gMultiProcessBrowser) {
document.commandDispatcher.unlock();
@ -1247,8 +1247,9 @@ window._gBrowser = {
}
this._tabAttrModified(tab, ["sharing"]);
if (aBrowser == this.mCurrentBrowser)
if (aBrowser == this.selectedBrowser) {
gIdentityHandler.updateSharingIndicator();
}
},
getTabSharingState(aTab) {
@ -1500,7 +1501,7 @@ window._gBrowser = {
browser = this.getBrowserForTab(aTargetTab);
targetTabIndex = aTargetTab._tPos;
} else {
browser = this.mCurrentBrowser;
browser = this.selectedBrowser;
targetTabIndex = this.tabContainer.selectedIndex;
}
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
@ -2213,8 +2214,9 @@ window._gBrowser = {
}
// if we're adding tabs, we're past interrupt mode, ditch the owner
if (this.mCurrentTab.owner)
this.mCurrentTab.owner = null;
if (this.selectedTab.owner) {
this.selectedTab.owner = null;
}
// Find the tab that opened this one, if any. This is used for
// determining positioning, and inherited attributes such as the
@ -2613,7 +2615,7 @@ window._gBrowser = {
},
removeCurrentTab(aParams) {
this.removeTab(this.mCurrentTab, aParams);
this.removeTab(this.selectedTab, aParams);
},
removeTab(aTab, aParams) {
@ -3396,7 +3398,7 @@ window._gBrowser = {
this._lastRelatedTabMap = new WeakMap();
}
let wasFocused = (document.activeElement == this.mCurrentTab);
let wasFocused = (document.activeElement == this.selectedTab);
aIndex = aIndex < aTab._tPos ? aIndex : aIndex + 1;
@ -3417,7 +3419,7 @@ window._gBrowser = {
// is set to true on two different tabs.
//
// What we want to do in moveTabTo is to remove logical selection
// from all tabs, and then re-add logical selection to mCurrentTab
// from all tabs, and then re-add logical selection to selectedTab
// (and visual selection as well if we're not running with e10s, which
// setting _selected will do automatically).
//
@ -3427,10 +3429,10 @@ window._gBrowser = {
// correct, and if we are in the midst of a tab switch, then the async
// tab switcher will set the visually selected tab once the tab switch
// has completed.
this.mCurrentTab._selected = true;
this.selectedTab._selected = true;
if (wasFocused)
this.mCurrentTab.focus();
this.selectedTab.focus();
this.tabContainer._handleTabSelect(true);
@ -3445,12 +3447,12 @@ window._gBrowser = {
},
moveTabForward() {
let nextTab = this.mCurrentTab.nextSibling;
let nextTab = this.selectedTab.nextSibling;
while (nextTab && nextTab.hidden)
nextTab = nextTab.nextSibling;
if (nextTab)
this.moveTabTo(this.mCurrentTab, nextTab._tPos);
this.moveTabTo(this.selectedTab, nextTab._tPos);
else if (this.arrowKeysShouldWrap)
this.moveTabToStart();
},
@ -3512,26 +3514,26 @@ window._gBrowser = {
},
moveTabBackward() {
let previousTab = this.mCurrentTab.previousSibling;
let previousTab = this.selectedTab.previousSibling;
while (previousTab && previousTab.hidden)
previousTab = previousTab.previousSibling;
if (previousTab)
this.moveTabTo(this.mCurrentTab, previousTab._tPos);
this.moveTabTo(this.selectedTab, previousTab._tPos);
else if (this.arrowKeysShouldWrap)
this.moveTabToEnd();
},
moveTabToStart() {
var tabPos = this.mCurrentTab._tPos;
let tabPos = this.selectedTab._tPos;
if (tabPos > 0)
this.moveTabTo(this.mCurrentTab, 0);
this.moveTabTo(this.selectedTab, 0);
},
moveTabToEnd() {
var tabPos = this.mCurrentTab._tPos;
let tabPos = this.selectedTab._tPos;
if (tabPos < this.browsers.length - 1)
this.moveTabTo(this.mCurrentTab, this.browsers.length - 1);
this.moveTabTo(this.selectedTab, this.browsers.length - 1);
},
moveTabOver(aEvent) {
@ -3624,7 +3626,7 @@ window._gBrowser = {
if (AppConstants.platform != "macosx") {
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
!this.mCurrentTab.pinned) {
!this.selectedTab.pinned) {
this.removeCurrentTab({ animate: true });
aEvent.preventDefault();
}
@ -3721,9 +3723,9 @@ window._gBrowser = {
case "sizemodechange":
case "occlusionstatechange":
if (aEvent.target == window && !this._switcher) {
this.mCurrentBrowser.preserveLayers(
this.selectedBrowser.preserveLayers(
window.windowState == window.STATE_MINIMIZED || window.isFullyOccluded);
this.mCurrentBrowser.docShellIsActive = this.shouldActivateDocShell(this.mCurrentBrowser);
this.selectedBrowser.docShellIsActive = this.shouldActivateDocShell(this.selectedBrowser);
}
break;
}

Просмотреть файл

@ -206,10 +206,6 @@ let InternalFaviconLoader = {
};
var PlacesUIUtils = {
ORGANIZER_LEFTPANE_VERSION: 8,
ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
ORGANIZER_QUERY_ANNO: "PlacesOrganizer/OrganizerQuery",
LOAD_IN_SIDEBAR_ANNO: "bookmarkProperties/loadInSidebar",
DESCRIPTION_ANNO: "bookmarkProperties/description",
@ -531,11 +527,16 @@ var PlacesUIUtils = {
}
// Is it a query pointing to one of the special root folders?
if (PlacesUtils.nodeIsQuery(parentNode) && PlacesUtils.nodeIsFolder(aNode)) {
let guid = PlacesUtils.getConcreteItemGuid(aNode);
// If the parent folder is not a folder, it must be a query, and so this node
// cannot be removed.
if (PlacesUtils.isRootItem(guid)) {
if (PlacesUtils.nodeIsQuery(parentNode)) {
if (PlacesUtils.nodeIsFolder(aNode)) {
let guid = PlacesUtils.getConcreteItemGuid(aNode);
// If the parent folder is not a folder, it must be a query, and so this node
// cannot be removed.
if (PlacesUtils.isRootItem(guid)) {
return false;
}
} else if (PlacesUtils.isVirtualLeftPaneItem(aNode.bookmarkGuid)) {
// If the item is a left-pane top-level item, it can't be removed.
return false;
}
}
@ -590,21 +591,7 @@ var PlacesUIUtils = {
view.controller.hasCachedLivemarkInfo(placesNode))
return true;
// leftPaneFolderId is a lazy getter
// performing at least a synchronous DB query (and on its very first call
// in a fresh profile, it also creates the entire structure).
// Therefore we don't want to this function, which is called very often by
// isCommandEnabled, to ever be the one that invokes it first, especially
// because isCommandEnabled may be called way before the left pane folder is
// even created (for example, if the user only uses the bookmarks menu or
// toolbar for managing bookmarks). To do so, we avoid comparing to those
// special folder if the lazy getter is still in place. This is safe merely
// because the only way to access the left pane contents goes through
// "resolving" the leftPaneFolderId getter.
if (typeof Object.getOwnPropertyDescriptor(this, "leftPaneFolderId").get == "function") {
return false;
}
return itemId == this.leftPaneFolderId;
return false;
},
/** aItemsToOpen needs to be an array of objects of the form:
@ -814,261 +801,6 @@ var PlacesUIUtils = {
return title || this.getString("noTitle");
},
get leftPaneQueries() {
// build the map
this.leftPaneFolderId;
return this.leftPaneQueries;
},
get leftPaneFolderId() {
delete this.leftPaneFolderId;
return this.leftPaneFolderId = this.maybeRebuildLeftPane();
},
// Get the folder id for the organizer left-pane folder.
maybeRebuildLeftPane() {
let leftPaneRoot = -1;
// Shortcuts to services.
let bs = PlacesUtils.bookmarks;
let as = PlacesUtils.annotations;
// This is the list of the left pane queries.
let queries = {
"PlacesRoot": { title: "" },
"History": { title: this.getString("OrganizerQueryHistory") },
"Downloads": { title: this.getString("OrganizerQueryDownloads") },
"Tags": { title: this.getString("OrganizerQueryTags") },
"AllBookmarks": { title: this.getString("OrganizerQueryAllBookmarks") },
};
// All queries but PlacesRoot.
const EXPECTED_QUERY_COUNT = 4;
// Removes an item and associated annotations, ignoring eventual errors.
function safeRemoveItem(aItemId) {
try {
if (as.itemHasAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO) &&
!(as.getItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO) in queries)) {
// Some extension annotated their roots with our query annotation,
// so we should not delete them.
return;
}
// removeItemAnnotation does not check if item exists, nor the anno,
// so this is safe to do.
as.removeItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
as.removeItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO);
// This will throw if the annotation is an orphan.
bs.removeItem(aItemId);
} catch (e) { /* orphan anno */ }
}
// Returns true if item really exists, false otherwise.
function itemExists(aItemId) {
try {
bs.getFolderIdForItem(aItemId);
return true;
} catch (e) {
return false;
}
}
// Get all items marked as being the left pane folder.
let items = as.getItemsWithAnnotation(this.ORGANIZER_FOLDER_ANNO);
if (items.length > 1) {
// Something went wrong, we cannot have more than one left pane folder,
// remove all left pane folders and continue. We will create a new one.
items.forEach(safeRemoveItem);
} else if (items.length == 1 && items[0] != -1) {
leftPaneRoot = items[0];
// Check that organizer left pane root is valid.
let version = as.getItemAnnotation(leftPaneRoot, this.ORGANIZER_FOLDER_ANNO);
if (version != this.ORGANIZER_LEFTPANE_VERSION ||
!itemExists(leftPaneRoot)) {
// Invalid root, we must rebuild the left pane.
safeRemoveItem(leftPaneRoot);
leftPaneRoot = -1;
}
}
if (leftPaneRoot != -1) {
// A valid left pane folder has been found.
// Build the leftPaneQueries Map. This is used to quickly access them,
// associating a mnemonic name to the real item ids.
delete this.leftPaneQueries;
this.leftPaneQueries = {};
let queryItems = as.getItemsWithAnnotation(this.ORGANIZER_QUERY_ANNO);
// While looping through queries we will also check for their validity.
let queriesCount = 0;
let corrupt = false;
for (let i = 0; i < queryItems.length; i++) {
let queryName = as.getItemAnnotation(queryItems[i], this.ORGANIZER_QUERY_ANNO);
// Some extension did use our annotation to decorate their items
// with icons, so we should check only our elements, to avoid dataloss.
if (!(queryName in queries))
continue;
let query = queries[queryName];
query.itemId = queryItems[i];
if (!itemExists(query.itemId)) {
// Orphan annotation, bail out and create a new left pane root.
corrupt = true;
break;
}
// Check that all queries have valid parents.
let parentId = bs.getFolderIdForItem(query.itemId);
if (!queryItems.includes(parentId) && parentId != leftPaneRoot) {
// The parent is not part of the left pane, bail out and create a new
// left pane root.
corrupt = true;
break;
}
// Titles could have been corrupted or the user could have changed his
// locale. Check title and eventually fix it.
if (bs.getItemTitle(query.itemId) != query.title)
bs.setItemTitle(query.itemId, query.title);
if ("concreteId" in query) {
if (bs.getItemTitle(query.concreteId) != query.concreteTitle)
bs.setItemTitle(query.concreteId, query.concreteTitle);
}
// Add the query to our cache.
this.leftPaneQueries[queryName] = query.itemId;
queriesCount++;
}
// Note: it's not enough to just check for queriesCount, since we may
// find an invalid query just after accounting for a sufficient number of
// valid ones. As well as we can't just rely on corrupt since we may find
// less valid queries than expected.
if (corrupt || queriesCount != EXPECTED_QUERY_COUNT) {
// Queries number is wrong, so the left pane must be corrupt.
// Note: we can't just remove the leftPaneRoot, because some query could
// have a bad parent, so we have to remove all items one by one.
queryItems.forEach(safeRemoveItem);
safeRemoveItem(leftPaneRoot);
} else {
// Everything is fine, return the current left pane folder.
return leftPaneRoot;
}
}
// Create a new left pane folder.
var callback = {
// Helper to create an organizer special query.
create_query: function CB_create_query(aQueryName, aParentId, aQueryUrl) {
let itemId = bs.insertBookmark(aParentId,
Services.io.newURI(aQueryUrl),
bs.DEFAULT_INDEX,
queries[aQueryName].title);
// Mark as special organizer query.
as.setItemAnnotation(itemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO, aQueryName,
0, as.EXPIRE_NEVER);
// We should never backup this, since it changes between profiles.
as.setItemAnnotation(itemId, PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1,
0, as.EXPIRE_NEVER);
// Add to the queries map.
PlacesUIUtils.leftPaneQueries[aQueryName] = itemId;
return itemId;
},
// Helper to create an organizer special folder.
create_folder: function CB_create_folder(aFolderName, aParentId, aIsRoot) {
// Left Pane Root Folder.
let folderId = bs.createFolder(aParentId,
queries[aFolderName].title,
bs.DEFAULT_INDEX);
// We should never backup this, since it changes between profiles.
as.setItemAnnotation(folderId, PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1,
0, as.EXPIRE_NEVER);
if (aIsRoot) {
// Mark as special left pane root.
as.setItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION,
0, as.EXPIRE_NEVER);
} else {
// Mark as special organizer folder.
as.setItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_QUERY_ANNO, aFolderName,
0, as.EXPIRE_NEVER);
PlacesUIUtils.leftPaneQueries[aFolderName] = folderId;
}
return folderId;
},
runBatched: function CB_runBatched(aUserData) {
delete PlacesUIUtils.leftPaneQueries;
PlacesUIUtils.leftPaneQueries = { };
// Left Pane Root Folder.
leftPaneRoot = this.create_folder("PlacesRoot", bs.placesRoot, true);
// History Query.
this.create_query("History", leftPaneRoot,
"place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING);
// Downloads.
this.create_query("Downloads", leftPaneRoot,
"place:transition=" +
Ci.nsINavHistoryService.TRANSITION_DOWNLOAD +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING);
// Tags Query.
this.create_query("Tags", leftPaneRoot,
"place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_TITLE_ASCENDING);
// All Bookmarks Folder.
this.create_query("AllBookmarks", leftPaneRoot,
"place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY);
}
};
bs.runInBatchMode(callback, null);
return leftPaneRoot;
},
/**
* If an item is a left-pane query, returns the name of the query
* or an empty string if not.
*
* @param aItemId id of a container
* @return the name of the query, or empty string if not a left-pane query
*/
getLeftPaneQueryNameFromId: function PUIU_getLeftPaneQueryNameFromId(aItemId) {
var queryName = "";
// If the let pane hasn't been built, use the annotation service
// directly, to avoid building the left pane too early.
if (Object.getOwnPropertyDescriptor(this, "leftPaneFolderId").value === undefined) {
try {
queryName = PlacesUtils.annotations.
getItemAnnotation(aItemId, this.ORGANIZER_QUERY_ANNO);
} catch (ex) {
// doesn't have the annotation
queryName = "";
}
} else {
// If the left pane has already been built, use the name->id map
// cached in PlacesUIUtils.
for (let [name, id] of Object.entries(this.leftPaneQueries)) {
if (aItemId == id)
queryName = name;
}
}
return queryName;
},
shouldShowTabsFromOtherComputersMenuitem() {
let weaveOK = Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED &&
Weave.Svc.Prefs.get("firstSync", "") != "notReady";
@ -1354,14 +1086,7 @@ function canMoveUnwrappedNode(unwrappedNode) {
parentGuid == PlacesUtils.bookmarks.rootGuid) {
return false;
}
// leftPaneFolderId and allBookmarksFolderId are lazy getters running
// at least a synchronous DB query. Therefore we don't want to invoke
// them first, especially because isCommandEnabled may be called way
// before the left pane folder is even necessary.
if (typeof Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId").get != "function" &&
(unwrappedNode.parent == PlacesUIUtils.leftPaneFolderId)) {
return false;
}
return true;
}

Просмотреть файл

@ -56,12 +56,6 @@ var gEditItemOverlay = {
}
let parent = node.parent;
isParentReadOnly = !PlacesUtils.nodeIsFolder(parent);
if (!isParentReadOnly) {
let folderId = PlacesUtils.getConcreteItemId(parent);
isParentReadOnly = folderId == PlacesUtils.placesRootId ||
(!("get" in Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId")) &&
(folderId == PlacesUIUtils.leftPaneFolderId));
}
parentId = parent.itemId;
parentGuid = parent.bookmarkGuid;
}

Просмотреть файл

@ -36,8 +36,7 @@ var PlacesOrganizer = {
],
_initFolderTree() {
var leftPaneRoot = PlacesUIUtils.leftPaneFolderId;
this._places.place = "place:excludeItems=1&expandQueries=0&folder=" + leftPaneRoot;
this._places.place = `place:type=${Ci.nsINavHistoryQueryOptions.RESULTS_AS_LEFT_PANE_QUERY}&excludeItems=1&expandQueries=0`;
},
/**
@ -50,31 +49,34 @@ var PlacesOrganizer = {
selectLeftPaneBuiltIn(item) {
switch (item) {
case "AllBookmarks":
case "History":
case "Downloads":
case "Tags": {
var itemId = PlacesUIUtils.leftPaneQueries[item];
this._places.selectItems([itemId]);
// Forcefully expand all-bookmarks
if (item == "AllBookmarks" || item == "History")
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
this._places.selectItems([PlacesUtils.virtualAllBookmarksGuid]);
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
break;
case "History":
this._places.selectItems([PlacesUtils.virtualHistoryGuid]);
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
break;
case "Downloads":
this._places.selectItems([PlacesUtils.virtualDownloadsGuid]);
break;
case "Tags":
this._places.selectItems([PlacesUtils.virtualTagsGuid]);
break;
}
case "BookmarksMenu":
this.selectLeftPaneContainerByHierarchy([
PlacesUIUtils.leftPaneQueries.AllBookmarks,
PlacesUtils.virtualAllBookmarksGuid,
PlacesUtils.bookmarks.virtualMenuGuid
]);
break;
case "BookmarksToolbar":
this.selectLeftPaneContainerByHierarchy([
PlacesUIUtils.leftPaneQueries.AllBookmarks,
PlacesUtils.virtualAllBookmarksGuid,
PlacesUtils.bookmarks.virtualToolbarGuid
]);
break;
case "UnfiledBookmarks":
this.selectLeftPaneContainerByHierarchy([
PlacesUIUtils.leftPaneQueries.AllBookmarks,
PlacesUtils.virtualAllBookmarksGuid,
PlacesUtils.bookmarks.virtualUnfiledGuid
]);
break;
@ -92,7 +94,6 @@ var PlacesOrganizer = {
* container may be either an item id, a Places URI string,
* or a named query, like:
* "BookmarksMenu", "BookmarksToolbar", "UnfiledBookmarks", "AllBookmarks".
* @see PlacesUIUtils.leftPaneQueries for supported named queries.
*/
selectLeftPaneContainerByHierarchy(aHierarchy) {
if (!aHierarchy)
@ -312,12 +313,12 @@ var PlacesOrganizer = {
* the node to set up scope from
*/
_setSearchScopeForNode: function PO__setScopeForNode(aNode) {
let itemId = aNode.itemId;
let itemGuid = aNode.bookmarkGuid;
if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
itemId == PlacesUIUtils.leftPaneQueries.History) {
itemGuid == PlacesUtils.virtualHistoryGuid) {
PlacesQueryBuilder.setScope("history");
} else if (itemId == PlacesUIUtils.leftPaneQueries.Downloads) {
} else if (itemGuid == PlacesUtils.virtualDownloadsGuid) {
PlacesQueryBuilder.setScope("downloads");
} else {
// Default to All Bookmarks for all other nodes, per bug 469437.

Просмотреть файл

@ -632,7 +632,7 @@
// caller. We support the "AllBookmarks" case to allow callers to
// specify just the top-level bookmark folders.
let shouldOpen = aOpenContainers && (PlacesUtils.nodeIsFolder(node) ||
(PlacesUtils.nodeIsQuery(node) && node.itemId == PlacesUIUtils.leftPaneQueries.AllBookmarks));
(PlacesUtils.nodeIsQuery(node) && node.bookmarkGuid == PlacesUIUtils.virtualAllBookmarksGuid));
PlacesUtils.asContainer(node);
if (!node.containerOpen && !shouldOpen)

Просмотреть файл

@ -138,6 +138,7 @@ PlacesTreeView.prototype = {
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY:
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY:
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_LEFT_PANE_QUERY:
return false;
}
@ -1305,11 +1306,13 @@ PlacesTreeView.prototype = {
case PlacesUtils.bookmarks.virtualUnfiledGuid:
properties += ` queryFolder_${PlacesUtils.bookmarks.unfiledGuid}`;
break;
case PlacesUtils.virtualAllBookmarksGuid:
case PlacesUtils.virtualHistoryGuid:
case PlacesUtils.virtualDownloadsGuid:
case PlacesUtils.virtualTagsGuid:
properties += ` OrganizerQuery_${node.bookmarkGuid}`;
break;
}
} else {
let queryName = PlacesUIUtils.getLeftPaneQueryNameFromId(itemId);
if (queryName)
properties += " OrganizerQuery_" + queryName;
}
} else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
properties += " separator";
@ -1792,15 +1795,6 @@ PlacesTreeView.prototype = {
PlacesUtils.isQueryGeneratedFolder(itemGuid))
return false;
let parentId = PlacesUtils.getConcreteItemId(node.parent);
if (parentId == PlacesUIUtils.leftPaneFolderId) {
// Note that the for the time being this is the check that actually
// blocks renaming places "roots", and not the isRootItem check above.
// That's because places root are only exposed through folder shortcuts
// descendants of the left pane folder.
return false;
}
return true;
},

Просмотреть файл

@ -15,50 +15,31 @@ support-files =
[browser_bookmark_add_tags.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmark_change_location.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmark_folder_moveability.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmark_load_in_sidebar.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmark_private_window.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmark_remove_tags.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarklet_windowOpen.js]
support-files =
bookmarklet_windowOpen_dummy.html
[browser_bookmarks_change_title.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarks_sidebar_search.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
support-files =
pageopeningwindow.html
[browser_bookmarkProperties_addFolderDefaultButton.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_addKeywordForThisSearch.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_addLivemark.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_bookmarkAllTabs.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_cancel.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_editTagContainer.js]
[browser_bookmarkProperties_no_user_actions.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarkProperties_readOnlyRoot.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_bookmarksProperties.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_check_correct_controllers.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_click_bookmarks_on_toolbar.js]
[browser_controller_onDrop_sidebar.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_controller_onDrop_tagFolder.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_controller_onDrop.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_copy_query_without_tree.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
subsuite = clipboard
@ -79,7 +60,7 @@ skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_library_downloads.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_library_infoBox.js]
[browser_library_left_pane_fixnames.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_library_left_pane_middleclick.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_library_left_pane_select_hierarchy.js]
@ -109,7 +90,7 @@ subsuite = clipboard
[browser_sidebar_open_bookmarks.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_sidebarpanels_click.js]
skip-if = (os == 'win' && ccov) || (os == "mac" && debug) # Bug 1423667
skip-if = (os == "mac" && debug) # Bug 1423667
[browser_sort_in_library.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
[browser_stayopenmenu.js]
@ -118,7 +99,6 @@ skip-if = os == "mac" && debug # bug 1400323
[browser_toolbar_overflow.js]
[browser_toolbarbutton_menu_context.js]
[browser_views_iconsupdate.js]
skip-if = (os == 'win' && ccov) # Bug 1423667
support-files =
favicon-normal16.png
[browser_views_liveupdate.js]

Просмотреть файл

@ -50,7 +50,7 @@ add_task(async function copy_mobile_shortcut() {
});
library.PlacesOrganizer.selectLeftPaneContainerByHierarchy([
PlacesUIUtils.leftPaneQueries.AllBookmarks,
PlacesUtils.virtualAllBookmarksGuid,
PlacesUtils.bookmarks.virtualMobileGuid,
]);

Просмотреть файл

@ -1,71 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Test we correctly fix broken Library left pane queries names.
*/
// Array of left pane queries objects, each one has the following properties:
// name: query's identifier got from annotations,
// itemId: query's itemId,
// correctTitle: original and correct query's title.
var leftPaneQueries = [];
function onLibraryReady(organizer) {
// Check titles have been fixed.
for (var i = 0; i < leftPaneQueries.length; i++) {
var query = leftPaneQueries[i];
if ("concreteId" in query) {
is(PlacesUtils.bookmarks.getItemTitle(query.concreteId),
query.concreteTitle, "Concrete title is correct for query " + query.name);
}
}
// Close Library window.
organizer.close();
// No need to cleanup anything, we have a correct left pane now.
finish();
}
function test() {
waitForExplicitFinish();
// Ensure left pane is initialized.
ok(PlacesUIUtils.leftPaneFolderId > 0, "left pane folder is initialized");
// Get the left pane folder.
var leftPaneItems = PlacesUtils.annotations
.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
// Check version.
var version = PlacesUtils.annotations
.getItemAnnotation(leftPaneItems[0],
PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual");
// Get all left pane queries.
var items = PlacesUtils.annotations
.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_QUERY_ANNO);
// Get current queries names.
for (var i = 0; i < items.length; i++) {
var itemId = items[i];
var queryName = PlacesUtils.annotations
.getItemAnnotation(items[i],
PlacesUIUtils.ORGANIZER_QUERY_ANNO);
var query = { name: queryName,
itemId,
correctTitle: PlacesUtils.bookmarks.getItemTitle(itemId) };
leftPaneQueries.push(query);
// Rename to a bad title.
PlacesUtils.bookmarks.setItemTitle(query.itemId, "badName");
}
restoreLeftPaneGetters();
// Open Library, this will kick-off left pane code.
openLibrary(onLibraryReady);
}

Просмотреть файл

@ -30,98 +30,33 @@ const TEST_DOWNLOAD_URL = "http://dummy.mozilla.org/dummy.pdf";
var gLibrary;
var testCases = [
function allBookmarksScope() {
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries.AllBookmarks);
search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
},
function historyScope() {
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries.History);
search(PlacesUIUtils.leftPaneQueries.History, "dummy", defScope);
},
function downloadsScope() {
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries.Downloads);
search(PlacesUIUtils.leftPaneQueries.Downloads, "dummy", defScope);
},
];
/**
* Returns the default search scope for a given folder.
*
* @param aFolderId
* the item ID of a node in the left pane's tree
* @return the default scope when the folder is newly selected
*/
function getDefaultScope(aFolderId) {
switch (aFolderId) {
case PlacesUIUtils.leftPaneQueries.History:
return "scopeBarHistory";
case PlacesUIUtils.leftPaneQueries.Downloads:
return "scopeBarDownloads";
default:
return "scopeBarAll";
}
}
/**
* Returns the single nsINavHistoryQuery represented by a given place URI.
*
* @param aPlaceURI
* a URI that represents a single query
* @return an nsINavHistoryQuery object
*/
function queryStringToQuery(aPlaceURI) {
let queries = {};
PlacesUtils.history.queryStringToQueries(aPlaceURI, queries, {}, {});
return queries.value[0];
}
/**
* Resets the search by clearing the search box's text and ensures that the
* search scope remains as expected.
*
* @param aExpectedScopeButtonId
* this button should be selected after the reset
*/
function resetSearch(aExpectedScopeButtonId) {
search(null, "", aExpectedScopeButtonId);
}
/**
* Performs a search for a given folder and search string and ensures that the
* URI of the right pane's content tree is as expected for the folder and search
* string. Also ensures that the search scope button is as expected after the
* search.
*
* @param aFolderId
* the item ID of a node in the left pane's tree
* @param aFolderGuid
* the item guid of a node in the left pane's tree
* @param aSearchStr
* the search text; may be empty to reset the search
* @param aExpectedScopeButtonId
* after searching the selected scope button should be this
*/
function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
async function search(aFolderGuid, aSearchStr) {
let doc = gLibrary.document;
let folderTree = doc.getElementById("placesList");
let contentTree = doc.getElementById("placeContent");
// First, ensure that selecting the folder in the left pane updates the
// content tree properly.
if (aFolderId) {
folderTree.selectItems([aFolderId]);
isnot(folderTree.selectedNode, null,
if (aFolderGuid) {
folderTree.selectItems([aFolderGuid]);
Assert.notEqual(folderTree.selectedNode, null,
"Sanity check: left pane tree should have selection after selecting!");
// getFolders() on a History query returns an empty array, so no use
// comparing against aFolderId in that case.
if (aFolderId !== PlacesUIUtils.leftPaneQueries.History &&
aFolderId !== PlacesUIUtils.leftPaneQueries.Downloads) {
// contentTree.place should be equal to contentTree.result.root.uri,
// but it's not until bug 476952 is fixed.
let query = queryStringToQuery(contentTree.result.root.uri);
is(query.getFolders()[0], aFolderId,
// The downloads folder never quite matches the url of the contentTree,
// probably due to the way downloads are loaded.
if (aFolderGuid !== PlacesUtils.virtualDownloadsGuid) {
Assert.equal(folderTree.selectedNode.uri, contentTree.place,
"Content tree's folder should be what was selected in the left pane");
}
}
@ -131,13 +66,14 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
let searchBox = doc.getElementById("searchFilter");
searchBox.value = aSearchStr;
gLibrary.PlacesSearchBox.search(searchBox.value);
let query = queryStringToQuery(contentTree.result.root.uri);
let queries = {};
PlacesUtils.history.queryStringToQueries(contentTree.result.root.uri, queries, {}, {});
if (aSearchStr) {
is(query.searchTerms, aSearchStr,
"Content tree's searchTerms should be text in search box");
Assert.equal(queries.value[0].searchTerms, aSearchStr,
"Content tree's searchTerms should be text in search box");
} else {
is(query.hasSearchTerms, false,
"Content tree's searchTerms should not exist after search reset");
Assert.equal(queries.value[0].hasSearchTerms, false,
"Content tree's searchTerms should not exist after search reset");
}
}
@ -160,7 +96,15 @@ add_task(async function test() {
gLibrary = await promiseLibrary();
testCases.forEach(aTest => aTest());
const rootsToTest = [
PlacesUtils.virtualAllBookmarksGuid,
PlacesUtils.virtualHistoryGuid,
PlacesUtils.virtualDownloadsGuid,
];
for (let root of rootsToTest) {
await search(root, "dummy");
}
await promiseLibraryClosed(gLibrary);

Просмотреть файл

@ -5,27 +5,6 @@ ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
ChromeUtils.defineModuleGetter(this, "TestUtils",
"resource://testing-common/TestUtils.jsm");
// We need to cache these before test runs...
let leftPaneGetters = new Map([["leftPaneFolderId", null]]);
for (let [key, val] of leftPaneGetters) {
if (!val) {
let getter = Object.getOwnPropertyDescriptor(PlacesUIUtils, key).get;
if (typeof getter == "function") {
leftPaneGetters.set(key, getter);
}
}
}
// ...And restore them when test ends.
function restoreLeftPaneGetters() {
for (let [key, getter] of leftPaneGetters) {
Object.defineProperty(PlacesUIUtils, key, {
enumerable: true, configurable: true, get: getter
});
}
}
registerCleanupFunction(restoreLeftPaneGetters);
function openLibrary(callback, aLeftPaneRoot) {
let library = window.openDialog("chrome://browser/content/places/places.xul",
"", "chrome,toolbar=yes,dialog=no,resizable",

Просмотреть файл

@ -3,16 +3,12 @@ support-files = head.js
[test_0_bug510634.xul]
[test_bug1163447_selectItems_through_shortcut.xul]
skip-if = (os == 'win' && ccov) # Bug 1423667
[test_bug427633_no_newfolder_if_noip.xul]
[test_bug485100-change-case-loses-tag.xul]
[test_bug549192.xul]
[test_bug549491.xul]
[test_bug631374_tags_selector_scroll.xul]
[test_editBookmarkOverlay_keywords.xul]
skip-if = (os == 'win' && ccov) # Bug 1423667
[test_editBookmarkOverlay_tags_liveUpdate.xul]
skip-if = (os == 'win' && ccov) # Bug 1423667
[test_selectItems_on_nested_tree.xul]
skip-if = (os == 'win' && ccov) # Bug 1423667
[test_treeview_date.xul]

Просмотреть файл

@ -37,58 +37,41 @@
* Bug 510634 - Wrong icons on bookmarks sidebar
* https://bugzilla.mozilla.org/show_bug.cgi?id=510634
*
* Ensures that properties for special queries are set on their tree nodes,
* even if PlacesUIUtils.leftPaneFolderId was not initialized.
* Ensures that properties for special queries are set on their tree nodes.
*/
SimpleTest.waitForExplicitFinish();
function runTest() {
// We need to cache and restore the getters in order to simulate
// Bug 510634.
let leftPaneGetters = new Map([["leftPaneFolderId", null]]);
for (let [key, val] of leftPaneGetters) {
if (!val) {
let getter = Object.getOwnPropertyDescriptor(PlacesUIUtils, key).get;
if (typeof getter == "function") {
leftPaneGetters.set(key, getter);
}
}
}
function restoreLeftPaneGetters() {
for (let [key, getter] of leftPaneGetters) {
Object.defineProperty(PlacesUIUtils, key, {
enumerable: true, configurable: true, get: getter
});
}
}
let leftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
restoreLeftPaneGetters();
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = "place:queryType=1&folder=" + leftPaneFolderId;
tree.place = `place:type=${Ci.nsINavHistoryQueryOptions.RESULTS_AS_LEFT_PANE_QUERY}&excludeItems=1&expandQueries=0`;
// The query-property is set on the title column for each row.
let titleColumn = tree.treeBoxObject.columns.getColumnAt(0);
// Open All Bookmarks
tree.selectItems([PlacesUIUtils.leftPaneQueries["AllBookmarks"]]);
tree.selectItems([PlacesUtils.virtualAllBookmarksGuid]);
PlacesUtils.asContainer(tree.selectedNode).containerOpen = true;
is(tree.selectedNode.uri,
"place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY +
"&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS,
"Opened All Bookmarks");
for (let queryName of ["History", "Downloads", "Tags", "AllBookmarks"]) {
const topLevelGuids = [
PlacesUtils.virtualHistoryGuid,
PlacesUtils.virtualDownloadsGuid,
PlacesUtils.virtualTagsGuid,
PlacesUtils.virtualAllBookmarksGuid
];
for (let queryName of topLevelGuids) {
let found = false;
for (let i = 0; i < tree.view.rowCount && !found; i++) {
rowProperties = tree.view.getCellProperties(i, titleColumn).split(" ");
found = rowProperties.includes("OrganizerQuery_" + queryName);
}
ok(found, "OrganizerQuery_" + queryName + " is set");
ok(found, `OrganizerQuery_${queryName} is set`);
}
const folderGuids = [
@ -103,15 +86,12 @@
rowProperties = tree.view.getCellProperties(i, titleColumn).split(" ");
found = rowProperties.includes("queryFolder_" + guid);
}
ok(found, "queryFolder_" + guid + " is set");
ok(found, `queryFolder_${guid} is set`);
}
// Close the root node
tree.result.root.containerOpen = false;
// Restore the getters for the next test.
restoreLeftPaneGetters();
SimpleTest.finish();
}

Просмотреть файл

@ -20,9 +20,6 @@ XPCOMUtils.defineLazyGetter(this, "PlacesUIUtils", function() {
return PlacesUIUtils;
});
const ORGANIZER_FOLDER_ANNO = "PlacesOrganizer/OrganizerFolder";
const ORGANIZER_QUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
// Needed by some test that relies on having an app registered.
ChromeUtils.import("resource://testing-common/AppInfo.jsm", this);
updateAppInfo({

Просмотреть файл

@ -1,149 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Tests that we build a working leftpane in various corruption situations.
*/
// Used to store the original leftPaneFolderId getter.
var gLeftPaneFolderIdGetter;
// Used to store the original left Pane status as a JSON string.
var gReferenceHierarchy;
var gLeftPaneFolderId;
add_task(async function() {
// We want empty roots.
await PlacesUtils.bookmarks.eraseEverything();
// Sanity check.
Assert.ok(!!PlacesUIUtils);
// Check getters.
gLeftPaneFolderIdGetter = Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId");
Assert.equal(typeof(gLeftPaneFolderIdGetter.get), "function");
registerCleanupFunction(() => PlacesUtils.bookmarks.eraseEverything());
});
add_task(async function() {
// Add a third party bogus annotated item. Should not be removed.
let folder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title: "test",
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
let folderId = await PlacesUtils.promiseItemId(folder.guid);
PlacesUtils.annotations.setItemAnnotation(folderId, ORGANIZER_QUERY_ANNO,
"test", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
// Create the left pane, and store its current status, it will be used
// as reference value.
gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
gReferenceHierarchy = folderIdToHierarchy(gLeftPaneFolderId);
while (gTests.length) {
// Run current test.
await gTests.shift()();
// Regenerate getters.
Object.defineProperty(PlacesUIUtils, "leftPaneFolderId", gLeftPaneFolderIdGetter);
gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
// Check the new left pane folder.
let leftPaneHierarchy = folderIdToHierarchy(gLeftPaneFolderId);
Assert.equal(gReferenceHierarchy, leftPaneHierarchy);
folder = await PlacesUtils.bookmarks.fetch({guid: folder.guid});
Assert.equal(folder.title, "test");
}
});
// Corruption cases.
var gTests = [
function test1() {
print("1. Do nothing, checks test calibration.");
},
async function test2() {
print("2. Delete the left pane folder.");
let guid = await PlacesUtils.promiseItemGuid(gLeftPaneFolderId);
await PlacesUtils.bookmarks.remove(guid);
},
async function test3() {
print("3. Delete a child of the left pane folder.");
let guid = await PlacesUtils.promiseItemGuid(gLeftPaneFolderId);
let bm = await PlacesUtils.bookmarks.fetch({parentGuid: guid, index: 0});
await PlacesUtils.bookmarks.remove(bm.guid);
},
async function test4() {
print("4. Create a duplicated left pane folder.");
let folder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title: "PlacesRoot",
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
let folderId = await PlacesUtils.promiseItemId(folder.guid);
PlacesUtils.annotations.setItemAnnotation(folderId, ORGANIZER_FOLDER_ANNO,
"PlacesRoot", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
},
async function test5() {
print("5. Create a duplicated left pane query.");
let folder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title: "AllBookmarks",
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
let folderId = await PlacesUtils.promiseItemId(folder.guid);
PlacesUtils.annotations.setItemAnnotation(folderId, ORGANIZER_QUERY_ANNO,
"AllBookmarks", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
},
function test6() {
print("6. Remove the left pane folder annotation.");
PlacesUtils.annotations.removeItemAnnotation(gLeftPaneFolderId,
ORGANIZER_FOLDER_ANNO);
},
];
/**
* Convert a folder item id to a JSON representation of it and its contents.
*/
function folderIdToHierarchy(aFolderId) {
let root = PlacesUtils.getFolderContents(aFolderId).root;
let hier = JSON.stringify(hierarchyToObj(root));
root.containerOpen = false;
return hier;
}
function hierarchyToObj(aNode) {
let o = {};
o.title = aNode.title;
o.annos = PlacesUtils.getAnnotationsForItem(aNode.itemId);
if (PlacesUtils.nodeIsURI(aNode)) {
o.uri = aNode.uri;
} else if (PlacesUtils.nodeIsFolder(aNode)) {
o.children = [];
PlacesUtils.asContainer(aNode).containerOpen = true;
for (let i = 0; i < aNode.childCount; ++i) {
o.children.push(hierarchyToObj(aNode.getChild(i)));
}
aNode.containerOpen = false;
}
return o;
}

Просмотреть файл

@ -20,5 +20,4 @@ support-files =
[test_browserGlue_smartBookmarks.js]
[test_browserGlue_urlbar_defaultbehavior_migration.js]
[test_clearHistory_shutdown.js]
[test_leftpane_corruption_handling.js]
[test_PUIU_batchUpdatesForNode.js]

Просмотреть файл

@ -5,13 +5,8 @@ prefs =
support-files =
head.js
privacypane_tests_perwindow.js
site_data_test.html
service_worker_test.html
service_worker_test.js
addons/set_homepage.xpi
addons/set_newtab.xpi
offline/offline.html
offline/manifest.appcache
[browser_applications_selection.js]
skip-if = os == 'linux' # bug 1382057
@ -45,7 +40,6 @@ skip-if = os != "win" || (os == "win" && os_version == "6.1")
# This test tests the windows-specific app selection dialog, so can't run on non-Windows.
# Skip the test on Window 7, see the detail at Bug 1381706.
[browser_checkspelling.js]
[browser_clearSiteData.js]
[browser_connection.js]
[browser_connection_bug388287.js]
[browser_cookies_exceptions.js]
@ -82,10 +76,6 @@ run-if = nightly_build
[browser_searchsuggestions.js]
[browser_security-1.js]
[browser_security-2.js]
[browser_siteData.js]
skip-if = (os == 'linux' && debug) # Bug 1439332
[browser_siteData2.js]
[browser_siteData3.js]
[browser_spotlight.js]
[browser_site_login_exceptions.js]
[browser_permissions_dialog.js]

Просмотреть файл

@ -3,8 +3,6 @@
ChromeUtils.import("resource://gre/modules/Promise.jsm", this);
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager");
const kDefaultWait = 2000;
function is_hidden(aElement) {
@ -144,46 +142,6 @@ function openPreferencesViaOpenPreferencesAPI(aPane, aOptions) {
});
}
function promiseWindowDialogOpen(buttonAction, url) {
return BrowserTestUtils.promiseAlertDialogOpen(buttonAction, url);
}
function promiseAlertDialogOpen(buttonAction) {
return BrowserTestUtils.promiseAlertDialogOpen(buttonAction);
}
function promiseSiteDataManagerSitesUpdated() {
return TestUtils.topicObserved("sitedatamanager:sites-updated", () => true);
}
function openSiteDataSettingsDialog() {
let doc = gBrowser.selectedBrowser.contentDocument;
let settingsBtn = doc.getElementById("siteDataSettings");
let dialogOverlay = content.gSubDialog._preloadDialog._overlay;
let dialogLoadPromise = promiseLoadSubDialog("chrome://browser/content/preferences/siteDataSettings.xul");
let dialogInitPromise = TestUtils.topicObserved("sitedata-settings-init", () => true);
let fullyLoadPromise = Promise.all([dialogLoadPromise, dialogInitPromise]).then(() => {
is(dialogOverlay.style.visibility, "visible", "The Settings dialog should be visible");
});
settingsBtn.doCommand();
return fullyLoadPromise;
}
function assertSitesListed(doc, hosts) {
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let removeAllBtn = frameDoc.getElementById("removeAll");
let sitesList = frameDoc.getElementById("sitesList");
let totalSitesNumber = sitesList.getElementsByTagName("richlistitem").length;
is(totalSitesNumber, hosts.length, "Should list the right sites number");
hosts.forEach(host => {
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
ok(site, `Should list the site of ${host}`);
});
is(removeBtn.disabled, true, "Should disable the removeSelected button");
is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
}
async function evaluateSearchResults(keyword, searchReults) {
searchReults = Array.isArray(searchReults) ? searchReults : [searchReults];
searchReults.push("header-searchResults");
@ -206,111 +164,3 @@ async function evaluateSearchResults(keyword, searchReults) {
}
}
const mockSiteDataManager = {
_SiteDataManager: null,
_originalQMS: null,
_originalRemoveQuotaUsage: null,
getUsage(onUsageResult) {
let result = this.fakeSites.map(site => ({
origin: site.principal.origin,
usage: site.usage,
persisted: site.persisted,
lastAccessed: site.lastAccessed,
}));
onUsageResult({ result, resultCode: Cr.NS_OK });
},
_removeQuotaUsage(site) {
var target = site.principals[0].URI.host;
this.fakeSites = this.fakeSites.filter(fakeSite => {
return fakeSite.principal.URI.host != target;
});
},
register(SiteDataManager, fakeSites) {
this._SiteDataManager = SiteDataManager;
this._originalQMS = this._SiteDataManager._qms;
this._SiteDataManager._qms = this;
this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage;
this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this);
// Add some fake data.
this.fakeSites = fakeSites;
for (let site of fakeSites) {
if (!site.principal) {
site.principal = Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin(site.origin);
}
let uri = site.principal.URI;
try {
site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host);
} catch (e) {
site.baseDomain = uri.host;
}
// Add some cookies if needed.
for (let i = 0; i < (site.cookies || 0); i++) {
Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i,
false, false, false, Date.now() + 1000 * 60 * 60);
}
}
},
async unregister() {
await this._SiteDataManager.removeAll();
this.fakeSites = null;
this._SiteDataManager._qms = this._originalQMS;
this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage;
}
};
function getQuotaUsage(origin) {
return new Promise(resolve => {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
});
}
function promiseCookiesCleared() {
return TestUtils.topicObserved("cookie-changed", (subj, data) => {
return data === "cleared";
});
}
async function loadServiceWorkerTestPage(url) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await BrowserTestUtils.waitForCondition(() => {
return ContentTask.spawn(tab.linkedBrowser, {}, () =>
content.document.body.getAttribute("data-test-service-worker-registered") === "true");
}, `Fail to load service worker test ${url}`);
await BrowserTestUtils.removeTab(tab);
}
function promiseServiceWorkersCleared() {
return BrowserTestUtils.waitForCondition(() => {
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
if (serviceWorkers.length == 0) {
ok(true, "Cleared all service workers");
return true;
}
return false;
}, "Should clear all service workers");
}
function promiseServiceWorkerRegisteredFor(url) {
return BrowserTestUtils.waitForCondition(() => {
try {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(url);
let sw = serviceWorkerManager.getRegistrationByPrincipal(principal, principal.URI.spec);
if (sw) {
ok(true, `Found the service worker registered for ${url}`);
return true;
}
} catch (e) {}
return false;
}, `Should register service worker for ${url}`);
}

Просмотреть файл

@ -0,0 +1,14 @@
[DEFAULT]
support-files =
head.js
site_data_test.html
service_worker_test.html
service_worker_test.js
offline/offline.html
offline/manifest.appcache
[browser_clearSiteData.js]
[browser_siteData.js]
skip-if = (os == 'linux' && debug) # Bug 1439332
[browser_siteData2.js]
[browser_siteData3.js]

Просмотреть файл

@ -5,17 +5,6 @@
ChromeUtils.import("resource:///modules/SitePermissions.jsm");
const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
const TEST_QUOTA_USAGE_HOST = "example.com";
const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/site_data_test.html";
const TEST_OFFLINE_HOST = "example.org";
const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/offline/offline.html";
const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/service_worker_test.html";
async function testClearData(clearSiteData, clearCache) {
let quotaURI = Services.io.newURI(TEST_QUOTA_USAGE_ORIGIN);
SitePermissions.set(quotaURI, "persistent-storage", SitePermissions.ALLOW);
@ -89,7 +78,7 @@ async function testClearData(clearSiteData, clearCache) {
let updatePromise;
let cookiesClearedPromise;
if (clearSiteData) {
acceptPromise = promiseAlertDialogOpen("accept");
acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
updatePromise = promiseSiteDataManagerSitesUpdated();
cookiesClearedPromise = promiseCookiesCleared();
}

Просмотреть файл

@ -3,22 +3,8 @@
"use strict";
const TEST_QUOTA_USAGE_HOST = "example.com";
const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/site_data_test.html";
const TEST_OFFLINE_HOST = "example.org";
const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/offline/offline.html";
const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/service_worker_test.html";
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {});
const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
const { OfflineAppCacheHelper } = ChromeUtils.import("resource:///modules/offlineAppCache.jsm", {});
function getPersistentStoragePermStatus(origin) {
let uri = NetUtil.newURI(origin);
let uri = Services.io.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
return Services.perms.testExactPermissionFromPrincipal(principal, "persistent-storage");
}
@ -26,8 +12,6 @@ function getPersistentStoragePermStatus(origin) {
// Test listing site using quota usage or site using appcache
// This is currently disabled because of bug 1414751.
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Open a test site which would save into appcache
await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_OFFLINE_URL);
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -71,7 +55,6 @@ add_task(async function() {
// Test buttons are disabled and loading message shown while updating sites
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
let updatedPromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatedPromise;
@ -118,7 +101,6 @@ add_task(async function() {
// Test clearing service wroker through the settings panel
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Register a test service worker
await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
@ -126,7 +108,7 @@ add_task(async function() {
await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);
// Open the Site Data Settings panel and remove the site
await openSiteDataSettingsDialog();
let acceptRemovePromise = promiseAlertDialogOpen("accept");
let acceptRemovePromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
ContentTask.spawn(gBrowser.selectedBrowser, { TEST_OFFLINE_HOST }, args => {
let host = args.TEST_OFFLINE_HOST;
@ -186,7 +168,7 @@ add_task(async function() {
// Open the site data manager and remove one site.
await openSiteDataSettingsDialog();
let removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1, creationDate2}, function(args) {
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
@ -221,7 +203,7 @@ add_task(async function() {
// Open the site data manager and remove another site.
await openSiteDataSettingsDialog();
let acceptRemovePromise = promiseAlertDialogOpen("accept");
let acceptRemovePromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1}, function(args) {
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;

Просмотреть файл

@ -1,6 +1,4 @@
"use strict";
const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
/* eslint-disable mozilla/no-cpows-in-tests */
@ -31,7 +29,6 @@ function assertAllSitesNotListed(win) {
// Test selecting and removing all sites one by one
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
@ -83,7 +80,7 @@ add_task(async function() {
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button but cancelling save
let cancelPromise = promiseAlertDialogOpen("cancel");
let cancelPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel");
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
saveBtn = frameDoc.getElementById("save");
@ -98,7 +95,7 @@ add_task(async function() {
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button and accepting save
let acceptPromise = promiseAlertDialogOpen("accept");
let acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
settingsDialogClosePromise = promiseSettingsDialogClose();
updatePromise = promiseSiteDataManagerSitesUpdated();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
@ -129,7 +126,6 @@ add_task(async function() {
// Test selecting and removing partial sites
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
@ -197,7 +193,7 @@ add_task(async function() {
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button but canceling save
removeDialogOpenPromise = promiseWindowDialogOpen("cancel", REMOVE_DIALOG_URL);
removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel", REMOVE_DIALOG_URL);
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
saveBtn = frameDoc.getElementById("save");
@ -212,7 +208,7 @@ add_task(async function() {
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button and accepting save
removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
saveBtn = frameDoc.getElementById("save");
@ -247,7 +243,6 @@ add_task(async function() {
// Test searching and then removing only visible sites
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
@ -288,7 +283,7 @@ add_task(async function() {
// Test only removing all visible sites listed
updatePromise = promiseSiteDataManagerSitesUpdated();
let acceptRemovePromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
let acceptRemovePromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
let settingsDialogClosePromise = promiseSettingsDialogClose();
let removeAllBtn = frameDoc.getElementById("removeAll");
let saveBtn = frameDoc.getElementById("save");
@ -306,7 +301,6 @@ add_task(async function() {
// Test dynamically clearing all site data
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
@ -346,7 +340,7 @@ add_task(async function() {
let win = gBrowser.selectedBrowser.contentWindow;
let frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
updatePromise = promiseSiteDataManagerSitesUpdated();
let acceptRemovePromise = promiseAlertDialogOpen("accept");
let acceptRemovePromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
let settingsDialogClosePromise = promiseSettingsDialogClose();
let removeAllBtn = frameDoc.getElementById("removeAll");
let saveBtn = frameDoc.getElementById("save");

Просмотреть файл

@ -1,10 +1,7 @@
"use strict";
const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
// Test not displaying sites which store 0 byte and don't have persistent storage.
add_task(async function() {
await SpecialPowers.pushPrefEnv({ set: [["browser.storageManager.enabled", true]] });
mockSiteDataManager.register(SiteDataManager, [
{
usage: 0,
@ -48,7 +45,6 @@ add_task(async function() {
// Test grouping and listing sites across scheme, port and origin attributes by host
add_task(async function() {
await SpecialPowers.pushPrefEnv({ set: [["browser.storageManager.enabled", true]] });
const quotaUsage = 1024;
mockSiteDataManager.register(SiteDataManager, [
{
@ -107,7 +103,6 @@ add_task(async function() {
// Test sorting
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,

Просмотреть файл

@ -0,0 +1,237 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_QUOTA_USAGE_HOST = "example.com";
const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
const TEST_QUOTA_USAGE_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", TEST_QUOTA_USAGE_ORIGIN) + "/site_data_test.html";
const TEST_OFFLINE_HOST = "example.org";
const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
const TEST_OFFLINE_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", TEST_OFFLINE_ORIGIN) + "/offline/offline.html";
const TEST_SERVICE_WORKER_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", TEST_OFFLINE_ORIGIN) + "/service_worker_test.html";
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
const { OfflineAppCacheHelper } = ChromeUtils.import("resource:///modules/offlineAppCache.jsm", {});
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager");
function promiseSiteDataManagerSitesUpdated() {
return TestUtils.topicObserved("sitedatamanager:sites-updated", () => true);
}
function is_hidden(aElement) {
var style = aElement.ownerGlobal.getComputedStyle(aElement);
if (style.display == "none")
return true;
if (style.visibility != "visible")
return true;
// Hiding a parent element will hide all its children
if (aElement.parentNode != aElement.ownerDocument)
return is_hidden(aElement.parentNode);
return false;
}
function is_element_visible(aElement, aMsg) {
isnot(aElement, null, "Element should not be null, when checking visibility");
ok(!is_hidden(aElement), aMsg);
}
function is_element_hidden(aElement, aMsg) {
isnot(aElement, null, "Element should not be null, when checking visibility");
ok(is_hidden(aElement), aMsg);
}
function promiseLoadSubDialog(aURL) {
return new Promise((resolve, reject) => {
content.gSubDialog._dialogStack.addEventListener("dialogopen", function dialogopen(aEvent) {
if (aEvent.detail.dialog._frame.contentWindow.location == "about:blank")
return;
content.gSubDialog._dialogStack.removeEventListener("dialogopen", dialogopen);
is(aEvent.detail.dialog._frame.contentWindow.location.toString(), aURL,
"Check the proper URL is loaded");
// Check visibility
is_element_visible(aEvent.detail.dialog._overlay, "Overlay is visible");
// Check that stylesheets were injected
let expectedStyleSheetURLs = aEvent.detail.dialog._injectedStyleSheets.slice(0);
for (let styleSheet of aEvent.detail.dialog._frame.contentDocument.styleSheets) {
let i = expectedStyleSheetURLs.indexOf(styleSheet.href);
if (i >= 0) {
info("found " + styleSheet.href);
expectedStyleSheetURLs.splice(i, 1);
}
}
is(expectedStyleSheetURLs.length, 0, "All expectedStyleSheetURLs should have been found");
// Wait for the next event tick to make sure the remaining part of the
// testcase runs after the dialog gets ready for input.
executeSoon(() => resolve(aEvent.detail.dialog._frame.contentWindow));
});
});
}
function openPreferencesViaOpenPreferencesAPI(aPane, aOptions) {
return new Promise(resolve => {
let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded", () => true);
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
openPreferences(aPane);
let newTabBrowser = gBrowser.selectedBrowser;
newTabBrowser.addEventListener("Initialized", function() {
newTabBrowser.contentWindow.addEventListener("load", async function() {
let win = gBrowser.contentWindow;
let selectedPane = win.history.state;
await finalPrefPaneLoaded;
if (!aOptions || !aOptions.leaveOpen)
gBrowser.removeCurrentTab();
resolve({ selectedPane });
}, { once: true });
}, { capture: true, once: true });
});
}
function openSiteDataSettingsDialog() {
let doc = gBrowser.selectedBrowser.contentDocument;
let settingsBtn = doc.getElementById("siteDataSettings");
let dialogOverlay = content.gSubDialog._preloadDialog._overlay;
let dialogLoadPromise = promiseLoadSubDialog("chrome://browser/content/preferences/siteDataSettings.xul");
let dialogInitPromise = TestUtils.topicObserved("sitedata-settings-init", () => true);
let fullyLoadPromise = Promise.all([dialogLoadPromise, dialogInitPromise]).then(() => {
is(dialogOverlay.style.visibility, "visible", "The Settings dialog should be visible");
});
settingsBtn.doCommand();
return fullyLoadPromise;
}
function assertSitesListed(doc, hosts) {
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let removeAllBtn = frameDoc.getElementById("removeAll");
let sitesList = frameDoc.getElementById("sitesList");
let totalSitesNumber = sitesList.getElementsByTagName("richlistitem").length;
is(totalSitesNumber, hosts.length, "Should list the right sites number");
hosts.forEach(host => {
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
ok(site, `Should list the site of ${host}`);
});
is(removeBtn.disabled, true, "Should disable the removeSelected button");
is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
}
const mockSiteDataManager = {
_SiteDataManager: null,
_originalQMS: null,
_originalRemoveQuotaUsage: null,
getUsage(onUsageResult) {
let result = this.fakeSites.map(site => ({
origin: site.principal.origin,
usage: site.usage,
persisted: site.persisted,
lastAccessed: site.lastAccessed,
}));
onUsageResult({ result, resultCode: Cr.NS_OK });
},
_removeQuotaUsage(site) {
var target = site.principals[0].URI.host;
this.fakeSites = this.fakeSites.filter(fakeSite => {
return fakeSite.principal.URI.host != target;
});
},
register(siteDataManager, fakeSites) {
this._SiteDataManager = siteDataManager;
this._originalQMS = this._SiteDataManager._qms;
this._SiteDataManager._qms = this;
this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage;
this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this);
// Add some fake data.
this.fakeSites = fakeSites;
for (let site of fakeSites) {
if (!site.principal) {
site.principal = Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin(site.origin);
}
let uri = site.principal.URI;
try {
site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host);
} catch (e) {
site.baseDomain = uri.host;
}
// Add some cookies if needed.
for (let i = 0; i < (site.cookies || 0); i++) {
Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i,
false, false, false, Date.now() + 1000 * 60 * 60);
}
}
},
async unregister() {
await this._SiteDataManager.removeAll();
this.fakeSites = null;
this._SiteDataManager._qms = this._originalQMS;
this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage;
}
};
function getQuotaUsage(origin) {
return new Promise(resolve => {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
});
}
function promiseCookiesCleared() {
return TestUtils.topicObserved("cookie-changed", (subj, data) => {
return data === "cleared";
});
}
async function loadServiceWorkerTestPage(url) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await BrowserTestUtils.waitForCondition(() => {
return ContentTask.spawn(tab.linkedBrowser, {}, () =>
content.document.body.getAttribute("data-test-service-worker-registered") === "true");
}, `Fail to load service worker test ${url}`);
await BrowserTestUtils.removeTab(tab);
}
function promiseServiceWorkersCleared() {
return BrowserTestUtils.waitForCondition(() => {
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
if (serviceWorkers.length == 0) {
ok(true, "Cleared all service workers");
return true;
}
return false;
}, "Should clear all service workers");
}
function promiseServiceWorkerRegisteredFor(url) {
return BrowserTestUtils.waitForCondition(() => {
try {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(url);
let sw = serviceWorkerManager.getRegistrationByPrincipal(principal, principal.URI.spec);
if (sw) {
ok(true, `Found the service worker registered for ${url}`);
return true;
}
} catch (e) {}
return false;
}, `Should register service worker for ${url}`);
}

Просмотреть файл

@ -9,7 +9,8 @@ DIRS += [
]
BROWSER_CHROME_MANIFESTS += [
'in-content/tests/browser.ini'
'in-content/tests/browser.ini',
'in-content/tests/siteData/browser.ini'
]
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):

Просмотреть файл

@ -219,7 +219,7 @@
In addition, browser.js fills two lists of autodetected search engines
(browser.engines and browser.hiddenEngines) as properties of
mCurrentBrowser. Those lists contain unnamed JS objects of the form
selectedBrowser. Those lists contain unnamed JS objects of the form
{ uri:, title:, icon: }, and that's what the searchbar uses to determine
whether to show any "Add <EngineName>" menu items in the drop-down.

Просмотреть файл

@ -62,11 +62,6 @@ detailsPane.itemsCountLabel=One item;#1 items
mostVisitedTitle=Most Visited
recentTagsTitle=Recent Tags
OrganizerQueryHistory=History
OrganizerQueryDownloads=Downloads
OrganizerQueryAllBookmarks=All Bookmarks
OrganizerQueryTags=Tags
# LOCALIZATION NOTE (tagResultLabel, bookmarkResultLabel, switchtabResultLabel,
# keywordResultLabel, searchengineResultLabel)
# Noun used to describe the location bar autocomplete result type

Просмотреть файл

@ -58,16 +58,16 @@ treechildren::-moz-tree-image(query) {
list-style-image: url("chrome://browser/skin/places/folder-smart.svg");
}
treechildren::-moz-tree-image(query, OrganizerQuery_AllBookmarks) {
treechildren::-moz-tree-image(query, OrganizerQuery_allbms_____v) {
list-style-image: url("chrome://browser/skin/places/allBookmarks.png");
}
treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
treechildren::-moz-tree-image(query, OrganizerQuery_downloads__v) {
list-style-image: url("chrome://browser/skin/places/downloads.png");
}
treechildren::-moz-tree-image(title, query, tagContainer),
treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
treechildren::-moz-tree-image(query, OrganizerQuery_tags_______v) {
list-style-image: url("chrome://browser/skin/places/tag.png");
}
@ -80,7 +80,7 @@ treechildren::-moz-tree-image(title, query, hostContainer) {
list-style-image: url("chrome://browser/skin/places/folder.svg");
}
treechildren::-moz-tree-image(query, OrganizerQuery_History) {
treechildren::-moz-tree-image(query, OrganizerQuery_history____v) {
list-style-image: url("chrome://browser/skin/places/history.svg");
}

Просмотреть файл

@ -236,7 +236,7 @@ function openToolbox(form, chrome = false, tool = "webconsole", isTabActor) {
toolbox.once("destroyed", function () {
gClient.close();
});
}, console.error.bind(console));
}, console.error);
window.close();
}, console.error.bind(console));
}, console.error);
}

Просмотреть файл

@ -565,7 +565,7 @@ Toolbox.prototype = {
this.emit("ready");
this._isOpenDeferred.resolve();
}.bind(this))().catch(console.error.bind(console));
}.bind(this))().catch(console.error);
},
/**

Просмотреть файл

@ -12,9 +12,9 @@ const Services = require("Services");
loader.lazyRequireGetter(this, "NetworkHelper",
"devtools/shared/webconsole/network-helper");
loader.lazyGetter(this, "debug", function() {
loader.lazyGetter(this, "debugJsModules", function() {
let {AppConstants} = require("resource://gre/modules/AppConstants.jsm");
return !!(AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES);
return !!(AppConstants.DEBUG_JS_MODULES);
});
const childProcessMessageManager =
@ -168,7 +168,7 @@ function exportData(win, request) {
defineAs: "JSONView"
});
data.debug = debug;
data.debugJsModules = debugJsModules;
data.json = new win.Text();

Просмотреть файл

@ -30,19 +30,19 @@ require.config({
"devtools/client/shared": "resource://devtools-client-shared",
"devtools/shared": "resource://devtools/shared",
"devtools/client/shared/vendor/react":
JSONView.debug
JSONView.debugJsModules
? "resource://devtools-client-shared/vendor/react-dev"
: "resource://devtools-client-shared/vendor/react",
"devtools/client/shared/vendor/react-dom":
JSONView.debug
JSONView.debugJsModules
? "resource://devtools-client-shared/vendor/react-dom-dev"
: "resource://devtools-client-shared/vendor/react-dom",
"devtools/client/shared/vendor/react-prop-types":
JSONView.debug
JSONView.debugJsModules
? "resource://devtools-client-shared/vendor/react-prop-types-dev"
: "resource://devtools-client-shared/vendor/react-prop-types",
"devtools/client/shared/vendor/react-dom-test-utils":
JSONView.debug
JSONView.debugJsModules
? "resource://devtools-client-shared/vendor/react-dom-test-utils-dev"
: "resource://devtools-client-shared/vendor/react-dom-test-utils",
}

Просмотреть файл

@ -100,7 +100,7 @@ function BrowserLoaderBuilder({ baseURI, window, useOnlyShared, commonLibRequire
const loaderOptions = devtools.require("@loader/options");
const dynamicPaths = {};
if (AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES) {
if (AppConstants.DEBUG_JS_MODULES) {
dynamicPaths["devtools/client/shared/vendor/react"] =
"resource://devtools/client/shared/vendor/react-dev";
dynamicPaths["devtools/client/shared/vendor/react-dom"] =

Просмотреть файл

@ -135,7 +135,7 @@
// Final notification for further theme-switching related logic.
gDevTools.emit("theme-switched", window, newTheme, oldTheme);
notifyWindow();
}, console.error.bind(console));
}, console.error);
}
function handlePrefChange() {

6
devtools/client/shared/vendor/moz.build поставляемый
Просмотреть файл

@ -28,10 +28,8 @@ DevToolsModules(
'WasmParser.js',
)
# react dev versions are used if either debug mode is enabled,
# or enable-debug-js-modules is set in .mozconfig so include it for
# both
if CONFIG['DEBUG_JS_MODULES'] or CONFIG['MOZ_DEBUG']:
# react dev versions are used if enable-debug-js-modules is set in .mozconfig.
if CONFIG['DEBUG_JS_MODULES']:
DevToolsModules(
'react-dev.js',
'react-dom-dev.js',

Просмотреть файл

@ -19,11 +19,6 @@ const TEMPLATES_URL = "devtools.webide.templatesURL";
var gTemplateList = null;
// See bug 989619
console.log = console.log.bind(console);
console.warn = console.warn.bind(console);
console.error = console.error.bind(console);
window.addEventListener("load", function () {
let projectNameNode = document.querySelector("#project-name");
projectNameNode.addEventListener("input", canValidate, true);

Просмотреть файл

@ -41,11 +41,6 @@ const MIN_ZOOM = 0.6;
getJSON("devtools.webide.templatesURL");
getJSON("devtools.devices.url");
// See bug 989619
console.log = console.log.bind(console);
console.warn = console.warn.bind(console);
console.error = console.error.bind(console);
window.addEventListener("load", function () {
UI.init();
}, {once: true});

Просмотреть файл

@ -239,7 +239,7 @@ var AppManager = exports.AppManager = {
}
return this.getTarget().then(target => {
target.activeTab.reload();
}, console.error.bind(console));
}, console.error);
},
getTarget: function () {

Просмотреть файл

@ -432,7 +432,6 @@ function reallyAssert(condition, message) {
*
* Assertions are enabled when any of the following are true:
* - This is a DEBUG_JS_MODULES build
* - This is a DEBUG build
* - flags.testing is set to true
*
* If assertions are enabled, then `condition` is checked and if false-y, the
@ -441,7 +440,7 @@ function reallyAssert(condition, message) {
* If assertions are not enabled, then this function is a no-op.
*/
Object.defineProperty(exports, "assert", {
get: () => (AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES || flags.testing)
get: () => (AppConstants.DEBUG_JS_MODULES || flags.testing)
? reallyAssert
: exports.noop,
});

Просмотреть файл

@ -8826,8 +8826,7 @@ bool
nsContentUtils::IsUpgradableDisplayType(nsContentPolicyType aType)
{
MOZ_ASSERT(NS_IsMainThread());
return sIsUpgradableDisplayContentPrefEnabled &&
(aType == nsIContentPolicy::TYPE_IMAGE ||
return (aType == nsIContentPolicy::TYPE_IMAGE ||
aType == nsIContentPolicy::TYPE_MEDIA);
}

Просмотреть файл

@ -2365,7 +2365,7 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
timedChannel = nullptr;
}
if (timing) {
mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
mPerformance = Performance::CreateForMainThread(this, mDoc->NodePrincipal(), timing, timedChannel);
}
}

Просмотреть файл

@ -1854,6 +1854,7 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
if (currentInner->mPerformance) {
newInnerWindow->mPerformance =
Performance::CreateForMainThread(newInnerWindow->AsInner(),
aDocument->NodePrincipal(),
currentInner->mPerformance->GetDOMTiming(),
currentInner->mPerformance->GetChannel());
}
@ -7872,3 +7873,4 @@ nsAutoPopupStatePusherInternal::~nsAutoPopupStatePusherInternal()
{
nsContentUtils::PopPopupControlState(mOldState);
}

Просмотреть файл

@ -881,7 +881,7 @@ BrowserElementChild.prototype = {
// one we return the form's method and action uri.
let parent = elem.parentNode;
while (parent) {
if (parent instanceof Ci.nsIDOMHTMLFormElement &&
if (ChromeUtils.getClassName(parent) === "HTMLFormElement" &&
parent.hasAttribute("action")) {
let actionHref = docShell.QueryInterface(Ci.nsIWebNavigation)
.currentURI

25
dom/events/Event.cpp Normal file → Executable file
Просмотреть файл

@ -1095,10 +1095,14 @@ Event::DefaultPrevented(CallerType aCallerType) const
}
double
Event::TimeStampImpl() const
Event::TimeStamp()
{
if (!sReturnHighResTimeStamp) {
return static_cast<double>(mEvent->mTime);
// In the situation where you have set a very old, not-very-supported
// non-default preference, we will always reduce the precision,
// regardless of system principal or not.
double ret = static_cast<double>(mEvent->mTime);
return nsRFPService::ReduceTimePrecisionAsMSecs(ret);
}
if (mEvent->mTimeStamp.IsNull()) {
@ -1120,19 +1124,22 @@ Event::TimeStampImpl() const
return 0.0;
}
return perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp);
double ret = perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp);
MOZ_ASSERT(mOwner->PrincipalOrNull());
if (nsContentUtils::IsSystemPrincipal(mOwner->PrincipalOrNull()))
return ret;
return nsRFPService::ReduceTimePrecisionAsMSecs(ret);
}
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
return workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp);
}
double ret = workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp);
if (workerPrivate->UsesSystemPrincipal())
return ret;
double
Event::TimeStamp() const
{
return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampImpl());
return nsRFPService::ReduceTimePrecisionAsMSecs(ret);
}
NS_IMETHODIMP

3
dom/events/Event.h Normal file → Executable file
Просмотреть файл

@ -65,7 +65,6 @@ private:
void ConstructorInit(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetEvent* aEvent);
double TimeStampImpl() const;
public:
static Event* FromSupports(nsISupports* aSupports)
@ -255,7 +254,7 @@ public:
return mEvent->mFlags.mIsSynthesizedForTests;
}
double TimeStamp() const;
double TimeStamp();
EventTarget* GetOriginalTarget() const;
EventTarget* GetExplicitOriginalTarget() const;

Просмотреть файл

@ -151,7 +151,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLFormElement,
nsGenericHTMLElement,
nsIDOMHTMLFormElement,
nsIForm,
nsIWebProgressListener,
nsIRadioGroupContainer)
@ -315,7 +314,7 @@ static void
CollectOrphans(nsINode* aRemovalRoot,
const nsTArray<nsGenericHTMLFormElement*>& aArray
#ifdef DEBUG
, nsIDOMHTMLFormElement* aThisForm
, HTMLFormElement* aThisForm
#endif
)
{
@ -349,8 +348,7 @@ CollectOrphans(nsINode* aRemovalRoot,
#ifdef DEBUG
if (!removed) {
nsCOMPtr<nsIDOMHTMLFormElement> form;
node->GetForm(getter_AddRefs(form));
HTMLFormElement* form = node->GetForm();
NS_ASSERTION(form == aThisForm, "How did that happen?");
}
#endif /* DEBUG */
@ -361,7 +359,7 @@ static void
CollectOrphans(nsINode* aRemovalRoot,
const nsTArray<HTMLImageElement*>& aArray
#ifdef DEBUG
, nsIDOMHTMLFormElement* aThisForm
, HTMLFormElement* aThisForm
#endif
)
{
@ -390,7 +388,7 @@ CollectOrphans(nsINode* aRemovalRoot,
#ifdef DEBUG
if (!removed) {
nsCOMPtr<nsIDOMHTMLFormElement> form = node->GetForm();
HTMLFormElement* form = node->GetForm();
NS_ASSERTION(form == aThisForm, "How did that happen?");
}
#endif /* DEBUG */
@ -982,7 +980,7 @@ HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
nsCOMPtr<nsIFormSubmitObserver> formSubmitObserver(
do_QueryInterface(inst));
if (formSubmitObserver) {
rv = formSubmitObserver->Notify(this,
rv = formSubmitObserver->Notify(static_cast<nsIContent*>(this),
window ? window->GetCurrentInnerWindow() : nullptr,
aActionURL,
aCancelSubmit);
@ -1981,7 +1979,7 @@ HTMLFormElement::CheckValidFormSubmission()
observer = do_QueryInterface(inst);
if (observer) {
observer->NotifyInvalidSubmit(this,
observer->NotifyInvalidSubmit(static_cast<nsIContent*>(this),
static_cast<nsIArray*>(invalidElements));
}
}

Просмотреть файл

@ -15,7 +15,6 @@
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIWebProgressListener.h"
#include "nsIRadioGroupContainer.h"
#include "nsIWeakReferenceUtils.h"
@ -36,7 +35,6 @@ class HTMLFormControlsCollection;
class HTMLImageElement;
class HTMLFormElement final : public nsGenericHTMLElement,
public nsIDOMHTMLFormElement,
public nsIWebProgressListener,
public nsIForm,
public nsIRadioGroupContainer
@ -55,9 +53,6 @@ public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMHTMLFormElement
NS_DECL_NSIDOMHTMLFORMELEMENT
// nsIWebProgressListener
NS_DECL_NSIWEBPROGRESSLISTENER

Просмотреть файл

@ -859,7 +859,7 @@ HTMLImageElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
#ifdef DEBUG
nsIDOMHTMLFormElement*
HTMLFormElement*
HTMLImageElement::GetForm() const
{
return mForm;
@ -867,13 +867,13 @@ HTMLImageElement::GetForm() const
#endif
void
HTMLImageElement::SetForm(nsIDOMHTMLFormElement* aForm)
HTMLImageElement::SetForm(HTMLFormElement* aForm)
{
NS_PRECONDITION(aForm, "Don't pass null here");
NS_ASSERTION(!mForm,
"We don't support switching from one non-null form to another.");
mForm = static_cast<HTMLFormElement*>(aForm);
mForm = aForm;
}
void

Просмотреть файл

@ -249,9 +249,9 @@ public:
}
#ifdef DEBUG
nsIDOMHTMLFormElement* GetForm() const;
HTMLFormElement* GetForm() const;
#endif
void SetForm(nsIDOMHTMLFormElement* aForm);
void SetForm(HTMLFormElement* aForm);
void ClearForm(bool aRemoveFromForm);
virtual void DestroyContent() override;

Просмотреть файл

@ -66,7 +66,6 @@
#include "nsITextControlFrame.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "nsFocusManager.h"
#include "nsAttrValueOrString.h"
@ -1713,13 +1712,13 @@ nsGenericHTMLFormElement::SaveSubtreeState()
}
void
nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm)
{
NS_PRECONDITION(aForm, "Don't pass null here");
NS_ASSERTION(!mForm,
"We don't support switching from one non-null form to another.");
SetForm(static_cast<HTMLFormElement*>(aForm), false);
SetForm(aForm, false);
}
void nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm, bool aBindToTree)
@ -1776,14 +1775,6 @@ nsGenericHTMLFormElement::GetFieldSet()
return mFieldSet;
}
nsresult
nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
NS_ENSURE_ARG_POINTER(aForm);
NS_IF_ADDREF(*aForm = mForm);
return NS_OK;
}
nsIContent::IMEState
nsGenericHTMLFormElement::GetDesiredIMEState()
{

Просмотреть файл

@ -1011,11 +1011,9 @@ public:
{
return mForm;
}
virtual void SetForm(nsIDOMHTMLFormElement* aForm) override;
virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) override;
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override;
nsresult GetForm(nsIDOMHTMLFormElement** aForm);
NS_IMETHOD SaveState() override
{
return NS_OK;

Просмотреть файл

@ -9,7 +9,6 @@
#include "mozilla/EventForwards.h"
#include "nsISupports.h"
class nsIDOMHTMLFormElement;
class nsPresState;
namespace mozilla {
@ -17,6 +16,7 @@ namespace dom {
class Element;
class HTMLFieldSetElement;
class HTMLFormSubmission;
class HTMLFormElement;
} // namespace dom
} // namespace mozilla
@ -120,7 +120,7 @@ public:
* so that it can be properly sorted with the other controls in the
* form.
*/
virtual void SetForm(nsIDOMHTMLFormElement* aForm) = 0;
virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) = 0;
/**
* Tell the control to forget about its form.

Просмотреть файл

@ -6,7 +6,6 @@
#include "nsISupports.idl"
interface nsIDOMHTMLFormElement;
interface mozIDOMWindow;
interface nsIURI;
interface nsIArray;
@ -14,9 +13,11 @@ interface nsIArray;
[scriptable, uuid(867cb7e7-835d-408b-9788-d2834d284e03)]
interface nsIFormSubmitObserver: nsISupports
{
void notify(in nsIDOMHTMLFormElement formNode, in mozIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
// formNode must be a HTMLFormElement (bug 1444991 can clean it up)
void notify(in nsISupports formNode, in mozIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
void notifyInvalidSubmit(in nsIDOMHTMLFormElement formNode,
// formNode must be a HTMLFormElement (bug 1444991 can clean it up)
void notifyInvalidSubmit(in nsISupports formNode,
in nsIArray invalidElements);
};

Просмотреть файл

@ -48,7 +48,6 @@ interface nsIDOMEventTarget;
interface nsIDOMEventListener;
// HTML
interface nsIDOMHTMLFormElement;
interface nsIDOMHTMLHeadElement;
// Range

Просмотреть файл

@ -8,7 +8,6 @@ with Files("**"):
BUG_COMPONENT = ("Core", "DOM")
XPIDL_SOURCES += [
'nsIDOMHTMLFormElement.idl',
'nsIDOMHTMLInputElement.idl',
'nsIDOMMozBrowserFrame.idl',
'nsIMozBrowserFrame.idl',

Просмотреть файл

@ -1,22 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* The nsIDOMHTMLFormElement interface is the interface to a [X]HTML
* form element.
*
* This interface is trying to follow the DOM Level 2 HTML specification:
* http://www.w3.org/TR/DOM-Level-2-HTML/
*
* with changes from the work-in-progress WHATWG HTML specification:
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[uuid(ad9b2ad0-9d29-43f6-b1a2-a1fd24627e6b)]
interface nsIDOMHTMLFormElement : nsISupports
{
};

Просмотреть файл

@ -7,7 +7,6 @@
interface nsIControllers;
interface nsIDOMFileList;
interface nsIDOMHTMLFormElement;
/**
* The nsIDOMHTMLInputElement interface is the interface to a [X]HTML

Просмотреть файл

@ -49,6 +49,7 @@ NS_IMPL_RELEASE_INHERITED(Performance, DOMEventTargetHelper)
/* static */ already_AddRefed<Performance>
Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel)
{
@ -56,6 +57,7 @@ Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
RefPtr<Performance> performance =
new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
performance->mSystemPrincipal = nsContentUtils::IsSystemPrincipal(aPrincipal);
return performance.forget();
}
@ -66,6 +68,7 @@ Performance::CreateForWorker(WorkerPrivate* aWorkerPrivate)
aWorkerPrivate->AssertIsOnWorkerThread();
RefPtr<Performance> performance = new PerformanceWorker(aWorkerPrivate);
performance->mSystemPrincipal = aWorkerPrivate->UsesSystemPrincipal();
return performance.forget();
}
@ -88,10 +91,23 @@ Performance::~Performance()
{}
DOMHighResTimeStamp
Performance::Now() const
Performance::Now()
{
DOMHighResTimeStamp rawTime = NowUnclamped();
if (mSystemPrincipal) {
return rawTime;
}
const double maxResolutionMs = 0.020;
DOMHighResTimeStamp minimallyClamped = floor(rawTime / maxResolutionMs) * maxResolutionMs;
return nsRFPService::ReduceTimePrecisionAsMSecs(minimallyClamped);
}
DOMHighResTimeStamp
Performance::NowUnclamped() const
{
TimeDuration duration = TimeStamp::Now() - CreationTimeStamp();
return RoundTime(duration.ToMilliseconds());
return duration.ToMilliseconds();
}
DOMHighResTimeStamp
@ -102,8 +118,12 @@ Performance::TimeOrigin()
}
MOZ_ASSERT(mPerformanceService);
return nsRFPService::ReduceTimePrecisionAsMSecs(
mPerformanceService->TimeOrigin(CreationTimeStamp()));
DOMHighResTimeStamp rawTimeOrigin = mPerformanceService->TimeOrigin(CreationTimeStamp());
if (mSystemPrincipal) {
return rawTimeOrigin;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawTimeOrigin);
}
JSObject*
@ -206,17 +226,6 @@ Performance::ClearResourceTimings()
mResourceEntries.Clear();
}
DOMHighResTimeStamp
Performance::RoundTime(double aTime) const
{
// Round down to the nearest 20us, because if the timer is too accurate people
// can do nasty timing attacks with it.
const double maxResolutionMs = 0.020;
return nsRFPService::ReduceTimePrecisionAsMSecs(
floor(aTime / maxResolutionMs) * maxResolutionMs);
}
void
Performance::Mark(const nsAString& aName, ErrorResult& aRv)
{

Просмотреть файл

@ -41,6 +41,7 @@ public:
static already_AddRefed<Performance>
CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsIPrincipal* aPrincipal,
nsDOMNavigationTiming* aDOMTiming,
nsITimedChannel* aChannel);
@ -63,7 +64,9 @@ public:
void ClearResourceTimings();
DOMHighResTimeStamp Now() const;
DOMHighResTimeStamp Now();
DOMHighResTimeStamp NowUnclamped() const;
DOMHighResTimeStamp TimeOrigin();
@ -100,6 +103,11 @@ public:
virtual TimeStamp CreationTimeStamp() const = 0;
uint64_t IsSystemPrincipal()
{
return mSystemPrincipal;
}
void MemoryPressure();
size_t SizeOfUserEntries(mozilla::MallocSizeOf aMallocSizeOf) const;
@ -143,8 +151,6 @@ protected:
void RunNotificationObserversTask();
void QueueEntry(PerformanceEntry* aEntry);
DOMHighResTimeStamp RoundTime(double aTime) const;
nsTObserverArray<PerformanceObserver*> mObservers;
protected:
@ -159,6 +165,8 @@ protected:
bool mPendingNotificationObserversTask;
RefPtr<PerformanceService> mPerformanceService;
bool mSystemPrincipal;
};
} // namespace dom

0
dom/performance/PerformanceMainThread.cpp Normal file → Executable file
Просмотреть файл

6
dom/performance/PerformanceNavigationTiming.h Normal file → Executable file
Просмотреть файл

@ -39,7 +39,11 @@ public:
DOMHighResTimeStamp Duration() const override
{
return nsRFPService::ReduceTimePrecisionAsMSecs(LoadEventEnd() - StartTime());
DOMHighResTimeStamp rawDuration = LoadEventEnd() - StartTime();
if (mPerformance->IsSystemPrincipal()) {
return rawDuration;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawDuration);
}
DOMHighResTimeStamp StartTime() const override

0
dom/performance/PerformanceStorageWorker.cpp Normal file → Executable file
Просмотреть файл

88
dom/performance/PerformanceTiming.cpp Normal file → Executable file
Просмотреть файл

@ -81,7 +81,9 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
mTimingData.reset(new PerformanceTimingData(aChannel, aHttpChannel,
aZeroTime));
aPerformance->IsSystemPrincipal()
? aZeroTime
: nsRFPService::ReduceTimePrecisionAsMSecs(aZeroTime)));
// Non-null aHttpChannel implies that this PerformanceTiming object is being
// used for subresources, which is irrelevant to this probe.
@ -112,8 +114,8 @@ PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
, mInitialized(false)
{
mInitialized = !!aChannel;
mZeroTime = aZeroTime;
mZeroTime = nsRFPService::ReduceTimePrecisionAsMSecs(aZeroTime);
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
mZeroTime = 0;
@ -252,6 +254,9 @@ PerformanceTimingData::FetchStartHighRes(Performance* aPerformance)
}
}
}
if (aPerformance->IsSystemPrincipal()) {
return mFetchStart;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(mFetchStart);
}
@ -327,8 +332,11 @@ PerformanceTimingData::AsyncOpenHighRes(Performance* aPerformance)
nsContentUtils::ShouldResistFingerprinting() || mAsyncOpen.IsNull()) {
return mZeroTime;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mAsyncOpen));
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mAsyncOpen);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMHighResTimeStamp
@ -340,8 +348,11 @@ PerformanceTimingData::WorkerStartHighRes(Performance* aPerformance)
nsContentUtils::ShouldResistFingerprinting() || mWorkerStart.IsNull()) {
return mZeroTime;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mWorkerStart));
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mWorkerStart);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
/**
@ -447,10 +458,14 @@ PerformanceTimingData::DomainLookupEndHighRes(Performance* aPerformance)
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
return mDomainLookupEnd.IsNull()
? DomainLookupStartHighRes(aPerformance)
: nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mDomainLookupEnd));
if (mDomainLookupEnd.IsNull()) {
return DomainLookupStartHighRes(aPerformance);
}
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mDomainLookupEnd);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMTimeMilliSec
@ -468,10 +483,14 @@ PerformanceTimingData::ConnectStartHighRes(Performance* aPerformance)
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
return mConnectStart.IsNull()
? DomainLookupEndHighRes(aPerformance)
: nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mConnectStart));
if (mConnectStart.IsNull()) {
return DomainLookupEndHighRes(aPerformance);
}
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mConnectStart);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMTimeMilliSec
@ -489,13 +508,18 @@ PerformanceTimingData::SecureConnectionStartHighRes(Performance* aPerformance)
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
return !mSecureConnection
? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
if (!mSecureConnection) {
return 0; // We use 0 here, because mZeroTime is sometimes set to the navigation
// start time.
: (mSecureConnectionStart.IsNull()
? mZeroTime
: nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart)));
}
if (mSecureConnectionStart.IsNull()) {
return mZeroTime;
}
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMTimeMilliSec
@ -514,10 +538,14 @@ PerformanceTimingData::ConnectEndHighRes(Performance* aPerformance)
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
return mConnectEnd.IsNull()
? ConnectStartHighRes(aPerformance)
: nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mConnectEnd));
if (mConnectEnd.IsNull()) {
return ConnectStartHighRes(aPerformance);
}
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mConnectEnd);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMTimeMilliSec
@ -593,10 +621,14 @@ PerformanceTimingData::ResponseEndHighRes(Performance* aPerformance)
mResponseEnd = mWorkerResponseEnd;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
return mResponseEnd.IsNull()
? ResponseStartHighRes(aPerformance)
: nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, mResponseEnd));
if (mResponseEnd.IsNull()) {
return ResponseStartHighRes(aPerformance);
}
DOMHighResTimeStamp rawValue = TimeStampToDOMHighRes(aPerformance, mResponseEnd);
if (aPerformance->IsSystemPrincipal()) {
return rawValue;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawValue);
}
DOMTimeMilliSec

47
dom/performance/PerformanceTiming.h Normal file → Executable file
Просмотреть файл

@ -82,10 +82,16 @@ public:
{
MOZ_ASSERT(aPerformance);
return (!aStamp.IsNull())
? nsRFPService::ReduceTimePrecisionAsMSecs(
TimeStampToDOMHighRes(aPerformance, aStamp))
: FetchStartHighRes(aPerformance);
if(aStamp.IsNull()) {
return FetchStartHighRes(aPerformance);
}
DOMHighResTimeStamp rawTimestamp = TimeStampToDOMHighRes(aPerformance, aStamp);
if (aPerformance->IsSystemPrincipal()) {
return rawTimestamp;
}
return nsRFPService::ReduceTimePrecisionAsMSecs(rawTimestamp);
}
/**
@ -268,6 +274,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetNavigationStart();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetNavigationStart());
}
@ -278,6 +287,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetUnloadEventStart();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetUnloadEventStart());
}
@ -288,6 +300,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetUnloadEventEnd();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetUnloadEventEnd());
}
@ -311,6 +326,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetDomLoading();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetDomLoading());
}
@ -321,6 +339,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetDomInteractive();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetDomInteractive());
}
@ -331,6 +352,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetDomContentLoadedEventStart();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetDomContentLoadedEventStart());
}
@ -341,6 +365,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetDomContentLoadedEventEnd();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetDomContentLoadedEventEnd());
}
@ -351,6 +378,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetDomComplete();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetDomComplete());
}
@ -361,6 +391,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetLoadEventStart();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetLoadEventStart());
}
@ -371,6 +404,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetLoadEventEnd();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetLoadEventEnd());
}
@ -381,6 +417,9 @@ public:
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetTimeToNonBlankPaint();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetTimeToNonBlankPaint());
}

Просмотреть файл

@ -55,9 +55,12 @@ bool nsMixedContentBlocker::sBlockMixedScript = false;
bool nsMixedContentBlocker::sBlockMixedObjectSubrequest = false;
// Is mixed display content blocking (images, audio, video, <a ping>) enabled?
// Is mixed display content blocking (images, audio, video) enabled?
bool nsMixedContentBlocker::sBlockMixedDisplay = false;
// Is mixed display content upgrading (images, audio, video) enabled?
bool nsMixedContentBlocker::sUpgradeMixedDisplay = false;
enum MixedContentHSTSState {
MCB_HSTS_PASSIVE_NO_HSTS = 0,
MCB_HSTS_PASSIVE_WITH_HSTS = 1,
@ -214,6 +217,10 @@ nsMixedContentBlocker::nsMixedContentBlocker()
// Cache the pref for mixed display blocking
Preferences::AddBoolVarCache(&sBlockMixedDisplay,
"security.mixed_content.block_display_content");
// Cache the pref for mixed display upgrading
Preferences::AddBoolVarCache(&sUpgradeMixedDisplay,
"security.mixed_content.upgrade_display_content");
}
nsMixedContentBlocker::~nsMixedContentBlocker()
@ -777,7 +784,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// pref "security.mixed_content.upgrade_display_content" is true.
// This behaves like GetUpgradeInsecureRequests above in that the channel will
// be upgraded to https before fetching any data from the netwerk.
bool isUpgradableDisplayType = nsContentUtils::IsUpgradableDisplayType(aContentType);
bool isUpgradableDisplayType = nsContentUtils::IsUpgradableDisplayType(aContentType) && ShouldUpgradeMixedDisplayContent();
if (isHttpScheme && isUpgradableDisplayType) {
*aDecision = ACCEPT;
return NS_OK;
@ -1128,3 +1135,9 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS(
}
}
}
bool
nsMixedContentBlocker::ShouldUpgradeMixedDisplayContent()
{
return sUpgradeMixedDisplay;
}

Просмотреть файл

@ -72,9 +72,12 @@ public:
bool aActive,
const OriginAttributes& aOriginAttributes);
static bool ShouldUpgradeMixedDisplayContent();
static bool sBlockMixedScript;
static bool sBlockMixedObjectSubrequest;
static bool sBlockMixedDisplay;
static bool sUpgradeMixedDisplay;
};
#endif /* nsMixedContentBlocker_h___ */

Просмотреть файл

@ -51,7 +51,7 @@
}
function nativeCallback() {
new Promise(function(resolve, reject) { resolve(42); }).then(console.log.bind(console));
new Promise(function(resolve, reject) { resolve(42); }).then(console.log);
}
function timeStamp(val) {

Просмотреть файл

@ -2622,8 +2622,12 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
if (mIsSecureContext) {
mJSSettings.chrome.compartmentOptions
.creationOptions().setSecureContext(true);
mJSSettings.chrome.compartmentOptions
.creationOptions().setClampAndJitterTime(false);
mJSSettings.content.compartmentOptions
.creationOptions().setSecureContext(true);
mJSSettings.content.compartmentOptions
.creationOptions().setClampAndJitterTime(false);
}
mIsInAutomation = xpc::IsInAutomation();

Просмотреть файл

@ -404,6 +404,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
static_cast<uint32_t>(aLoadInfo->GetTainting()),
aLoadInfo->GetUpgradeInsecureRequests(),
aLoadInfo->GetBrowserUpgradeInsecureRequests(),
aLoadInfo->GetBrowserWouldUpgradeInsecureRequests(),
aLoadInfo->GetVerifySignedContent(),
aLoadInfo->GetEnforceSRI(),
aLoadInfo->GetAllowDocumentToBeAgnosticToCSP(),
@ -551,6 +552,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
static_cast<LoadTainting>(loadInfoArgs.tainting()),
loadInfoArgs.upgradeInsecureRequests(),
loadInfoArgs.browserUpgradeInsecureRequests(),
loadInfoArgs.browserWouldUpgradeInsecureRequests(),
loadInfoArgs.verifySignedContent(),
loadInfoArgs.enforceSRI(),
loadInfoArgs.allowDocumentToBeAgnosticToCSP(),

Просмотреть файл

@ -80,7 +80,7 @@ function reinitializeRegistry() {
registry = {
spectest: {
print: console.log.bind(console),
print: console.log,
global: 666,
table: new WebAssembly.Table({initial: 10, maximum: 20, element: 'anyfunc'}),
memory: new WebAssembly.Memory({initial: 1, maximum: 2})

Просмотреть файл

@ -1994,7 +1994,8 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
preserveJitCode_(false),
cloneSingletons_(false),
sharedMemoryAndAtomics_(false),
secureContext_(false)
secureContext_(false),
clampAndJitterTime_(true)
{}
JSTraceOp getTrace() const {
@ -2062,6 +2063,12 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
return *this;
}
bool clampAndJitterTime() const { return clampAndJitterTime_; }
CompartmentCreationOptions& setClampAndJitterTime(bool flag) {
clampAndJitterTime_ = flag;
return *this;
}
private:
JSTraceOp traceGlobal_;
ZoneSpecifier zoneSpec_;
@ -2072,6 +2079,7 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
bool cloneSingletons_;
bool sharedMemoryAndAtomics_;
bool secureContext_;
bool clampAndJitterTime_;
};
/**

15
js/src/jsdate.cpp Executable file → Normal file
Просмотреть файл

@ -1305,12 +1305,13 @@ date_parse(JSContext* cx, unsigned argc, Value* vp)
}
static ClippedTime
NowAsMillis()
NowAsMillis(JSContext* cx)
{
double now = PRMJ_Now();
if (sReduceMicrosecondTimePrecisionCallback)
bool clampAndJitter = JS::CompartmentCreationOptionsRef(js::GetContextCompartment(cx)).clampAndJitterTime();
if (clampAndJitter && sReduceMicrosecondTimePrecisionCallback)
now = sReduceMicrosecondTimePrecisionCallback(now);
else if (sResolutionUsec) {
else if (clampAndJitter && sResolutionUsec) {
double clamped = floor(now / sResolutionUsec) * sResolutionUsec;
if (sJitter) {
@ -1349,7 +1350,7 @@ bool
js::date_now(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().set(TimeValue(NowAsMillis()));
args.rval().set(TimeValue(NowAsMillis(cx)));
return true;
}
@ -3120,7 +3121,7 @@ DateNoArguments(JSContext* cx, const CallArgs& args)
{
MOZ_ASSERT(args.length() == 0);
ClippedTime now = NowAsMillis();
ClippedTime now = NowAsMillis(cx);
if (args.isConstructing())
return NewDateObject(cx, args, now);
@ -3171,7 +3172,7 @@ DateOneArgument(JSContext* cx, const CallArgs& args)
return NewDateObject(cx, args, t);
}
return ToDateString(cx, args, NowAsMillis());
return ToDateString(cx, args, NowAsMillis(cx));
}
static bool
@ -3251,7 +3252,7 @@ DateMultipleArguments(JSContext* cx, const CallArgs& args)
return NewDateObject(cx, args, TimeClip(UTC(finalDate)));
}
return ToDateString(cx, args, NowAsMillis());
return ToDateString(cx, args, NowAsMillis(cx));
}
bool

Просмотреть файл

@ -0,0 +1,20 @@
<script>
function f() {
var buffer = new Uint8Array(8);
for (var i=0; i<100; i++) {}
buffer[0] = 0xff;
buffer[1] = 0xff;
buffer[2] = 0xff;
buffer[3] = 0xff;
buffer[4] = 0xff;
buffer[5] = 0xff;
buffer[6] = 0x0f;
buffer[7] = 0x00;
var view = new DataView(buffer.buffer);
view.getFloat64(0);
}
f();
</script>

Просмотреть файл

@ -55,3 +55,4 @@ load 854139.html
load 854604.html
pref(dom.use_xbl_scopes_for_remote_xul,true) load 898939.html
pref(security.fileuri.strict_origin_policy,false) load 938297.html
load 977538.html

Просмотреть файл

@ -991,6 +991,9 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
// [SecureContext] API (bug 1273687). In that case we'd call
// creationOptions.setSecureContext(true).
if (principal == nsXPConnect::SystemPrincipal())
creationOptions.setClampAndJitterTime(false);
if (xpc::SharedMemoryEnabled())
creationOptions.setSharedMemoryAndAtomicsEnabled(true);

Просмотреть файл

@ -508,6 +508,7 @@ InitGlobalObjectOptions(JS::CompartmentOptions& aOptions,
if (isSystem) {
// Make sure [SecureContext] APIs are visible:
aOptions.creationOptions().setSecureContext(true);
aOptions.creationOptions().setClampAndJitterTime(false);
}
if (shouldDiscardSystemSource) {

Просмотреть файл

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AutoProfilerStyleMarker_h
#define mozilla_AutoProfilerStyleMarker_h
#include "mozilla/Attributes.h"
#include "mozilla/ServoTraversalStatistics.h"
#include "mozilla/TimeStamp.h"
#include "GeckoProfiler.h"
#include "ProfilerMarkerPayload.h"
namespace mozilla {
class MOZ_RAII AutoProfilerStyleMarker
{
public:
explicit AutoProfilerStyleMarker(UniqueProfilerBacktrace aCause)
: mActive(profiler_is_active())
, mStartTime(TimeStamp::Now())
, mCause(Move(aCause))
{
if (!mActive) {
return;
}
MOZ_ASSERT(!ServoTraversalStatistics::sActive,
"Nested AutoProfilerStyleMarker");
ServoTraversalStatistics::sSingleton = ServoTraversalStatistics();
ServoTraversalStatistics::sActive = true;
}
~AutoProfilerStyleMarker()
{
if (!mActive) {
return;
}
ServoTraversalStatistics::sActive = false;
profiler_add_marker("Styles", MakeUnique<StyleMarkerPayload>(
mStartTime, TimeStamp::Now(), Move(mCause),
ServoTraversalStatistics::sSingleton));
}
private:
bool mActive;
TimeStamp mStartTime;
UniqueProfilerBacktrace mCause;
};
} // namespace mozilla
#endif // mozilla_AutoProfilerStyleMarker_h

Просмотреть файл

@ -8,6 +8,7 @@
#include "mozilla/PresShell.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/StyleSheetInlines.h"
@ -94,6 +95,9 @@
#include "nsDisplayList.h"
#include "nsRegion.h"
#include "nsAutoLayoutPhase.h"
#ifdef MOZ_GECKO_PROFILER
#include "AutoProfilerStyleMarker.h"
#endif
#ifdef MOZ_REFLOW_PERF
#include "nsFontMetrics.h"
#endif
@ -4056,6 +4060,13 @@ nsIPresShell::IsSafeToFlush() const
return true;
}
void
nsIPresShell::NotifyFontFaceSetOnRefresh()
{
if (FontFaceSet* set = mDocument->GetFonts()) {
set->DidRefresh();
}
}
void
PresShell::DoFlushPendingNotifications(FlushType aType)
@ -4188,9 +4199,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
if (!mIsDestroying) {
nsAutoScriptBlocker scriptBlocker;
#ifdef MOZ_GECKO_PROFILER
AutoProfilerTracing tracingStyleFlush("Paint", "Styles",
Move(mStyleCause));
mStyleCause = nullptr;
AutoProfilerStyleMarker tracingStyleFlush(Move(mStyleCause));
#endif
mPresContext->RestyleManager()->ProcessPendingRestyles();
@ -4214,9 +4223,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
if (!mIsDestroying) {
nsAutoScriptBlocker scriptBlocker;
#ifdef MOZ_GECKO_PROFILER
AutoProfilerTracing tracingStyleFlush("Paint", "Styles",
Move(mStyleCause));
mStyleCause = nullptr;
AutoProfilerStyleMarker tracingStyleFlush(Move(mStyleCause));
#endif
mPresContext->RestyleManager()->ProcessPendingRestyles();
@ -8610,7 +8617,7 @@ PresShell::WillDoReflow()
mPresContext->FlushFontFeatureValues();
mLastReflowStart = GetPerformanceNow();
mLastReflowStart = GetPerformanceNowUnclamped();
}
void
@ -8620,7 +8627,7 @@ PresShell::DidDoReflow(bool aInterruptible)
nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
if (docShell) {
DOMHighResTimeStamp now = GetPerformanceNow();
DOMHighResTimeStamp now = GetPerformanceNowUnclamped();
docShell->NotifyReflowObservers(aInterruptible, mLastReflowStart, now);
}
@ -8632,7 +8639,7 @@ PresShell::DidDoReflow(bool aInterruptible)
}
DOMHighResTimeStamp
PresShell::GetPerformanceNow()
PresShell::GetPerformanceNowUnclamped()
{
DOMHighResTimeStamp now = 0;
@ -8640,7 +8647,7 @@ PresShell::GetPerformanceNow()
Performance* perf = window->GetPerformance();
if (perf) {
now = perf->Now();
now = perf->NowUnclamped();
}
}

Просмотреть файл

@ -713,7 +713,7 @@ private:
nscolor GetDefaultBackgroundColorToDraw();
DOMHighResTimeStamp GetPerformanceNow();
DOMHighResTimeStamp GetPerformanceNowUnclamped();
// The callback for the mPaintSuppressionTimer timer.
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);

Просмотреть файл

@ -540,6 +540,12 @@ public:
*/
bool IsSafeToFlush() const;
/**
* Informs the document's FontFaceSet that the refresh driver ticked,
* flushing style and layout.
*/
void NotifyFontFaceSetOnRefresh();
/**
* Flush pending notifications of the type specified. This method
* will not affect the content model; it'll just affect style and
@ -555,7 +561,6 @@ public:
*
* @param aType the type of notifications to flush
*/
public:
void FlushPendingNotifications(mozilla::FlushType aType)
{
if (!NeedFlush(aType)) {

Просмотреть файл

@ -79,7 +79,6 @@
#include "gfxPrefs.h"
#include "nsIDOMChromeWindow.h"
#include "nsFrameLoader.h"
#include "mozilla/dom/FontFaceSet.h"
#include "nsContentUtils.h"
#include "nsPIWindowRoot.h"
#include "mozilla/Preferences.h"
@ -2879,15 +2878,6 @@ nsPresContext::HavePendingInputEvent()
}
}
void
nsPresContext::NotifyFontFaceSetOnRefresh()
{
FontFaceSet* set = mDocument->GetFonts();
if (set) {
set->DidRefresh();
}
}
bool
nsPresContext::HasPendingRestyleOrReflow()
{

Просмотреть файл

@ -1064,12 +1064,6 @@ public:
*/
bool HasPendingRestyleOrReflow();
/**
* Informs the document's FontFaceSet that the refresh driver ticked,
* flushing style and layout.
*/
void NotifyFontFaceSetOnRefresh();
/**
* Notify the prescontext that the presshell is about to reflow a reflow root.
* The single argument indicates whether this reflow should be interruptible.

Просмотреть файл

@ -1917,10 +1917,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
// Inform the FontFaceSet that we ticked, so that it can resolve its
// ready promise if it needs to (though it might still be waiting on
// a layout flush).
nsPresContext* presContext = shell->GetPresContext();
if (presContext) {
presContext->NotifyFontFaceSetOnRefresh();
}
shell->NotifyFontFaceSetOnRefresh();
mNeedToRecomputeVisibility = true;
}
}
@ -1945,10 +1942,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
shell->FlushPendingNotifications(ChangesToFlush(flushType, false));
// Inform the FontFaceSet that we ticked, so that it can resolve its
// ready promise if it needs to.
nsPresContext* presContext = shell->GetPresContext();
if (presContext) {
presContext->NotifyFontFaceSetOnRefresh();
}
shell->NotifyFontFaceSetOnRefresh();
mNeedToRecomputeVisibility = true;
}
}

Просмотреть файл

@ -68,6 +68,7 @@
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/SystemGroup.h"
#include "mozilla/ServoMediaList.h"
#include "mozilla/ServoTraversalStatistics.h"
#include "mozilla/Telemetry.h"
#include "mozilla/RWLock.h"
#include "mozilla/dom/Element.h"
@ -97,6 +98,10 @@ using namespace mozilla::dom;
SERVO_ARC_TYPE(StyleContext, ServoStyleContext)
#undef SERVO_ARC_TYPE
// Definitions of the global traversal stats.
bool ServoTraversalStatistics::sActive = false;
ServoTraversalStatistics ServoTraversalStatistics::sSingleton;
static RWLock* sServoFFILock = nullptr;
static

Просмотреть файл

@ -76,6 +76,7 @@ headers = [
"mozilla/ServoMediaList.h",
"mozilla/ServoStyleContext.h",
"mozilla/ServoDeclarationBlock.h",
"mozilla/ServoTraversalStatistics.h",
"mozilla/SizeOfState.h",
"nsCSSCounterStyleRule.h",
"nsCSSFontFaceRule.h",
@ -230,6 +231,7 @@ whitelist-types = [
"mozilla::ServoStyleSheet",
"mozilla::ServoStyleSheetInner",
"mozilla::ServoStyleSetSizes",
"mozilla::ServoTraversalStatistics",
"mozilla::CSSPseudoClassType",
"mozilla::css::ErrorReporter",
"mozilla::css::LoaderReusableStyleSheets",

Просмотреть файл

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ServoTraversalStatistics_h
#define mozilla_ServoTraversalStatistics_h
#include <inttypes.h>
namespace mozilla {
// Traversal statistics for Servo traversal.
//
// See style::context::PerThreadTraversalStatistics for
// meaning of these fields.
struct ServoTraversalStatistics
{
uint32_t mElementsTraversed = 0;
uint32_t mElementsStyled = 0;
uint32_t mElementsMatched = 0;
uint32_t mStylesShared = 0;
uint32_t mStylesReused = 0;
static bool sActive;
static ServoTraversalStatistics sSingleton;
};
} // namespace mozilla
#endif // mozilla_ServoTraversalStatistics_h

Просмотреть файл

@ -123,6 +123,7 @@ EXPORTS.mozilla += [
'ServoStyleSet.h',
'ServoStyleSheet.h',
'ServoSupportsRule.h',
'ServoTraversalStatistics.h',
'ServoTypes.h',
'ServoUtils.h',
'SheetType.h',

Просмотреть файл

@ -11,11 +11,9 @@ import org.json.simple.JSONObject;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.sync.CryptoRecord;
import org.mozilla.gecko.sync.InfoConfiguration;
import org.mozilla.gecko.sync.Server15PreviousPostFailedException;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.repositories.RepositorySession;
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate;
import org.mozilla.gecko.sync.repositories.domain.BookmarkRecord;
import org.mozilla.gecko.sync.repositories.domain.Record;
import java.util.ArrayList;
@ -102,8 +100,10 @@ public class BatchingUploader {
// maintain this limit for a single sanity check.
private final long maxPayloadFieldBytes;
// Set if this channel should ignore further calls to process.
private volatile boolean aborted = false;
// Depending on the 'shouldFailBatchOnFailure' flag below, "invalid" records (too large or fail
// to serialize correctly) will cause uploader to start ignoring any future records in the current
// flow.
private volatile boolean encounteredInvalidRecord = false;
// Whether or not we should set aborted if there are any issues with the record.
// This is used to prevent corruption with bookmark records, as uploading
@ -140,7 +140,7 @@ public class BatchingUploader {
final String guid = record.guid;
// If store failed entirely, just bail out. We've already told our delegate that we failed.
if (payloadDispatcher.storeFailed.get() || aborted) {
if (shouldIgnoreFurtherRecords()) {
return;
}
@ -148,7 +148,7 @@ public class BatchingUploader {
final String payloadField = (String) recordJSON.get(CryptoRecord.KEY_PAYLOAD);
if (payloadField == null) {
failRecordStore(new IllegalRecordException(), record, false);
processInvalidRecord(new IllegalRecordException(), record, false);
return;
}
@ -156,13 +156,13 @@ public class BatchingUploader {
// UTF-8 uses 1 byte per character for the ASCII range. Contents of the payloadField are
// base64 and hex encoded, so character count is sufficient.
if (payloadField.length() > this.maxPayloadFieldBytes) {
failRecordStore(new PayloadTooLargeToUpload(), record, true);
processInvalidRecord(new PayloadTooLargeToUpload(), record, true);
return;
}
final byte[] recordBytes = Record.stringToJSONBytes(recordJSON.toJSONString());
if (recordBytes == null) {
failRecordStore(new IllegalRecordException(), record, false);
processInvalidRecord(new IllegalRecordException(), record, false);
return;
}
@ -171,7 +171,7 @@ public class BatchingUploader {
// We can't upload individual records which exceed our payload total byte limit.
if ((recordDeltaByteCount + PER_PAYLOAD_OVERHEAD_BYTE_COUNT) > payload.maxBytes) {
failRecordStore(new RecordTooLargeToUpload(), record, true);
processInvalidRecord(new RecordTooLargeToUpload(), record, true);
return;
}
@ -221,6 +221,13 @@ public class BatchingUploader {
}
public void noMoreRecordsToUpload() {
// It's possible that we've hit a failure during an upload.
// If that's the case, bail out. Our delegate chain has already been notified.
if (shouldIgnoreFurtherRecords()) {
Logger.debug(LOG_TAG, "Ignoring 'no more records to upload' signal due to previous failure.");
return;
}
Logger.debug(LOG_TAG, "Received 'no more records to upload' signal.");
// If we have any pending records in the Payload, flush them!
@ -250,8 +257,14 @@ public class BatchingUploader {
sessionStoreDelegate.deferredStoreDelegate(executor).onStoreCompleted();
}
private boolean shouldIgnoreFurtherRecords() {
return (shouldFailBatchOnFailure && encounteredInvalidRecord) || payloadDispatcher.storeFailed.get();
}
// Common handling for marking a record failure and calling our delegate's onRecordStoreFailed.
private void failRecordStore(final Exception e, final Record record, boolean sizeOverflow) {
private void processInvalidRecord(final Exception e, final Record record, boolean sizeOverflow) {
encounteredInvalidRecord = true;
// There are three cases we're handling here. See bug 1362206 for some rationale here.
// 1. shouldFailBatchOnFailure is false, and it failed sanity checks for reasons other than
// "it's too large" (say, `record`'s json is 0 bytes),
@ -263,18 +276,12 @@ public class BatchingUploader {
if (shouldFailBatchOnFailure) {
// case 3
Logger.debug(LOG_TAG, "Batch failed with exception: " + e.toString());
// Start ignoring records, and send off to our delegate that we failed.
aborted = true;
executor.execute(new PayloadDispatcher.NonPayloadContextRunnable() {
@Override
public void run() {
sessionStoreDelegate.onRecordStoreFailed(e, record.guid);
payloadDispatcher.doStoreFailed(e);
}
});
// Send off to our delegate that we failed.
sessionStoreDelegate.onRecordStoreFailed(e, record.guid);
payloadDispatcher.doStoreFailed(e);
} else if (!sizeOverflow) {
// case 1
sessionStoreDelegate.deferredStoreDelegate(executor).onRecordStoreFailed(e, record.guid);
sessionStoreDelegate.onRecordStoreFailed(e, record.guid);
}
// case 2 is an implicit empty else {} here.
}
@ -342,7 +349,8 @@ public class BatchingUploader {
/* package-local */ static class PayloadTooLargeToUpload extends BatchingUploaderException {
private static final long serialVersionUID = 1L;
}
private static class IllegalRecordException extends BatchingUploaderException {
@VisibleForTesting
/* package-local */ static class IllegalRecordException extends BatchingUploaderException {
private static final long serialVersionUID = 1L;
}
}

Просмотреть файл

@ -231,6 +231,13 @@ public class RecordsChannel implements
// Allow this buffer to be reclaimed.
toProcess = null;
// It's possible that one of the delegate-driven `store` calls above failed.
// In that case, 'onStoreFailed' would have been already called, and we have nothing left to do.
if (storeFailed.get()) {
Logger.info(LOG_TAG, "Store failed while processing records via sink.store(...); bailing out.");
return;
}
// Now we wait for onStoreComplete
Logger.trace(LOG_TAG, "onFetchCompleted. Calling storeDone.");
sink.storeDone();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше