зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
b5ff200fa2
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче