зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
5ebab45abd
|
@ -1102,7 +1102,9 @@ nsContextMenu.prototype = {
|
||||||
// nsIExternalHelperAppService.doContent, which will wait for the
|
// nsIExternalHelperAppService.doContent, which will wait for the
|
||||||
// appropriate MIME-type headers and then prompt the user with a
|
// appropriate MIME-type headers and then prompt the user with a
|
||||||
// file picker
|
// file picker
|
||||||
function saveAsListener() {}
|
function saveAsListener(principal) {
|
||||||
|
this._triggeringPrincipal = principal;
|
||||||
|
}
|
||||||
saveAsListener.prototype = {
|
saveAsListener.prototype = {
|
||||||
extListener: null,
|
extListener: null,
|
||||||
|
|
||||||
|
@ -1146,7 +1148,7 @@ nsContextMenu.prototype = {
|
||||||
// do it the old fashioned way, which will pick the best filename
|
// do it the old fashioned way, which will pick the best filename
|
||||||
// it can without waiting.
|
// it can without waiting.
|
||||||
saveURL(linkURL, linkText, dialogTitle, bypassCache, false, docURI,
|
saveURL(linkURL, linkText, dialogTitle, bypassCache, false, docURI,
|
||||||
doc, isContentWindowPrivate);
|
doc, isContentWindowPrivate, this._triggeringPrincipal);
|
||||||
}
|
}
|
||||||
if (this.extListener)
|
if (this.extListener)
|
||||||
this.extListener.onStopRequest(aRequest, aStatusCode);
|
this.extListener.onStopRequest(aRequest, aStatusCode);
|
||||||
|
@ -1226,7 +1228,7 @@ nsContextMenu.prototype = {
|
||||||
timer.TYPE_ONE_SHOT);
|
timer.TYPE_ONE_SHOT);
|
||||||
|
|
||||||
// kick off the channel with our proxy object as the listener
|
// kick off the channel with our proxy object as the listener
|
||||||
channel.asyncOpen(new saveAsListener());
|
channel.asyncOpen(new saveAsListener(this.principal));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Save URL of clicked-on link.
|
// Save URL of clicked-on link.
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-icon-pending[preopened],
|
||||||
|
.tab-icon-image[preopened] {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-sharing-icon-overlay[sharing]:not([selected]),
|
.tab-sharing-icon-overlay[sharing]:not([selected]),
|
||||||
.tab-icon-overlay[soundplaying][pinned],
|
.tab-icon-overlay[soundplaying][pinned],
|
||||||
.tab-icon-overlay[muted][pinned],
|
.tab-icon-overlay[muted][pinned],
|
||||||
|
|
|
@ -32,6 +32,7 @@ window._gBrowser = {
|
||||||
window.addEventListener("occlusionstatechange", this);
|
window.addEventListener("occlusionstatechange", this);
|
||||||
|
|
||||||
this._setupInitialBrowserAndTab();
|
this._setupInitialBrowserAndTab();
|
||||||
|
this._preopenPinnedTabs();
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
|
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
|
||||||
this.tabpanels.style.backgroundColor = "-moz-default-background-color";
|
this.tabpanels.style.backgroundColor = "-moz-default-background-color";
|
||||||
|
@ -383,6 +384,29 @@ window._gBrowser = {
|
||||||
browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_preopenPinnedTabs() {
|
||||||
|
let numPinnedTabs = 0;
|
||||||
|
let windows = browserWindows();
|
||||||
|
windows.getNext();
|
||||||
|
let isOnlyWindow = !windows.hasMoreElements();
|
||||||
|
if (isOnlyWindow) {
|
||||||
|
numPinnedTabs = Services.prefs.getIntPref("browser.tabs.firstWindowRestore.numPinnedTabs", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < numPinnedTabs; i++) {
|
||||||
|
let tab = this.addTrustedTab("about:blank", {
|
||||||
|
skipAnimation: true,
|
||||||
|
noInitialLabel: true,
|
||||||
|
skipBackgroundNotify: true,
|
||||||
|
createLazyBrowser: true,
|
||||||
|
pinned: true,
|
||||||
|
isForFirstWindowRestore: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
tab.setAttribute("preopened", "true");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
|
* BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
|
||||||
* MAKE SURE TO ADD IT HERE AS WELL.
|
* MAKE SURE TO ADD IT HERE AS WELL.
|
||||||
|
@ -593,14 +617,32 @@ window._gBrowser = {
|
||||||
this.tabContainer._updateCloseButtons();
|
this.tabContainer._updateCloseButtons();
|
||||||
},
|
},
|
||||||
|
|
||||||
_notifyPinnedStatus(aTab) {
|
_sendPinnedTabContentMessage(aTab) {
|
||||||
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: aTab.pinned });
|
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: aTab.pinned });
|
||||||
|
},
|
||||||
|
|
||||||
|
_notifyPinnedStatus(aTab, aDeferContentMessage = false) {
|
||||||
|
if (!aDeferContentMessage) {
|
||||||
|
this._sendPinnedTabContentMessage(aTab);
|
||||||
|
}
|
||||||
|
|
||||||
let event = document.createEvent("Events");
|
let event = document.createEvent("Events");
|
||||||
event.initEvent(aTab.pinned ? "TabPinned" : "TabUnpinned", true, false);
|
event.initEvent(aTab.pinned ? "TabPinned" : "TabUnpinned", true, false);
|
||||||
aTab.dispatchEvent(event);
|
aTab.dispatchEvent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_maybeUpdateNumPinnedTabsPref() {
|
||||||
|
if (BrowserWindowTracker.getTopWindow() == window) {
|
||||||
|
Services.prefs.setIntPref("browser.tabs.firstWindowRestore.numPinnedTabs",
|
||||||
|
this._numPinnedTabs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
activatePreopenedPinnedTab(aTab) {
|
||||||
|
this._insertBrowser(aTab);
|
||||||
|
this._sendPinnedTabContentMessage(aTab);
|
||||||
|
},
|
||||||
|
|
||||||
pinTab(aTab) {
|
pinTab(aTab) {
|
||||||
if (aTab.pinned)
|
if (aTab.pinned)
|
||||||
return;
|
return;
|
||||||
|
@ -612,6 +654,7 @@ window._gBrowser = {
|
||||||
aTab.setAttribute("pinned", "true");
|
aTab.setAttribute("pinned", "true");
|
||||||
this._updateTabBarForPinnedTabs();
|
this._updateTabBarForPinnedTabs();
|
||||||
this._notifyPinnedStatus(aTab);
|
this._notifyPinnedStatus(aTab);
|
||||||
|
this._maybeUpdateNumPinnedTabsPref();
|
||||||
},
|
},
|
||||||
|
|
||||||
unpinTab(aTab) {
|
unpinTab(aTab) {
|
||||||
|
@ -623,6 +666,7 @@ window._gBrowser = {
|
||||||
aTab.style.marginInlineStart = "";
|
aTab.style.marginInlineStart = "";
|
||||||
this._updateTabBarForPinnedTabs();
|
this._updateTabBarForPinnedTabs();
|
||||||
this._notifyPinnedStatus(aTab);
|
this._notifyPinnedStatus(aTab);
|
||||||
|
this._maybeUpdateNumPinnedTabsPref();
|
||||||
},
|
},
|
||||||
|
|
||||||
previewTab(aTab, aCallback) {
|
previewTab(aTab, aCallback) {
|
||||||
|
@ -2306,6 +2350,7 @@ window._gBrowser = {
|
||||||
forceNotRemote,
|
forceNotRemote,
|
||||||
fromExternal,
|
fromExternal,
|
||||||
index,
|
index,
|
||||||
|
isForFirstWindowRestore,
|
||||||
lazyTabTitle,
|
lazyTabTitle,
|
||||||
name,
|
name,
|
||||||
nextTabParentId,
|
nextTabParentId,
|
||||||
|
@ -2489,6 +2534,9 @@ window._gBrowser = {
|
||||||
|
|
||||||
if (pinned) {
|
if (pinned) {
|
||||||
this._updateTabBarForPinnedTabs();
|
this._updateTabBarForPinnedTabs();
|
||||||
|
if (!isForFirstWindowRestore) {
|
||||||
|
this._maybeUpdateNumPinnedTabsPref();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.tabContainer._setPositionalAttributes();
|
this.tabContainer._setPositionalAttributes();
|
||||||
|
|
||||||
|
@ -2568,13 +2616,15 @@ window._gBrowser = {
|
||||||
userContextId);
|
userContextId);
|
||||||
b.registeredOpenURI = lazyBrowserURI;
|
b.registeredOpenURI = lazyBrowserURI;
|
||||||
}
|
}
|
||||||
SessionStore.setTabState(t, {
|
if (!isForFirstWindowRestore) {
|
||||||
entries: [{
|
SessionStore.setTabState(t, {
|
||||||
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
|
entries: [{
|
||||||
title: lazyTabTitle,
|
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
|
||||||
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
|
title: lazyTabTitle,
|
||||||
}],
|
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
|
||||||
});
|
}],
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._insertBrowser(t, true);
|
this._insertBrowser(t, true);
|
||||||
}
|
}
|
||||||
|
@ -2612,7 +2662,9 @@ window._gBrowser = {
|
||||||
|
|
||||||
// If we didn't swap docShells with a preloaded browser
|
// If we didn't swap docShells with a preloaded browser
|
||||||
// then let's just continue loading the page normally.
|
// then let's just continue loading the page normally.
|
||||||
if (!usingPreloadedContent && (!uriIsAboutBlank || !allowInheritPrincipal)) {
|
if (!usingPreloadedContent &&
|
||||||
|
!createLazyBrowser &&
|
||||||
|
(!uriIsAboutBlank || !allowInheritPrincipal)) {
|
||||||
// pretend the user typed this so it'll be available till
|
// pretend the user typed this so it'll be available till
|
||||||
// the document successfully loads
|
// the document successfully loads
|
||||||
if (aURI && !gInitialPages.includes(aURI)) {
|
if (aURI && !gInitialPages.includes(aURI)) {
|
||||||
|
@ -2665,7 +2717,7 @@ window._gBrowser = {
|
||||||
|
|
||||||
// Additionally send pinned tab events
|
// Additionally send pinned tab events
|
||||||
if (pinned) {
|
if (pinned) {
|
||||||
this._notifyPinnedStatus(t);
|
this._notifyPinnedStatus(t, isForFirstWindowRestore);
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
@ -3163,8 +3215,10 @@ window._gBrowser = {
|
||||||
this.tabs[i]._tPos = i;
|
this.tabs[i]._tPos = i;
|
||||||
|
|
||||||
if (!this._windowIsClosing) {
|
if (!this._windowIsClosing) {
|
||||||
if (wasPinned)
|
if (wasPinned) {
|
||||||
this.tabContainer._positionPinnedTabs();
|
this.tabContainer._positionPinnedTabs();
|
||||||
|
this._maybeUpdateNumPinnedTabsPref();
|
||||||
|
}
|
||||||
|
|
||||||
// update tab close buttons state
|
// update tab close buttons state
|
||||||
this.tabContainer._updateCloseButtons();
|
this.tabContainer._updateCloseButtons();
|
||||||
|
@ -3837,7 +3891,6 @@ window._gBrowser = {
|
||||||
skipAnimation: true,
|
skipAnimation: true,
|
||||||
index: aIndex,
|
index: aIndex,
|
||||||
createLazyBrowser,
|
createLazyBrowser,
|
||||||
allowInheritPrincipal: createLazyBrowser,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let numPinned = this._numPinnedTabs;
|
let numPinned = this._numPinnedTabs;
|
||||||
|
@ -5014,6 +5067,7 @@ class TabProgressListener {
|
||||||
this.mTab.removeAttribute("crashed");
|
this.mTab.removeAttribute("crashed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.mTab.removeAttribute("preopened");
|
||||||
if (this._shouldShowProgress(aRequest)) {
|
if (this._shouldShowProgress(aRequest)) {
|
||||||
if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_RESTORING) &&
|
if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_RESTORING) &&
|
||||||
aWebProgress && aWebProgress.isTopLevel) {
|
aWebProgress && aWebProgress.isTopLevel) {
|
||||||
|
|
|
@ -1937,10 +1937,10 @@
|
||||||
anonid="tab-throbber"
|
anonid="tab-throbber"
|
||||||
class="tab-throbber"
|
class="tab-throbber"
|
||||||
layer="true"/>
|
layer="true"/>
|
||||||
<xul:hbox xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected,pendingicon"
|
<xul:hbox xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected,pendingicon,preopened"
|
||||||
anonid="tab-icon-pending"
|
anonid="tab-icon-pending"
|
||||||
class="tab-icon-pending"/>
|
class="tab-icon-pending"/>
|
||||||
<xul:image xbl:inherits="src=image,triggeringprincipal=iconloadingprincipal,requestcontextid,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
|
<xul:image xbl:inherits="src=image,triggeringprincipal=iconloadingprincipal,requestcontextid,fadein,pinned,selected=visuallyselected,busy,crashed,sharing,preopened"
|
||||||
anonid="tab-icon-image"
|
anonid="tab-icon-image"
|
||||||
class="tab-icon-image"
|
class="tab-icon-image"
|
||||||
validate="never"
|
validate="never"
|
||||||
|
|
|
@ -66,7 +66,7 @@ add_task(async function() {
|
||||||
// Click once:
|
// Click once:
|
||||||
document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
|
document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
|
||||||
});
|
});
|
||||||
await promiseWaitForCondition(() => !testTab.parentNode);
|
await TestUtils.waitForCondition(() => !testTab.parentNode);
|
||||||
ok(!testTab.parentNode, "Tab should be closed completely");
|
ok(!testTab.parentNode, "Tab should be closed completely");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ skip-if = !e10s
|
||||||
run-if = debug || devedition || nightly_build # Requires startupRecorder.js, which isn't shipped everywhere by default
|
run-if = debug || devedition || nightly_build # Requires startupRecorder.js, which isn't shipped everywhere by default
|
||||||
[browser_tabclose_grow.js]
|
[browser_tabclose_grow.js]
|
||||||
[browser_tabclose.js]
|
[browser_tabclose.js]
|
||||||
skip-if = (os == 'win' && bits == 32) || (os == 'mac') # Bug 1488537, Bug 1531417
|
skip-if = (os == 'win') || (os == 'mac') # Bug 1488537, Bug 1531417, Bug 1497713
|
||||||
[browser_tabdetach.js]
|
[browser_tabdetach.js]
|
||||||
[browser_tabopen.js]
|
[browser_tabopen.js]
|
||||||
skip-if = (verify && (os == 'mac'))
|
skip-if = (verify && (os == 'mac'))
|
||||||
|
|
|
@ -126,6 +126,30 @@ add_task(async function testGloballyBlockedOnNewWindow() {
|
||||||
add_task(async function testBFCache() {
|
add_task(async function testBFCache() {
|
||||||
Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED);
|
Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED);
|
||||||
|
|
||||||
|
await BrowserTestUtils.withNewTab("about:home", async function(browser) {
|
||||||
|
await BrowserTestUtils.loadURI(browser, AUTOPLAY_PAGE);
|
||||||
|
await blockedIconShown(browser);
|
||||||
|
|
||||||
|
gBrowser.goBack();
|
||||||
|
await TestUtils.waitForCondition(() => {
|
||||||
|
return BrowserTestUtils.is_hidden(autoplayBlockedIcon());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Not sure why using `gBrowser.goForward()` doesn't trigger document's
|
||||||
|
// visibility changes in some debug build on try server, which makes us not
|
||||||
|
// to receive the blocked event.
|
||||||
|
await ContentTask.spawn(browser, null, () => {
|
||||||
|
content.history.forward();
|
||||||
|
});
|
||||||
|
await blockedIconShown(browser);
|
||||||
|
});
|
||||||
|
|
||||||
|
Services.perms.removeAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testChangingBlockingSettingDuringNavigation() {
|
||||||
|
Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED);
|
||||||
|
|
||||||
await BrowserTestUtils.withNewTab("about:home", async function(browser) {
|
await BrowserTestUtils.withNewTab("about:home", async function(browser) {
|
||||||
await BrowserTestUtils.loadURI(browser, AUTOPLAY_PAGE);
|
await BrowserTestUtils.loadURI(browser, AUTOPLAY_PAGE);
|
||||||
await blockedIconShown(browser);
|
await blockedIconShown(browser);
|
||||||
|
|
|
@ -26,7 +26,7 @@ add_task(async function() {
|
||||||
ok(!isFullscreenSizeMode(), "Should not be in fullscreen sizemode before we enter fullscreen.");
|
ok(!isFullscreenSizeMode(), "Should not be in fullscreen sizemode before we enter fullscreen.");
|
||||||
|
|
||||||
BrowserFullScreen();
|
BrowserFullScreen();
|
||||||
await waitForCondition(() => isFullscreenSizeMode());
|
await TestUtils.waitForCondition(() => isFullscreenSizeMode());
|
||||||
ok(fullscreenButton.checked, "Fullscreen button should be checked when in fullscreen.");
|
ok(fullscreenButton.checked, "Fullscreen button should be checked when in fullscreen.");
|
||||||
|
|
||||||
await startCustomizing();
|
await startCustomizing();
|
||||||
|
@ -41,7 +41,7 @@ add_task(async function() {
|
||||||
|
|
||||||
BrowserFullScreen();
|
BrowserFullScreen();
|
||||||
fullscreenButton = document.getElementById("fullscreen-button");
|
fullscreenButton = document.getElementById("fullscreen-button");
|
||||||
await waitForCondition(() => !isFullscreenSizeMode());
|
await TestUtils.waitForCondition(() => !isFullscreenSizeMode());
|
||||||
ok(!fullscreenButton.checked, "Fullscreen button should not be checked when not in fullscreen.");
|
ok(!fullscreenButton.checked, "Fullscreen button should not be checked when not in fullscreen.");
|
||||||
CustomizableUI.reset();
|
CustomizableUI.reset();
|
||||||
});
|
});
|
||||||
|
|
|
@ -249,8 +249,8 @@ var SessionStore = {
|
||||||
return SessionStoreInternal.getWindowState(aWindow);
|
return SessionStoreInternal.getWindowState(aWindow);
|
||||||
},
|
},
|
||||||
|
|
||||||
setWindowState: function ss_setWindowState(aWindow, aState, aOverwrite) {
|
setWindowState: function ss_setWindowState(aWindow, aState, aOverwrite, aFirstWindow) {
|
||||||
SessionStoreInternal.setWindowState(aWindow, aState, aOverwrite);
|
SessionStoreInternal.setWindowState(aWindow, aState, aOverwrite, aFirstWindow);
|
||||||
},
|
},
|
||||||
|
|
||||||
getTabState: function ss_getTabState(aTab) {
|
getTabState: function ss_getTabState(aTab) {
|
||||||
|
@ -731,6 +731,7 @@ var SessionStoreInternal = {
|
||||||
this._prefBranch.addObserver("sessionstore.max_windows_undo", this, true);
|
this._prefBranch.addObserver("sessionstore.max_windows_undo", this, true);
|
||||||
|
|
||||||
this._restore_on_demand = this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
|
this._restore_on_demand = this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
|
||||||
|
this._restore_pinned_tabs_on_demand = this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand");
|
||||||
this._prefBranch.addObserver("sessionstore.restore_on_demand", this, true);
|
this._prefBranch.addObserver("sessionstore.restore_on_demand", this, true);
|
||||||
|
|
||||||
gResistFingerprintingEnabled = Services.prefs.getBoolPref("privacy.resistFingerprinting");
|
gResistFingerprintingEnabled = Services.prefs.getBoolPref("privacy.resistFingerprinting");
|
||||||
|
@ -2499,12 +2500,15 @@ var SessionStoreInternal = {
|
||||||
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
||||||
},
|
},
|
||||||
|
|
||||||
setWindowState: function ssi_setWindowState(aWindow, aState, aOverwrite) {
|
setWindowState: function ssi_setWindowState(aWindow, aState, aOverwrite, aFirstWindow) {
|
||||||
if (!aWindow.__SSi) {
|
if (!aWindow.__SSi) {
|
||||||
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.restoreWindows(aWindow, aState, {overwriteTabs: aOverwrite});
|
this.restoreWindows(aWindow, aState, {
|
||||||
|
overwriteTabs: aOverwrite,
|
||||||
|
firstWindow: aFirstWindow,
|
||||||
|
});
|
||||||
|
|
||||||
// Notify of changes to closed objects.
|
// Notify of changes to closed objects.
|
||||||
this._notifyOfClosedObjectsChange();
|
this._notifyOfClosedObjectsChange();
|
||||||
|
@ -3203,6 +3207,7 @@ var SessionStoreInternal = {
|
||||||
if (!uriObj || (uriObj && !window.gBrowser.isLocalAboutURI(uriObj))) {
|
if (!uriObj || (uriObj && !window.gBrowser.isLocalAboutURI(uriObj))) {
|
||||||
tab.setAttribute("busy", "true");
|
tab.setAttribute("busy", "true");
|
||||||
}
|
}
|
||||||
|
tab.removeAttribute("preopened");
|
||||||
|
|
||||||
// Hack to ensure that the about:home, about:newtab, and about:welcome
|
// Hack to ensure that the about:home, about:newtab, and about:welcome
|
||||||
// favicon is loaded instantaneously, to avoid flickering and improve
|
// favicon is loaded instantaneously, to avoid flickering and improve
|
||||||
|
@ -3595,6 +3600,36 @@ var SessionStoreInternal = {
|
||||||
return Promise.all([...WINDOW_SHOWING_PROMISES.values()].map(deferred => deferred.promise));
|
return Promise.all([...WINDOW_SHOWING_PROMISES.values()].map(deferred => deferred.promise));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the pinning / unpinning of a selected tab restored with
|
||||||
|
* restoreWindow.
|
||||||
|
*
|
||||||
|
* @param aWindow
|
||||||
|
* Window reference to the window used for restoration
|
||||||
|
* @param aWinData
|
||||||
|
* The window data we're restoring
|
||||||
|
* @param aRestoreIndex
|
||||||
|
* The index of the tab data we're currently restoring
|
||||||
|
* @returns the selected tab
|
||||||
|
*/
|
||||||
|
_updateRestoredSelectedTabPinnedState(aWindow, aWinData, aRestoreIndex) {
|
||||||
|
let tabbrowser = aWindow.gBrowser;
|
||||||
|
let tabData = aWinData.tabs[aRestoreIndex];
|
||||||
|
let tab = tabbrowser.selectedTab;
|
||||||
|
let needsUnpin = tab.pinned && !tabData.pinned;
|
||||||
|
let needsPin = !tab.pinned && tabData.pinned;
|
||||||
|
if (needsUnpin) {
|
||||||
|
tabbrowser.unpinTab(tab);
|
||||||
|
} else if (needsPin && tab == tabbrowser.tabs[aRestoreIndex]) {
|
||||||
|
tabbrowser.pinTab(tab);
|
||||||
|
} else if (needsPin) {
|
||||||
|
tabbrowser.removeTab(tabbrowser.tabs[aRestoreIndex]);
|
||||||
|
tabbrowser.pinTab(tab);
|
||||||
|
tabbrowser.moveTabTo(tab, aRestoreIndex);
|
||||||
|
}
|
||||||
|
return tab;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* restore features to a single window
|
* restore features to a single window
|
||||||
* @param aWindow
|
* @param aWindow
|
||||||
|
@ -3650,7 +3685,7 @@ var SessionStoreInternal = {
|
||||||
|
|
||||||
// We need to keep track of the initially open tabs so that they
|
// We need to keep track of the initially open tabs so that they
|
||||||
// can be moved to the end of the restored tabs.
|
// can be moved to the end of the restored tabs.
|
||||||
let initialTabs;
|
let initialTabs = [];
|
||||||
if (!overwriteTabs && firstWindow) {
|
if (!overwriteTabs && firstWindow) {
|
||||||
initialTabs = Array.slice(tabbrowser.tabs);
|
initialTabs = Array.slice(tabbrowser.tabs);
|
||||||
}
|
}
|
||||||
|
@ -3658,8 +3693,11 @@ var SessionStoreInternal = {
|
||||||
// Get rid of tabs that aren't needed anymore.
|
// Get rid of tabs that aren't needed anymore.
|
||||||
if (overwriteTabs) {
|
if (overwriteTabs) {
|
||||||
for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
|
for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
|
||||||
if (!tabbrowser.tabs[i].selected) {
|
if (!tabbrowser.tabs[i].selected &&
|
||||||
|
!tabbrowser.tabs[i].hasAttribute("preopened")) {
|
||||||
tabbrowser.removeTab(tabbrowser.tabs[i]);
|
tabbrowser.removeTab(tabbrowser.tabs[i]);
|
||||||
|
} else if (tabbrowser.tabs[i].hasAttribute("preopened")) {
|
||||||
|
initialTabs.push(tabbrowser.tabs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3677,14 +3715,18 @@ var SessionStoreInternal = {
|
||||||
// selecting a new tab.
|
// selecting a new tab.
|
||||||
if (select &&
|
if (select &&
|
||||||
tabbrowser.selectedTab.userContextId == userContextId) {
|
tabbrowser.selectedTab.userContextId == userContextId) {
|
||||||
tab = tabbrowser.selectedTab;
|
tab = this._updateRestoredSelectedTabPinnedState(aWindow, winData, t);
|
||||||
if (!tabData.pinned) {
|
|
||||||
tabbrowser.unpinTab(tab);
|
|
||||||
}
|
|
||||||
tabbrowser.moveTabToEnd();
|
tabbrowser.moveTabToEnd();
|
||||||
if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
|
if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
|
||||||
tabbrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
|
tabbrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
|
||||||
}
|
}
|
||||||
|
} else if (tabData.pinned &&
|
||||||
|
tabbrowser.tabs[t] &&
|
||||||
|
tabbrowser.tabs[t].pinned &&
|
||||||
|
!tabbrowser.tabs[t].linkedPanel) {
|
||||||
|
tab = tabbrowser.tabs[t];
|
||||||
|
tabbrowser.activatePreopenedPinnedTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new tab if needed.
|
// Add a new tab if needed.
|
||||||
|
@ -3733,11 +3775,14 @@ var SessionStoreInternal = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the originally open tabs to the end.
|
// Move the originally open tabs to the end.
|
||||||
if (initialTabs) {
|
let endPosition = tabbrowser.tabs.length - 1;
|
||||||
let endPosition = tabbrowser.tabs.length - 1;
|
for (let tab of initialTabs) {
|
||||||
for (let i = 0; i < initialTabs.length; i++) {
|
if (tab.hasAttribute("preopened") &&
|
||||||
tabbrowser.unpinTab(initialTabs[i]);
|
!tab.linkedPanel) {
|
||||||
tabbrowser.moveTabTo(initialTabs[i], endPosition);
|
tabbrowser.removeTab(tab);
|
||||||
|
} else if (!tab.hasAttribute("preopened")) {
|
||||||
|
tabbrowser.unpinTab(tab);
|
||||||
|
tabbrowser.moveTabTo(tab, endPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3998,6 +4043,9 @@ var SessionStoreInternal = {
|
||||||
for (let t = 0; t < aTabs.length; t++) {
|
for (let t = 0; t < aTabs.length; t++) {
|
||||||
if (t != selectedIndex) {
|
if (t != selectedIndex) {
|
||||||
this.restoreTab(aTabs[t], aTabData[t]);
|
this.restoreTab(aTabs[t], aTabData[t]);
|
||||||
|
if (this._restore_pinned_tabs_on_demand) {
|
||||||
|
aTabs[t].removeAttribute("preopened");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -113,6 +113,7 @@ skip-if = (verify && (os == 'win' || os == 'mac'))
|
||||||
[browser_old_favicon.js]
|
[browser_old_favicon.js]
|
||||||
[browser_page_title.js]
|
[browser_page_title.js]
|
||||||
[browser_pending_tabs.js]
|
[browser_pending_tabs.js]
|
||||||
|
[browser_preopened_apptabs.js]
|
||||||
[browser_privatetabs.js]
|
[browser_privatetabs.js]
|
||||||
[browser_purge_shistory.js]
|
[browser_purge_shistory.js]
|
||||||
skip-if = e10s # Bug 1271024
|
skip-if = e10s # Bug 1271024
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
||||||
|
const PREF_NUM_PINNED_TABS = "browser.tabs.firstWindowRestore.numPinnedTabs";
|
||||||
|
|
||||||
|
function muffleMainWindowType() {
|
||||||
|
let oldWinType = document.documentElement.getAttribute("windowtype");
|
||||||
|
// Check if we've already done this to allow calling multiple times:
|
||||||
|
if (oldWinType != "navigator:testrunner") {
|
||||||
|
// Make the main test window not count as a browser window any longer
|
||||||
|
document.documentElement.setAttribute("windowtype", "navigator:testrunner");
|
||||||
|
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
document.documentElement.setAttribute("windowtype", oldWinType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
Services.prefs.clearUserPref(PREF_NUM_PINNED_TABS);
|
||||||
|
});
|
||||||
|
|
||||||
|
let testCases = [
|
||||||
|
{numPinnedPref: 5, selected: 3, overrideTabs: false},
|
||||||
|
{numPinnedPref: 5, selected: 3, overrideTabs: true},
|
||||||
|
{numPinnedPref: 5, selected: 1, overrideTabs: false},
|
||||||
|
{numPinnedPref: 5, selected: 1, overrideTabs: true},
|
||||||
|
{numPinnedPref: 3, selected: 3, overrideTabs: false},
|
||||||
|
{numPinnedPref: 3, selected: 3, overrideTabs: true},
|
||||||
|
{numPinnedPref: 3, selected: 1, overrideTabs: false},
|
||||||
|
{numPinnedPref: 3, selected: 1, overrideTabs: true},
|
||||||
|
{numPinnedPref: 1, selected: 3, overrideTabs: false},
|
||||||
|
{numPinnedPref: 1, selected: 3, overrideTabs: true},
|
||||||
|
{numPinnedPref: 1, selected: 1, overrideTabs: false},
|
||||||
|
{numPinnedPref: 1, selected: 1, overrideTabs: true},
|
||||||
|
{numPinnedPref: 0, selected: 3, overrideTabs: false},
|
||||||
|
{numPinnedPref: 0, selected: 3, overrideTabs: true},
|
||||||
|
{numPinnedPref: 0, selected: 1, overrideTabs: false},
|
||||||
|
{numPinnedPref: 0, selected: 1, overrideTabs: true},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let {numPinnedPref, selected, overrideTabs} of testCases) {
|
||||||
|
add_task(async function testPrefSynced() {
|
||||||
|
Services.prefs.setIntPref(PREF_NUM_PINNED_TABS, numPinnedPref);
|
||||||
|
|
||||||
|
let state = { windows: [{ tabs: [
|
||||||
|
{ entries: [{ url: "http://example.org/#1", triggeringPrincipal_base64 }], pinned: true, userContextId: 0 },
|
||||||
|
{ entries: [{ url: "http://example.org/#2", triggeringPrincipal_base64 }], pinned: true, userContextId: 0 },
|
||||||
|
{ entries: [{ url: "http://example.org/#3", triggeringPrincipal_base64 }], pinned: true, userContextId: 0 },
|
||||||
|
], selected }] };
|
||||||
|
|
||||||
|
muffleMainWindowType();
|
||||||
|
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||||
|
Assert.equal([...win.gBrowser.tabs].filter(t => t.pinned).length, numPinnedPref);
|
||||||
|
Assert.equal([...win.gBrowser.tabs].filter(t => !!t.linkedPanel).length, 1);
|
||||||
|
await setWindowState(win, state, overrideTabs, true);
|
||||||
|
Assert.equal([...win.gBrowser.tabs].filter(t => t.pinned).length, 3);
|
||||||
|
Assert.equal([...win.gBrowser.tabs].filter(t => !!t.linkedPanel).length,
|
||||||
|
overrideTabs ? 3 : 4);
|
||||||
|
await BrowserTestUtils.closeWindow(win);
|
||||||
|
});
|
||||||
|
}
|
|
@ -190,8 +190,9 @@ async function setBrowserState(state, win = window) {
|
||||||
await promiseWindowRestored(win);
|
await promiseWindowRestored(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setWindowState(win, state, overwrite = false) {
|
async function setWindowState(win, state, overwrite = false, firstWindow = false) {
|
||||||
ss.setWindowState(win, typeof state != "string" ? JSON.stringify(state) : state, overwrite);
|
ss.setWindowState(win, typeof state != "string" ? JSON.stringify(state) : state,
|
||||||
|
overwrite, firstWindow);
|
||||||
await promiseWindowRestored(win);
|
await promiseWindowRestored(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,11 @@ function _untrackWindowOrder(window) {
|
||||||
_trackedWindows.splice(idx, 1);
|
_trackedWindows.splice(idx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _trackPinnedTabs(window) {
|
||||||
|
Services.prefs.setIntPref("browser.tabs.firstWindowRestore.numPinnedTabs",
|
||||||
|
window.gBrowser._numPinnedTabs);
|
||||||
|
}
|
||||||
|
|
||||||
// Methods that impact a window. Put into single object for organization.
|
// Methods that impact a window. Put into single object for organization.
|
||||||
var WindowHelper = {
|
var WindowHelper = {
|
||||||
addWindow(window) {
|
addWindow(window) {
|
||||||
|
@ -138,6 +143,7 @@ var WindowHelper = {
|
||||||
|
|
||||||
_untrackWindowOrder(window);
|
_untrackWindowOrder(window);
|
||||||
_trackWindowOrder(window);
|
_trackWindowOrder(window);
|
||||||
|
_trackPinnedTabs(window);
|
||||||
|
|
||||||
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
|
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
|
||||||
},
|
},
|
||||||
|
|
|
@ -185,6 +185,8 @@
|
||||||
list-style-image: url("chrome://browser/skin/send-to-device.svg");
|
list-style-image: url("chrome://browser/skin/send-to-device.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pageAction-panel-pinTab:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
||||||
|
#pageAction-urlbar-pinTab:-moz-locale-dir(rtl),
|
||||||
#pageAction-panel-sendToDevice:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
#pageAction-panel-sendToDevice:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
||||||
#pageAction-urlbar-sendToDevice:-moz-locale-dir(rtl) {
|
#pageAction-urlbar-sendToDevice:-moz-locale-dir(rtl) {
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
|
|
|
@ -13,7 +13,7 @@ const { bootstrap, L10N } = require("devtools-launchpad");
|
||||||
|
|
||||||
window.L10N = L10N;
|
window.L10N = L10N;
|
||||||
// $FlowIgnore:
|
// $FlowIgnore:
|
||||||
window.L10N.setBundle(require("../assets/panel/debugger.properties"));
|
window.L10N.setBundle(require("../../../locales/en-US/debugger.properties"));
|
||||||
|
|
||||||
bootstrap(React, ReactDOM).then(connection => {
|
bootstrap(React, ReactDOM).then(connection => {
|
||||||
onConnect(connection, require("devtools-source-map"), {
|
onConnect(connection, require("devtools-source-map"), {
|
||||||
|
|
|
@ -3193,8 +3193,8 @@ Toolbox.prototype = {
|
||||||
* Opens source in style editor. Falls back to plain "view-source:".
|
* Opens source in style editor. Falls back to plain "view-source:".
|
||||||
* @see devtools/client/shared/source-utils.js
|
* @see devtools/client/shared/source-utils.js
|
||||||
*/
|
*/
|
||||||
viewSourceInStyleEditor: function(sourceURL, sourceLine) {
|
viewSourceInStyleEditor: function(sourceURL, sourceLine, sourceColumn) {
|
||||||
return viewSource.viewSourceInStyleEditor(this, sourceURL, sourceLine);
|
return viewSource.viewSourceInStyleEditor(this, sourceURL, sourceLine, sourceColumn);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,6 +95,7 @@ class DominatorTreeSiblingLinkClass extends Component {
|
||||||
},
|
},
|
||||||
dom.a(
|
dom.a(
|
||||||
{
|
{
|
||||||
|
className: "load-more-link",
|
||||||
onClick: () => onLoadMoreSiblings(item),
|
onClick: () => onLoadMoreSiblings(item),
|
||||||
},
|
},
|
||||||
L10N.getStr("tree-item.load-more")
|
L10N.getStr("tree-item.load-more")
|
||||||
|
|
|
@ -21,11 +21,11 @@ var { gDevTools } = require("devtools/client/framework/devtools");
|
||||||
* @return {Promise<boolean>}
|
* @return {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
exports.viewSourceInStyleEditor = async function(toolbox, sourceURL,
|
exports.viewSourceInStyleEditor = async function(toolbox, sourceURL,
|
||||||
sourceLine) {
|
sourceLine, sourceColumn) {
|
||||||
const panel = await toolbox.loadTool("styleeditor");
|
const panel = await toolbox.loadTool("styleeditor");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await panel.selectStyleSheet(sourceURL, sourceLine);
|
await panel.selectStyleSheet(sourceURL, sourceLine, sourceColumn);
|
||||||
await toolbox.selectTool("styleeditor");
|
await toolbox.selectTool("styleeditor");
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,252 +0,0 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
||||||
/* vim: set ft=javascript ts=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/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
|
|
||||||
|
|
||||||
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
|
||||||
const { ViewHelpers, setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["BreadcrumbsWidget"];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A breadcrumb-like list of items.
|
|
||||||
*
|
|
||||||
* Note: this widget should be used in tandem with the WidgetMethods in
|
|
||||||
* view-helpers.js.
|
|
||||||
*
|
|
||||||
* @param Node aNode
|
|
||||||
* The element associated with the widget.
|
|
||||||
* @param Object aOptions
|
|
||||||
* - smoothScroll: specifies if smooth scrolling on selection is enabled.
|
|
||||||
*/
|
|
||||||
this.BreadcrumbsWidget = function BreadcrumbsWidget(aNode, aOptions = {}) {
|
|
||||||
this.document = aNode.ownerDocument;
|
|
||||||
this.window = this.document.defaultView;
|
|
||||||
this._parent = aNode;
|
|
||||||
|
|
||||||
// Create an internal arrowscrollbox container.
|
|
||||||
this._list = this.document.createElement("arrowscrollbox");
|
|
||||||
this._list.className = "breadcrumbs-widget-container";
|
|
||||||
this._list.setAttribute("flex", "1");
|
|
||||||
this._list.setAttribute("orient", "horizontal");
|
|
||||||
this._list.setAttribute("clicktoscroll", "true");
|
|
||||||
this._list.setAttribute("smoothscroll", !!aOptions.smoothScroll);
|
|
||||||
this._list.addEventListener("keydown", e => this.emit("keyDown", e));
|
|
||||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e));
|
|
||||||
this._parent.appendChild(this._list);
|
|
||||||
|
|
||||||
// By default, hide the arrows. We let the arrowscrollbox show them
|
|
||||||
// in case of overflow.
|
|
||||||
this._list._scrollButtonUp.collapsed = true;
|
|
||||||
this._list._scrollButtonDown.collapsed = true;
|
|
||||||
this._list.addEventListener("underflow", this._onUnderflow.bind(this));
|
|
||||||
this._list.addEventListener("overflow", this._onOverflow.bind(this));
|
|
||||||
|
|
||||||
// This widget emits events that can be handled in a MenuContainer.
|
|
||||||
EventEmitter.decorate(this);
|
|
||||||
|
|
||||||
// Delegate some of the associated node's methods to satisfy the interface
|
|
||||||
// required by MenuContainer instances.
|
|
||||||
ViewHelpers.delegateWidgetAttributeMethods(this, aNode);
|
|
||||||
ViewHelpers.delegateWidgetEventMethods(this, aNode);
|
|
||||||
};
|
|
||||||
|
|
||||||
BreadcrumbsWidget.prototype = {
|
|
||||||
/**
|
|
||||||
* Inserts an item in this container at the specified index.
|
|
||||||
*
|
|
||||||
* @param number aIndex
|
|
||||||
* The position in the container intended for this item.
|
|
||||||
* @param Node aContents
|
|
||||||
* The node displayed in the container.
|
|
||||||
* @return Node
|
|
||||||
* The element associated with the displayed item.
|
|
||||||
*/
|
|
||||||
insertItemAt: function(aIndex, aContents) {
|
|
||||||
const list = this._list;
|
|
||||||
const breadcrumb = new Breadcrumb(this, aContents);
|
|
||||||
return list.insertBefore(breadcrumb._target, list.childNodes[aIndex]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the child node in this container situated at the specified index.
|
|
||||||
*
|
|
||||||
* @param number aIndex
|
|
||||||
* The position in the container intended for this item.
|
|
||||||
* @return Node
|
|
||||||
* The element associated with the displayed item.
|
|
||||||
*/
|
|
||||||
getItemAtIndex: function(aIndex) {
|
|
||||||
return this._list.childNodes[aIndex];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified child node from this container.
|
|
||||||
*
|
|
||||||
* @param Node aChild
|
|
||||||
* The element associated with the displayed item.
|
|
||||||
*/
|
|
||||||
removeChild: function(aChild) {
|
|
||||||
this._list.removeChild(aChild);
|
|
||||||
|
|
||||||
if (this._selectedItem == aChild) {
|
|
||||||
this._selectedItem = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all of the child nodes from this container.
|
|
||||||
*/
|
|
||||||
removeAllItems: function() {
|
|
||||||
const list = this._list;
|
|
||||||
|
|
||||||
while (list.hasChildNodes()) {
|
|
||||||
list.firstChild.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._selectedItem = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the currently selected child node in this container.
|
|
||||||
* @return Node
|
|
||||||
*/
|
|
||||||
get selectedItem() {
|
|
||||||
return this._selectedItem;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the currently selected child node in this container.
|
|
||||||
* @param Node aChild
|
|
||||||
*/
|
|
||||||
set selectedItem(aChild) {
|
|
||||||
const childNodes = this._list.childNodes;
|
|
||||||
|
|
||||||
if (!aChild) {
|
|
||||||
this._selectedItem = null;
|
|
||||||
}
|
|
||||||
for (const node of childNodes) {
|
|
||||||
if (node == aChild) {
|
|
||||||
node.setAttribute("checked", "");
|
|
||||||
this._selectedItem = node;
|
|
||||||
} else {
|
|
||||||
node.removeAttribute("checked");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of the named attribute on this container.
|
|
||||||
*
|
|
||||||
* @param string aName
|
|
||||||
* The name of the attribute.
|
|
||||||
* @return string
|
|
||||||
* The current attribute value.
|
|
||||||
*/
|
|
||||||
getAttribute: function(aName) {
|
|
||||||
if (aName == "scrollPosition") {
|
|
||||||
return this._list.scrollPosition;
|
|
||||||
}
|
|
||||||
if (aName == "scrollWidth") {
|
|
||||||
return this._list.scrollWidth;
|
|
||||||
}
|
|
||||||
return this._parent.getAttribute(aName);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the specified element is visible.
|
|
||||||
*
|
|
||||||
* @param Node aElement
|
|
||||||
* The element to make visible.
|
|
||||||
*/
|
|
||||||
ensureElementIsVisible: function(aElement) {
|
|
||||||
if (!aElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeated calls to ensureElementIsVisible would interfere with each other
|
|
||||||
// and may sometimes result in incorrect scroll positions.
|
|
||||||
setNamedTimeout("breadcrumb-select", ENSURE_SELECTION_VISIBLE_DELAY, () => {
|
|
||||||
if (this._list.ensureElementIsVisible) {
|
|
||||||
this._list.ensureElementIsVisible(aElement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The underflow and overflow listener for the arrowscrollbox container.
|
|
||||||
*/
|
|
||||||
_onUnderflow: function({ target }) {
|
|
||||||
if (target != this._list) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
target._scrollButtonUp.collapsed = true;
|
|
||||||
target._scrollButtonDown.collapsed = true;
|
|
||||||
target.removeAttribute("overflows");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The underflow and overflow listener for the arrowscrollbox container.
|
|
||||||
*/
|
|
||||||
_onOverflow: function({ target }) {
|
|
||||||
if (target != this._list) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
target._scrollButtonUp.collapsed = false;
|
|
||||||
target._scrollButtonDown.collapsed = false;
|
|
||||||
target.setAttribute("overflows", "");
|
|
||||||
},
|
|
||||||
|
|
||||||
window: null,
|
|
||||||
document: null,
|
|
||||||
_parent: null,
|
|
||||||
_list: null,
|
|
||||||
_selectedItem: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Breadcrumb constructor for the BreadcrumbsWidget.
|
|
||||||
*
|
|
||||||
* @param BreadcrumbsWidget aWidget
|
|
||||||
* The widget to contain this breadcrumb.
|
|
||||||
* @param Node aContents
|
|
||||||
* The node displayed in the container.
|
|
||||||
*/
|
|
||||||
function Breadcrumb(aWidget, aContents) {
|
|
||||||
this.document = aWidget.document;
|
|
||||||
this.window = aWidget.window;
|
|
||||||
this.ownerView = aWidget;
|
|
||||||
|
|
||||||
this._target = this.document.createElement("hbox");
|
|
||||||
this._target.className = "breadcrumbs-widget-item";
|
|
||||||
this._target.setAttribute("align", "center");
|
|
||||||
this.contents = aContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
Breadcrumb.prototype = {
|
|
||||||
/**
|
|
||||||
* Sets the contents displayed in this item's view.
|
|
||||||
*
|
|
||||||
* @param string | Node aContents
|
|
||||||
* The string or node displayed in the container.
|
|
||||||
*/
|
|
||||||
set contents(aContents) {
|
|
||||||
// If there are already some contents displayed, replace them.
|
|
||||||
if (this._target.hasChildNodes()) {
|
|
||||||
this._target.replaceChild(aContents, this._target.firstChild);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// These are the first contents ever displayed.
|
|
||||||
this._target.appendChild(aContents);
|
|
||||||
},
|
|
||||||
|
|
||||||
window: null,
|
|
||||||
document: null,
|
|
||||||
ownerView: null,
|
|
||||||
_target: null,
|
|
||||||
};
|
|
|
@ -1,247 +0,0 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
||||||
/* vim: set ft=javascript ts=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/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
|
||||||
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list menu widget that attempts to be very fast.
|
|
||||||
*
|
|
||||||
* Note: this widget should be used in tandem with the WidgetMethods in
|
|
||||||
* view-helpers.js.
|
|
||||||
*
|
|
||||||
* @param Node aNode
|
|
||||||
* The element associated with the widget.
|
|
||||||
*/
|
|
||||||
const FastListWidget = module.exports = function FastListWidget(node) {
|
|
||||||
this.document = node.ownerDocument;
|
|
||||||
this.window = this.document.defaultView;
|
|
||||||
this._parent = node;
|
|
||||||
this._fragment = this.document.createDocumentFragment();
|
|
||||||
|
|
||||||
// This is a prototype element that each item added to the list clones.
|
|
||||||
this._templateElement = this.document.createElement("hbox");
|
|
||||||
|
|
||||||
// Create an internal scrollbox container.
|
|
||||||
this._list = this.document.createElement("scrollbox");
|
|
||||||
this._list.className = "fast-list-widget-container theme-body";
|
|
||||||
this._list.setAttribute("flex", "1");
|
|
||||||
this._list.setAttribute("orient", "vertical");
|
|
||||||
this._list.setAttribute("tabindex", "0");
|
|
||||||
this._list.addEventListener("keydown", e => this.emit("keyDown", e));
|
|
||||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e));
|
|
||||||
this._parent.appendChild(this._list);
|
|
||||||
|
|
||||||
this._orderedMenuElementsArray = [];
|
|
||||||
this._itemsByElement = new Map();
|
|
||||||
|
|
||||||
// This widget emits events that can be handled in a MenuContainer.
|
|
||||||
EventEmitter.decorate(this);
|
|
||||||
|
|
||||||
// Delegate some of the associated node's methods to satisfy the interface
|
|
||||||
// required by MenuContainer instances.
|
|
||||||
ViewHelpers.delegateWidgetAttributeMethods(this, node);
|
|
||||||
ViewHelpers.delegateWidgetEventMethods(this, node);
|
|
||||||
};
|
|
||||||
|
|
||||||
FastListWidget.prototype = {
|
|
||||||
/**
|
|
||||||
* Inserts an item in this container at the specified index, optionally
|
|
||||||
* grouping by name.
|
|
||||||
*
|
|
||||||
* @param number aIndex
|
|
||||||
* The position in the container intended for this item.
|
|
||||||
* @param Node aContents
|
|
||||||
* The node to be displayed in the container.
|
|
||||||
* @param Object aAttachment [optional]
|
|
||||||
* Extra data for the user.
|
|
||||||
* @return Node
|
|
||||||
* The element associated with the displayed item.
|
|
||||||
*/
|
|
||||||
insertItemAt: function(index, contents, attachment = {}) {
|
|
||||||
const element = this._templateElement.cloneNode();
|
|
||||||
element.appendChild(contents);
|
|
||||||
|
|
||||||
if (index >= 0) {
|
|
||||||
throw new Error("FastListWidget only supports appending items.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._fragment.appendChild(element);
|
|
||||||
this._orderedMenuElementsArray.push(element);
|
|
||||||
this._itemsByElement.set(element, this);
|
|
||||||
|
|
||||||
return element;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a non-standard widget implementation method. When appending items,
|
|
||||||
* they are queued in a document fragment. This method appends the document
|
|
||||||
* fragment to the dom.
|
|
||||||
*/
|
|
||||||
flush: function() {
|
|
||||||
this._list.appendChild(this._fragment);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all of the child nodes from this container.
|
|
||||||
*/
|
|
||||||
removeAllItems: function() {
|
|
||||||
const list = this._list;
|
|
||||||
|
|
||||||
while (list.hasChildNodes()) {
|
|
||||||
list.firstChild.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._selectedItem = null;
|
|
||||||
|
|
||||||
this._orderedMenuElementsArray.length = 0;
|
|
||||||
this._itemsByElement.clear();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the given item.
|
|
||||||
*/
|
|
||||||
removeChild: function(child) {
|
|
||||||
throw new Error("Not yet implemented");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the currently selected child node in this container.
|
|
||||||
* @return Node
|
|
||||||
*/
|
|
||||||
get selectedItem() {
|
|
||||||
return this._selectedItem;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the currently selected child node in this container.
|
|
||||||
* @param Node child
|
|
||||||
*/
|
|
||||||
set selectedItem(child) {
|
|
||||||
const menuArray = this._orderedMenuElementsArray;
|
|
||||||
|
|
||||||
if (!child) {
|
|
||||||
this._selectedItem = null;
|
|
||||||
}
|
|
||||||
for (const node of menuArray) {
|
|
||||||
if (node == child) {
|
|
||||||
node.classList.add("selected");
|
|
||||||
this._selectedItem = node;
|
|
||||||
} else {
|
|
||||||
node.classList.remove("selected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ensureElementIsVisible(this.selectedItem);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the child node in this container situated at the specified index.
|
|
||||||
*
|
|
||||||
* @param number index
|
|
||||||
* The position in the container intended for this item.
|
|
||||||
* @return Node
|
|
||||||
* The element associated with the displayed item.
|
|
||||||
*/
|
|
||||||
getItemAtIndex: function(index) {
|
|
||||||
return this._orderedMenuElementsArray[index];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new attribute or changes an existing attribute on this container.
|
|
||||||
*
|
|
||||||
* @param string name
|
|
||||||
* The name of the attribute.
|
|
||||||
* @param string value
|
|
||||||
* The desired attribute value.
|
|
||||||
*/
|
|
||||||
setAttribute: function(name, value) {
|
|
||||||
this._parent.setAttribute(name, value);
|
|
||||||
|
|
||||||
if (name == "emptyText") {
|
|
||||||
this._textWhenEmpty = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes an attribute on this container.
|
|
||||||
*
|
|
||||||
* @param string name
|
|
||||||
* The name of the attribute.
|
|
||||||
*/
|
|
||||||
removeAttribute: function(name) {
|
|
||||||
this._parent.removeAttribute(name);
|
|
||||||
|
|
||||||
if (name == "emptyText") {
|
|
||||||
this._removeEmptyText();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the specified element is visible.
|
|
||||||
*
|
|
||||||
* @param Node element
|
|
||||||
* The element to make visible.
|
|
||||||
*/
|
|
||||||
ensureElementIsVisible: function(element) {
|
|
||||||
if (!element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the element is visible but not scrolled horizontally.
|
|
||||||
element.scrollIntoView({ block: "nearest" });
|
|
||||||
this._list.scrollBy(-this._list.clientWidth, 0);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the text displayed in this container when empty.
|
|
||||||
* @param string aValue
|
|
||||||
*/
|
|
||||||
set _textWhenEmpty(value) {
|
|
||||||
if (this._emptyTextNode) {
|
|
||||||
this._emptyTextNode.setAttribute("value", value);
|
|
||||||
}
|
|
||||||
this._emptyTextValue = value;
|
|
||||||
this._showEmptyText();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and appends a label signaling that this container is empty.
|
|
||||||
*/
|
|
||||||
_showEmptyText: function() {
|
|
||||||
if (this._emptyTextNode || !this._emptyTextValue) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const label = this.document.createElement("label");
|
|
||||||
label.className = "plain fast-list-widget-empty-text";
|
|
||||||
label.setAttribute("value", this._emptyTextValue);
|
|
||||||
|
|
||||||
this._parent.insertBefore(label, this._list);
|
|
||||||
this._emptyTextNode = label;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the label signaling that this container is empty.
|
|
||||||
*/
|
|
||||||
_removeEmptyText: function() {
|
|
||||||
if (!this._emptyTextNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._parent.removeChild(this._emptyTextNode);
|
|
||||||
this._emptyTextNode = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
window: null,
|
|
||||||
document: null,
|
|
||||||
_parent: null,
|
|
||||||
_list: null,
|
|
||||||
_selectedItem: null,
|
|
||||||
_orderedMenuElementsArray: null,
|
|
||||||
_itemsByElement: null,
|
|
||||||
_emptyTextNode: null,
|
|
||||||
_emptyTextValue: "",
|
|
||||||
};
|
|
|
@ -11,11 +11,9 @@ DIRS += [
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
'AbstractTreeItem.jsm',
|
'AbstractTreeItem.jsm',
|
||||||
'BarGraphWidget.js',
|
'BarGraphWidget.js',
|
||||||
'BreadcrumbsWidget.jsm',
|
|
||||||
'Chart.js',
|
'Chart.js',
|
||||||
'CubicBezierPresets.js',
|
'CubicBezierPresets.js',
|
||||||
'CubicBezierWidget.js',
|
'CubicBezierWidget.js',
|
||||||
'FastListWidget.js',
|
|
||||||
'FilterWidget.js',
|
'FilterWidget.js',
|
||||||
'FlameGraph.js',
|
'FlameGraph.js',
|
||||||
'Graphs.js',
|
'Graphs.js',
|
||||||
|
|
|
@ -13,12 +13,6 @@
|
||||||
-moz-user-focus: normal;
|
-moz-user-focus: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FastListWidget */
|
|
||||||
|
|
||||||
.fast-list-widget-container {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SideMenuWidget */
|
/* SideMenuWidget */
|
||||||
|
|
||||||
.side-menu-widget-container {
|
.side-menu-widget-container {
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
--focus-cell-border-color: rgba(255,255,255,0.5);
|
--focus-cell-border-color: rgba(255,255,255,0.5);
|
||||||
--row-alt-background-color: rgba(86, 117, 185, 0.15);
|
--row-alt-background-color: rgba(86, 117, 185, 0.15);
|
||||||
--row-hover-background-color: rgba(86, 117, 185, 0.25);
|
--row-hover-background-color: rgba(86, 117, 185, 0.25);
|
||||||
|
--link-color: var(--blue-40);
|
||||||
|
--link-color-active: var(--blue-30);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-light {
|
.theme-light {
|
||||||
|
@ -17,6 +19,8 @@
|
||||||
--focus-cell-border-color: rgba(0,0,0,0.3);
|
--focus-cell-border-color: rgba(0,0,0,0.3);
|
||||||
--row-alt-background-color: rgba(76,158,217,0.1);
|
--row-alt-background-color: rgba(76,158,217,0.1);
|
||||||
--row-hover-background-color: rgba(76,158,217,0.2);
|
--row-hover-background-color: rgba(76,158,217,0.2);
|
||||||
|
--link-color: var(--blue-60);
|
||||||
|
--link-color-active: var(--blue-70);
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body, #app, #memory-tool {
|
html, body, #app, #memory-tool {
|
||||||
|
@ -278,7 +282,7 @@ html, body, #app, #memory-tool {
|
||||||
/**
|
/**
|
||||||
* Flex: contains a .heap-view-panel which needs to fill out all the
|
* Flex: contains a .heap-view-panel which needs to fill out all the
|
||||||
* available space, horizontally and vertically.
|
* available space, horizontally and vertically.
|
||||||
*/;
|
*/
|
||||||
display: flex;
|
display: flex;
|
||||||
/**
|
/**
|
||||||
* Flexing to fill out remaining horizontal space. The preceeding sibling
|
* Flexing to fill out remaining horizontal space. The preceeding sibling
|
||||||
|
@ -550,6 +554,19 @@ html, body, #app, #memory-tool {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.load-more-link {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-more-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-more-link:active {
|
||||||
|
color: var(--link-color-active);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heap tree errors.
|
* Heap tree errors.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -963,12 +963,18 @@ body {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background: url("chrome://devtools/skin/images/arrow.svg") no-repeat center;
|
background: url("chrome://devtools/skin/images/arrow.svg") no-repeat center;
|
||||||
background-size: 10px;
|
background-size: 10px;
|
||||||
|
transform: rotate(-90deg);
|
||||||
/* Needed for alignment */
|
/* Needed for alignment */
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
-moz-context-properties: fill;
|
-moz-context-properties: fill;
|
||||||
fill: var(--theme-icon-dimmed-color);
|
fill: var(--theme-icon-dimmed-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.webconsole-app .tree .arrow.expanded,
|
||||||
|
.webconsole-app .object-inspector .tree-node .arrow.expanded {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Sidebar */
|
/* Sidebar */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -101,21 +101,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FastListWidget */
|
|
||||||
|
|
||||||
.fast-list-widget-container {
|
|
||||||
/* Hack: force hardware acceleration */
|
|
||||||
transform: translateZ(1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.fast-list-widget-empty-text {
|
|
||||||
padding: 4px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fast-list-widget-empty-text {
|
|
||||||
color: var(--theme-body-color-alt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SideMenuWidget */
|
/* SideMenuWidget */
|
||||||
|
|
||||||
.side-menu-widget-container {
|
.side-menu-widget-container {
|
||||||
|
|
|
@ -82,6 +82,21 @@ async function performTests() {
|
||||||
is(getL10NContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
is(getL10NContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
||||||
"The context menu has the correct edit menu items");
|
"The context menu has the correct edit menu items");
|
||||||
|
|
||||||
|
const node = hud.jsterm.inputNode || hud.jsterm.node;
|
||||||
|
const inputContainer = node.closest(".jsterm-input-container");
|
||||||
|
await openContextMenu(hud, inputContainer);
|
||||||
|
|
||||||
|
expectedContextMenu = [
|
||||||
|
"#editmenu-undo (editmenu-undo) [disabled]",
|
||||||
|
"#editmenu-cut (editmenu-cut)",
|
||||||
|
"#editmenu-copy (editmenu-copy)",
|
||||||
|
"#editmenu-paste (editmenu-paste)",
|
||||||
|
"#editmenu-delete (editmenu-delete) [disabled]",
|
||||||
|
"#editmenu-selectAll (editmenu-select-all) [disabled]",
|
||||||
|
];
|
||||||
|
is(getL10NContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
||||||
|
"The context menu has the required elements");
|
||||||
|
|
||||||
await hideContextMenu(hud);
|
await hideContextMenu(hud);
|
||||||
// Close the browser console.
|
// Close the browser console.
|
||||||
await HUDService.toggleBrowserConsole();
|
await HUDService.toggleBrowserConsole();
|
||||||
|
|
|
@ -23,18 +23,29 @@ add_task(async function() {
|
||||||
info("Test Copy URL menu item for text log");
|
info("Test Copy URL menu item for text log");
|
||||||
|
|
||||||
info("Logging a text message in the content window");
|
info("Logging a text message in the content window");
|
||||||
const onLogMessage = waitForMessage(hud, "simple text message");
|
const onLogMessage = waitForMessage(hud, "stringLog");
|
||||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
||||||
content.wrappedJSObject.console.log("simple text message");
|
content.wrappedJSObject.stringLog();
|
||||||
});
|
});
|
||||||
let message = await onLogMessage;
|
let message = await onLogMessage;
|
||||||
ok(message, "Text log found in the console");
|
ok(message, "Text log found in the console");
|
||||||
|
|
||||||
info("Open and check the context menu for the logged text message");
|
info("Open and check the context menu for the logged text message");
|
||||||
let menuPopup = await openContextMenu(hud, message.node);
|
let menuPopup = await openContextMenu(hud, message.node);
|
||||||
|
|
||||||
let copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
let copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
||||||
ok(!copyURLItem, "Copy URL menu item is hidden for a simple text message");
|
ok(!copyURLItem, "Copy URL menu item is hidden for a simple text message");
|
||||||
|
|
||||||
|
info("Open and check the context menu for the logged text message");
|
||||||
|
const locationElement = message.node.querySelector(".frame-link-source-inner");
|
||||||
|
menuPopup = await openContextMenu(hud, locationElement);
|
||||||
|
copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
||||||
|
ok(copyURLItem, "The Copy Link Location entry is displayed");
|
||||||
|
|
||||||
|
info("Click on Copy URL menu item and wait for clipboard to be updated");
|
||||||
|
await waitForClipboardPromise(() => copyURLItem.click(), TEST_URI);
|
||||||
|
ok(true, "Expected text was copied to the clipboard.");
|
||||||
|
|
||||||
await hideContextMenu(hud);
|
await hideContextMenu(hud);
|
||||||
hud.ui.clearOutput();
|
hud.ui.clearOutput();
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,12 @@ async function testViewSource(hud, toolbox, text) {
|
||||||
info("style editor window focused");
|
info("style editor window focused");
|
||||||
const href = frameLinkNode.getAttribute("data-url");
|
const href = frameLinkNode.getAttribute("data-url");
|
||||||
const line = frameLinkNode.getAttribute("data-line");
|
const line = frameLinkNode.getAttribute("data-line");
|
||||||
|
const column = frameLinkNode.getAttribute("data-column");
|
||||||
ok(line, "found source line");
|
ok(line, "found source line");
|
||||||
|
|
||||||
const editor = getEditorForHref(panel.UI, href);
|
const editor = getEditorForHref(panel.UI, href);
|
||||||
ok(editor, "found style editor for " + href);
|
ok(editor, "found style editor for " + href);
|
||||||
await performLineCheck(panel.UI, editor, line - 1);
|
await checkCursorPosition(panel.UI, editor, line - 1, column - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onStyleEditorReady(panel) {
|
async function onStyleEditorReady(panel) {
|
||||||
|
@ -72,13 +73,15 @@ function getEditorForHref(styleEditorUI, href) {
|
||||||
return foundEditor;
|
return foundEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function performLineCheck(styleEditorUI, editor, line) {
|
async function checkCursorPosition(styleEditorUI, editor, line, column) {
|
||||||
info("wait for source editor to load");
|
info("wait for source editor to load");
|
||||||
// Get out of the styleeditor-selected event loop.
|
// Get out of the styleeditor-selected event loop.
|
||||||
await waitForTick();
|
await waitForTick();
|
||||||
|
|
||||||
is(editor.sourceEditor.getCursor().line, line,
|
is(editor.sourceEditor.getCursor().line, line,
|
||||||
"correct line is selected");
|
"correct line is selected");
|
||||||
|
is(editor.sourceEditor.getCursor().ch, column,
|
||||||
|
"correct column is selected");
|
||||||
is(styleEditorUI.selectedStyleSheetIndex, editor.styleSheet.styleSheetIndex,
|
is(styleEditorUI.selectedStyleSheetIndex, editor.styleSheet.styleSheetIndex,
|
||||||
"correct stylesheet is selected in the editor");
|
"correct stylesheet is selected in the editor");
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ function createContextMenu(webConsoleUI, parentNode, {
|
||||||
rootActorId,
|
rootActorId,
|
||||||
executionPoint,
|
executionPoint,
|
||||||
toolbox,
|
toolbox,
|
||||||
|
url,
|
||||||
}) {
|
}) {
|
||||||
const win = parentNode.ownerDocument.defaultView;
|
const win = parentNode.ownerDocument.defaultView;
|
||||||
const selection = win.getSelection();
|
const selection = win.getSelection();
|
||||||
|
@ -207,6 +208,15 @@ function createContextMenu(webConsoleUI, parentNode, {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
id: "console-menu-copy-url",
|
||||||
|
label: l10n.getStr("webconsole.menu.copyURL.label"),
|
||||||
|
accesskey: l10n.getStr("webconsole.menu.copyURL.accesskey"),
|
||||||
|
click: () => clipboardHelper.copyString(url),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,9 @@ class WebConsoleWrapper {
|
||||||
const messageEl = target.closest(".message");
|
const messageEl = target.closest(".message");
|
||||||
const clipboardText = getElementText(messageEl);
|
const clipboardText = getElementText(messageEl);
|
||||||
|
|
||||||
|
const linkEl = target.closest("a[href]");
|
||||||
|
const url = linkEl && linkEl.href;
|
||||||
|
|
||||||
const messageVariable = target.closest(".objectBox");
|
const messageVariable = target.closest(".objectBox");
|
||||||
// Ensure that console.group and console.groupCollapsed commands are not captured
|
// Ensure that console.group and console.groupCollapsed commands are not captured
|
||||||
const variableText = (messageVariable
|
const variableText = (messageVariable
|
||||||
|
@ -233,6 +236,7 @@ class WebConsoleWrapper {
|
||||||
rootActorId,
|
rootActorId,
|
||||||
executionPoint,
|
executionPoint,
|
||||||
toolbox: this.toolbox,
|
toolbox: this.toolbox,
|
||||||
|
url,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Emit the "menu-open" event for testing.
|
// Emit the "menu-open" event for testing.
|
||||||
|
@ -279,7 +283,8 @@ class WebConsoleWrapper {
|
||||||
}),
|
}),
|
||||||
onViewSourceInStyleEditor: frame => this.toolbox.viewSourceInStyleEditor(
|
onViewSourceInStyleEditor: frame => this.toolbox.viewSourceInStyleEditor(
|
||||||
frame.url,
|
frame.url,
|
||||||
frame.line
|
frame.line,
|
||||||
|
frame.column
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.telemetry.recordEvent("jump_to_source", "webconsole",
|
this.telemetry.recordEvent("jump_to_source", "webconsole",
|
||||||
null, { "session_id": this.toolbox.sessionId }
|
null, { "session_id": this.toolbox.sessionId }
|
||||||
|
|
|
@ -692,27 +692,6 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates through all nodes below a given rootNode (optionally also in
|
|
||||||
* nested frames) and finds all existing animation players.
|
|
||||||
* @param {DOMNode} rootNode The root node to start iterating at. Animation
|
|
||||||
* players will *not* be reported for this node.
|
|
||||||
* @param {Boolean} traverseFrames Whether we should iterate through nested
|
|
||||||
* frames too.
|
|
||||||
* @return {Array} An array of AnimationPlayer objects.
|
|
||||||
*/
|
|
||||||
getAllAnimations: function(rootNode, traverseFrames) {
|
|
||||||
if (!traverseFrames) {
|
|
||||||
return rootNode.getAnimations({subtree: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
let animations = [];
|
|
||||||
for (const {document} of this.targetActor.windows) {
|
|
||||||
animations = [...animations, ...document.getAnimations({subtree: true})];
|
|
||||||
}
|
|
||||||
return animations;
|
|
||||||
},
|
|
||||||
|
|
||||||
onWillNavigate: function({isTopLevel}) {
|
onWillNavigate: function({isTopLevel}) {
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
this.stopAnimationPlayerUpdates();
|
this.stopAnimationPlayerUpdates();
|
||||||
|
|
|
@ -3871,7 +3871,7 @@ Element* Document::GetRootElement() const {
|
||||||
: GetRootElementInternal();
|
: GetRootElementInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContent* Document::GetUnfocusedKeyEventTarget() { return GetRootElement(); }
|
Element* Document::GetUnfocusedKeyEventTarget() { return GetRootElement(); }
|
||||||
|
|
||||||
Element* Document::GetRootElementInternal() const {
|
Element* Document::GetRootElementInternal() const {
|
||||||
// We invoke GetRootElement() immediately before the servo traversal, so we
|
// We invoke GetRootElement() immediately before the servo traversal, so we
|
||||||
|
|
|
@ -1342,7 +1342,7 @@ class Document : public nsINode,
|
||||||
* Gets the event target to dispatch key events to if there is no focused
|
* Gets the event target to dispatch key events to if there is no focused
|
||||||
* content in the document.
|
* content in the document.
|
||||||
*/
|
*/
|
||||||
virtual nsIContent* GetUnfocusedKeyEventTarget();
|
virtual Element* GetUnfocusedKeyEventTarget();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve information about the viewport as a data structure.
|
* Retrieve information about the viewport as a data structure.
|
||||||
|
|
|
@ -7509,7 +7509,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||||
|
|
||||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||||
item->flavor() = flavorStr;
|
item->flavor() = flavorStr;
|
||||||
item->data() = dataAsShmem;
|
item->data() = std::move(dataAsShmem);
|
||||||
} else if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
|
} else if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
|
||||||
// Images to be pasted on the clipboard are nsIInputStreams
|
// Images to be pasted on the clipboard are nsIInputStreams
|
||||||
nsCString imageData;
|
nsCString imageData;
|
||||||
|
@ -7522,7 +7522,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||||
|
|
||||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||||
item->flavor() = flavorStr;
|
item->flavor() = flavorStr;
|
||||||
item->data() = imageDataShmem;
|
item->data() = std::move(imageDataShmem);
|
||||||
} else if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
|
} else if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
|
||||||
// Images to be placed on the clipboard are imgIContainers.
|
// Images to be placed on the clipboard are imgIContainers.
|
||||||
RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
|
RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
|
||||||
|
@ -7550,7 +7550,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||||
item->flavor() = flavorStr;
|
item->flavor() = flavorStr;
|
||||||
// Turn item->data() into an nsCString prior to accessing it.
|
// Turn item->data() into an nsCString prior to accessing it.
|
||||||
item->data() = surfaceData.ref();
|
item->data() = std::move(surfaceData.ref());
|
||||||
|
|
||||||
IPCDataTransferImage& imageDetails = item->imageDetails();
|
IPCDataTransferImage& imageDetails = item->imageDetails();
|
||||||
mozilla::gfx::IntSize size = dataSurface->GetSize();
|
mozilla::gfx::IntSize size = dataSurface->GetSize();
|
||||||
|
@ -7581,7 +7581,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||||
IPCDataTransferItem* item =
|
IPCDataTransferItem* item =
|
||||||
aIPCDataTransfer->items().AppendElement();
|
aIPCDataTransfer->items().AppendElement();
|
||||||
item->flavor() = type;
|
item->flavor() = type;
|
||||||
item->data() = dataAsShmem;
|
item->data() = std::move(dataAsShmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -396,11 +396,21 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
||||||
loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently we query the CSP from the principal, but after
|
// Expanded Principals override the CSP of the document, hence we first check
|
||||||
// Bug 1529877 we should query the CSP from within GetURL and
|
// if the triggeringPrincipal overrides the document's principal. If so, let's
|
||||||
// store it as a member, similar to mTriggeringPrincipal.
|
// query the CSP from that Principal, otherwise we use the document's CSP.
|
||||||
|
// Note that even after Bug 965637, Expanded Principals will hold their own
|
||||||
|
// CSP.
|
||||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||||
loadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
|
if (BasePrincipal::Cast(loadState->TriggeringPrincipal())
|
||||||
|
->OverridesCSP(mOwnerContent->NodePrincipal())) {
|
||||||
|
loadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
|
||||||
|
} else {
|
||||||
|
// Currently the NodePrincipal holds the CSP for a document. After
|
||||||
|
// Bug 965637 we can query the CSP from mOwnerContent->OwnerDoc()
|
||||||
|
// instead of mOwnerContent->NodePrincipal().
|
||||||
|
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||||
|
}
|
||||||
loadState->SetCsp(csp);
|
loadState->SetCsp(csp);
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> referrer;
|
nsCOMPtr<nsIURI> referrer;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<iframe src="http://mochi.test:8888/tests/dom/base/test/iframe_shared_compartment2b.html">
|
||||||
|
</iframe>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<script>
|
||||||
|
window.onload = () => window.parent.parent.go(this);
|
||||||
|
</script>
|
|
@ -230,6 +230,8 @@ support-files =
|
||||||
iframe7_bug431701.xml
|
iframe7_bug431701.xml
|
||||||
iframe1_bug426646.html
|
iframe1_bug426646.html
|
||||||
iframe2_bug426646.html
|
iframe2_bug426646.html
|
||||||
|
iframe_shared_compartment2a.html
|
||||||
|
iframe_shared_compartment2b.html
|
||||||
file1_setting_opener.html
|
file1_setting_opener.html
|
||||||
file2_setting_opener.html
|
file2_setting_opener.html
|
||||||
file3_setting_opener.html
|
file3_setting_opener.html
|
||||||
|
@ -791,6 +793,8 @@ skip-if = debug == false
|
||||||
[test_settimeout_inner.html]
|
[test_settimeout_inner.html]
|
||||||
[test_setTimeoutWith0.html]
|
[test_setTimeoutWith0.html]
|
||||||
[test_setting_opener.html]
|
[test_setting_opener.html]
|
||||||
|
[test_shared_compartment1.html]
|
||||||
|
[test_shared_compartment2.html]
|
||||||
[test_style_cssText.html]
|
[test_style_cssText.html]
|
||||||
[test_text_wholeText.html]
|
[test_text_wholeText.html]
|
||||||
[test_textnode_normalize_in_selection.html]
|
[test_textnode_normalize_in_selection.html]
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1530608
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 1530608</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 1530608 **/
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var Cu = SpecialPowers.Cu;
|
||||||
|
var isSameCompartment = Cu.getJSTestingFunctions().isSameCompartment;
|
||||||
|
|
||||||
|
var testsDone = 0;
|
||||||
|
function finishIfDone() {
|
||||||
|
testsDone++;
|
||||||
|
if (testsDone === 4) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 1: same-origin iframe.
|
||||||
|
function testFrame1() {
|
||||||
|
var frameWin = document.getElementById("frame1").contentWindow;
|
||||||
|
ok(isSameCompartment(window, frameWin),
|
||||||
|
"Same-origin iframe must be same-compartment");
|
||||||
|
finishIfDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 2: cross-origin iframe.
|
||||||
|
function testFrame2() {
|
||||||
|
var frameWin = document.getElementById("frame2").contentWindow;
|
||||||
|
ok(!isSameCompartment(window, frameWin),
|
||||||
|
"Cross-origin iframe must be cross-compartment");
|
||||||
|
finishIfDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 3: same-site, cross-origin iframe.
|
||||||
|
function testFrame3() {
|
||||||
|
var frame = document.getElementById("frame3");
|
||||||
|
ok(!isSameCompartment(window, frame.contentWindow),
|
||||||
|
"Same-site cross-origin iframe must be cross-compartment");
|
||||||
|
|
||||||
|
// Now load a same-origin page in this iframe.
|
||||||
|
frame.onload = function() {
|
||||||
|
ok(isSameCompartment(window, frame.contentWindow),
|
||||||
|
"Frame must be same-compartment now");
|
||||||
|
finishIfDone();
|
||||||
|
};
|
||||||
|
frame.src = "file_empty.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 4: dynamically created iframe.
|
||||||
|
addLoadEvent(function() {
|
||||||
|
var frame = document.createElement("iframe");
|
||||||
|
document.body.appendChild(frame);
|
||||||
|
ok(isSameCompartment(window, frame.contentWindow),
|
||||||
|
"Newly created iframe must be same-compartment");
|
||||||
|
finishIfDone();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1530608">Mozilla Bug 1530608</a>
|
||||||
|
|
||||||
|
<iframe id="frame1" onload="testFrame1()" src="file_empty.html"></iframe>
|
||||||
|
<iframe id="frame2" onload="testFrame2()" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe>
|
||||||
|
<iframe id="frame3" onload="testFrame3()" src="http://test1.mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1530608
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 1530608</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 1530608 **/
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
// We have the following origins:
|
||||||
|
//
|
||||||
|
// 1: this page: mochi.test:8888
|
||||||
|
// 2: iframe: example.org
|
||||||
|
// 3: inner iframe: mochi.test:8888
|
||||||
|
//
|
||||||
|
// Test that 1 and 2 are cross-compartment (because cross-origin), but 1 and 3
|
||||||
|
// are same-compartment.
|
||||||
|
|
||||||
|
function go(innerWin) {
|
||||||
|
var Cu = SpecialPowers.Cu;
|
||||||
|
var isSameCompartment = Cu.getJSTestingFunctions().isSameCompartment;
|
||||||
|
|
||||||
|
var frame = document.getElementById("frame");
|
||||||
|
ok(!isSameCompartment(window, frame.contentWindow),
|
||||||
|
"Cross-origin iframe must be cross-compartment");
|
||||||
|
|
||||||
|
ok(isSameCompartment(window, innerWin),
|
||||||
|
"Same-origin inner iframe must be same-compartment");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1530608">Mozilla Bug 1530608</a>
|
||||||
|
|
||||||
|
<iframe id="frame" src="http://example.org/tests/dom/base/test/iframe_shared_compartment2a.html"></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3737,6 +3737,7 @@ void HTMLMediaElement::DispatchEventsWhenPlayWasNotAllowed() {
|
||||||
OwnerDoc()->MaybeNotifyAutoplayBlocked();
|
OwnerDoc()->MaybeNotifyAutoplayBlocked();
|
||||||
ReportToConsole(nsIScriptError::warningFlag, "BlockAutoplayError");
|
ReportToConsole(nsIScriptError::warningFlag, "BlockAutoplayError");
|
||||||
mHasPlayEverBeenBlocked = true;
|
mHasPlayEverBeenBlocked = true;
|
||||||
|
mHasEverBeenBlockedForAutoplay = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLMediaElement::PlayInternal(bool aHandlingUserInput) {
|
void HTMLMediaElement::PlayInternal(bool aHandlingUserInput) {
|
||||||
|
@ -5985,6 +5986,14 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement,
|
||||||
mEventDeliveryPaused = false;
|
mEventDeliveryPaused = false;
|
||||||
DispatchPendingMediaEvents();
|
DispatchPendingMediaEvents();
|
||||||
}
|
}
|
||||||
|
// If the media element has been blocked and isn't still allowed to play
|
||||||
|
// when it comes back from the bfcache, we would notify front end to show
|
||||||
|
// the blocking icon in order to inform user that the site is still being
|
||||||
|
// blocked.
|
||||||
|
if (mHasEverBeenBlockedForAutoplay &&
|
||||||
|
!AutoplayPolicy::IsAllowedToPlay(*this)) {
|
||||||
|
OwnerDoc()->MaybeNotifyAutoplayBlocked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1669,6 +1669,11 @@ class HTMLMediaElement : public nsGenericHTMLElement,
|
||||||
// audio.
|
// audio.
|
||||||
MozPromiseHolder<GenericNonExclusivePromise> mAllowedToPlayPromise;
|
MozPromiseHolder<GenericNonExclusivePromise> mAllowedToPlayPromise;
|
||||||
|
|
||||||
|
// True if media has ever been blocked for autoplay, it's used to notify front
|
||||||
|
// end to show the correct blocking icon when the document goes back from
|
||||||
|
// bfcache.
|
||||||
|
bool mHasEverBeenBlockedForAutoplay = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Helper class to measure times for playback telemetry stats
|
// Helper class to measure times for playback telemetry stats
|
||||||
class TimeDurationAccumulator {
|
class TimeDurationAccumulator {
|
||||||
|
|
|
@ -755,7 +755,7 @@ void nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContent* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
|
Element* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
|
||||||
if (nsGenericHTMLElement* body = GetBody()) {
|
if (nsGenericHTMLElement* body = GetBody()) {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
|
|
||||||
virtual bool IsWriting() override { return mWriteLevel != uint32_t(0); }
|
virtual bool IsWriting() override { return mWriteLevel != uint32_t(0); }
|
||||||
|
|
||||||
virtual nsIContent* GetUnfocusedKeyEventTarget() override;
|
virtual Element* GetUnfocusedKeyEventTarget() override;
|
||||||
|
|
||||||
nsContentList* GetExistingForms() const { return mForms; }
|
nsContentList* GetExistingForms() const { return mForms; }
|
||||||
|
|
||||||
|
|
|
@ -2018,7 +2018,7 @@ bool ContentChild::DeallocPPSMContentDownloaderChild(
|
||||||
|
|
||||||
PExternalHelperAppChild* ContentChild::AllocPExternalHelperAppChild(
|
PExternalHelperAppChild* ContentChild::AllocPExternalHelperAppChild(
|
||||||
const OptionalURIParams& uri,
|
const OptionalURIParams& uri,
|
||||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||||
const uint32_t& aContentDispositionHint,
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
|
@ -3555,7 +3555,7 @@ mozilla::ipc::IPCResult ContentChild::RecvSaveRecording(
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
|
mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
|
||||||
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
|
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
|
||||||
const OptionalLoadInfoArgs& aLoadInfo, const uint64_t& aChannelId,
|
const Maybe<LoadInfoArgs>& aLoadInfo, const uint64_t& aChannelId,
|
||||||
nsIURI* aOriginalURI, const uint64_t& aIdentifier) {
|
nsIURI* aOriginalURI, const uint64_t& aIdentifier) {
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
|
|
|
@ -280,7 +280,7 @@ class ContentChild final : public PContentChild,
|
||||||
|
|
||||||
PExternalHelperAppChild* AllocPExternalHelperAppChild(
|
PExternalHelperAppChild* AllocPExternalHelperAppChild(
|
||||||
const OptionalURIParams& uri,
|
const OptionalURIParams& uri,
|
||||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||||
const uint32_t& aContentDispositionHint,
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
|
@ -680,9 +680,8 @@ class ContentChild final : public PContentChild,
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvCrossProcessRedirect(
|
mozilla::ipc::IPCResult RecvCrossProcessRedirect(
|
||||||
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
|
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
|
||||||
const OptionalLoadInfoArgs& aLoadInfoForwarder,
|
const Maybe<LoadInfoArgs>& aLoadInfoForwarder, const uint64_t& aChannelId,
|
||||||
const uint64_t& aChannelId, nsIURI* aOriginalURI,
|
nsIURI* aOriginalURI, const uint64_t& aIdentifier);
|
||||||
const uint64_t& aIdentifier);
|
|
||||||
|
|
||||||
#ifdef NIGHTLY_BUILD
|
#ifdef NIGHTLY_BUILD
|
||||||
// Fetch the current number of pending input events.
|
// Fetch the current number of pending input events.
|
||||||
|
|
|
@ -3632,7 +3632,7 @@ bool ContentParent::DeallocPPSMContentDownloaderParent(
|
||||||
|
|
||||||
PExternalHelperAppParent* ContentParent::AllocPExternalHelperAppParent(
|
PExternalHelperAppParent* ContentParent::AllocPExternalHelperAppParent(
|
||||||
const OptionalURIParams& uri,
|
const OptionalURIParams& uri,
|
||||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||||
const uint32_t& aContentDispositionHint,
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
|
@ -3655,8 +3655,9 @@ bool ContentParent::DeallocPExternalHelperAppParent(
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentParent::RecvPExternalHelperAppConstructor(
|
mozilla::ipc::IPCResult ContentParent::RecvPExternalHelperAppConstructor(
|
||||||
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
||||||
const OptionalLoadInfoArgs& loadInfoArgs, const nsCString& aMimeContentType,
|
const Maybe<LoadInfoArgs>& loadInfoArgs, const nsCString& aMimeContentType,
|
||||||
const nsCString& aContentDisposition, const uint32_t& aContentDispositionHint,
|
const nsCString& aContentDisposition,
|
||||||
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
const int64_t& aContentLength, const bool& aWasFileChannel,
|
const int64_t& aContentLength, const bool& aWasFileChannel,
|
||||||
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) {
|
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) {
|
||||||
|
|
|
@ -876,7 +876,7 @@ class ContentParent final : public PContentParent,
|
||||||
|
|
||||||
PExternalHelperAppParent* AllocPExternalHelperAppParent(
|
PExternalHelperAppParent* AllocPExternalHelperAppParent(
|
||||||
const OptionalURIParams& aUri,
|
const OptionalURIParams& aUri,
|
||||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||||
const uint32_t& aContentDispositionHint,
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
|
@ -887,8 +887,9 @@ class ContentParent final : public PContentParent,
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvPExternalHelperAppConstructor(
|
mozilla::ipc::IPCResult RecvPExternalHelperAppConstructor(
|
||||||
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
||||||
const OptionalLoadInfoArgs& loadInfoArgs, const nsCString& aMimeContentType,
|
const Maybe<LoadInfoArgs>& loadInfoArgs,
|
||||||
const nsCString& aContentDisposition, const uint32_t& aContentDispositionHint,
|
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||||
|
const uint32_t& aContentDispositionHint,
|
||||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||||
const int64_t& aContentLength, const bool& aWasFileChannel,
|
const int64_t& aContentLength, const bool& aWasFileChannel,
|
||||||
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) override;
|
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) override;
|
||||||
|
|
|
@ -773,7 +773,7 @@ child:
|
||||||
async CrossProcessRedirect(uint32_t aRegistrarId,
|
async CrossProcessRedirect(uint32_t aRegistrarId,
|
||||||
nsIURI aURI,
|
nsIURI aURI,
|
||||||
uint32_t aNewLoadFlags,
|
uint32_t aNewLoadFlags,
|
||||||
OptionalLoadInfoArgs aLoadInfo,
|
LoadInfoArgs? aLoadInfo,
|
||||||
uint64_t aChannelId,
|
uint64_t aChannelId,
|
||||||
nsIURI aOriginalURI,
|
nsIURI aOriginalURI,
|
||||||
uint64_t aIdentifier);
|
uint64_t aIdentifier);
|
||||||
|
@ -901,7 +901,7 @@ parent:
|
||||||
async PPSMContentDownloader(uint32_t aCertType);
|
async PPSMContentDownloader(uint32_t aCertType);
|
||||||
|
|
||||||
async PExternalHelperApp(OptionalURIParams uri,
|
async PExternalHelperApp(OptionalURIParams uri,
|
||||||
OptionalLoadInfoArgs loadInfoArgs,
|
LoadInfoArgs? loadInfoArgs,
|
||||||
nsCString aMimeContentType,
|
nsCString aMimeContentType,
|
||||||
nsCString aContentDisposition,
|
nsCString aContentDisposition,
|
||||||
uint32_t aContentDispositionHint,
|
uint32_t aContentDispositionHint,
|
||||||
|
|
|
@ -671,7 +671,7 @@ mozilla::ipc::IPCResult ChromiumCDMChild::RecvDecrypt(
|
||||||
// Success! Return the decrypted sample to parent.
|
// Success! Return the decrypted sample to parent.
|
||||||
MOZ_ASSERT(!HasShmemOfSize(outputShmemSize));
|
MOZ_ASSERT(!HasShmemOfSize(outputShmemSize));
|
||||||
ipc::Shmem shmem = buffer->ExtractShmem();
|
ipc::Shmem shmem = buffer->ExtractShmem();
|
||||||
if (SendDecrypted(aId, cdm::kSuccess, shmem)) {
|
if (SendDecrypted(aId, cdm::kSuccess, std::move(shmem))) {
|
||||||
// No need to deallocate the output shmem; it should have been returned
|
// No need to deallocate the output shmem; it should have been returned
|
||||||
// to the content process.
|
// to the content process.
|
||||||
autoDeallocateOutputShmem.release();
|
autoDeallocateOutputShmem.release();
|
||||||
|
@ -820,7 +820,7 @@ void ChromiumCDMChild::ReturnOutput(WidevineVideoFrame& aFrame) {
|
||||||
CDMBuffer* base = reinterpret_cast<CDMBuffer*>(aFrame.FrameBuffer());
|
CDMBuffer* base = reinterpret_cast<CDMBuffer*>(aFrame.FrameBuffer());
|
||||||
if (base->AsShmemBuffer()) {
|
if (base->AsShmemBuffer()) {
|
||||||
ipc::Shmem shmem = base->AsShmemBuffer()->ExtractShmem();
|
ipc::Shmem shmem = base->AsShmemBuffer()->ExtractShmem();
|
||||||
Unused << SendDecodedShmem(output, shmem);
|
Unused << SendDecodedShmem(output, std::move(shmem));
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(base->AsArrayBuffer());
|
MOZ_ASSERT(base->AsArrayBuffer());
|
||||||
Unused << SendDecodedData(output, base->AsArrayBuffer()->ExtractBuffer());
|
Unused << SendDecodedData(output, base->AsArrayBuffer()->ExtractBuffer());
|
||||||
|
|
|
@ -270,7 +270,7 @@ bool ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer,
|
||||||
? crypto.mIV
|
? crypto.mIV
|
||||||
: crypto.mConstantIV;
|
: crypto.mConstantIV;
|
||||||
aBuffer = gmp::CDMInputBuffer(
|
aBuffer = gmp::CDMInputBuffer(
|
||||||
shmem, crypto.mKeyId, iv, aSample->mTime.ToMicroseconds(),
|
std::move(shmem), crypto.mKeyId, iv, aSample->mTime.ToMicroseconds(),
|
||||||
aSample->mDuration.ToMicroseconds(), crypto.mPlainSizes,
|
aSample->mDuration.ToMicroseconds(), crypto.mPlainSizes,
|
||||||
crypto.mEncryptedSizes, crypto.mCryptByteBlock, crypto.mSkipByteBlock,
|
crypto.mEncryptedSizes, crypto.mCryptByteBlock, crypto.mSkipByteBlock,
|
||||||
encryptionScheme);
|
encryptionScheme);
|
||||||
|
@ -291,7 +291,7 @@ bool ChromiumCDMParent::SendBufferToCDM(uint32_t aSizeInBytes) {
|
||||||
if (!AllocShmem(aSizeInBytes, Shmem::SharedMemory::TYPE_BASIC, &shmem)) {
|
if (!AllocShmem(aSizeInBytes, Shmem::SharedMemory::TYPE_BASIC, &shmem)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SendGiveBuffer(shmem)) {
|
if (!SendGiveBuffer(std::move(shmem))) {
|
||||||
DeallocShmem(shmem);
|
DeallocShmem(shmem);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -713,7 +713,7 @@ ipc::IPCResult ChromiumCDMParent::RecvDecodedShmem(const CDMVideoFrame& aFrame,
|
||||||
|
|
||||||
// Return the shmem to the CDM so the shmem can be reused to send us
|
// Return the shmem to the CDM so the shmem can be reused to send us
|
||||||
// another frame.
|
// another frame.
|
||||||
if (!SendGiveBuffer(aShmem)) {
|
if (!SendGiveBuffer(std::move(aShmem))) {
|
||||||
mDecodePromise.RejectIfExists(
|
mDecodePromise.RejectIfExists(
|
||||||
MediaResult(NS_ERROR_OUT_OF_MEMORY,
|
MediaResult(NS_ERROR_OUT_OF_MEMORY,
|
||||||
RESULT_DETAIL("Can't return shmem to CDM process")),
|
RESULT_DETAIL("Can't return shmem to CDM process")),
|
||||||
|
|
|
@ -68,7 +68,7 @@ bool GMPSharedMemManager::MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass,
|
||||||
// XXX This works; there are better pool algorithms. We need to avoid
|
// XXX This works; there are better pool algorithms. We need to avoid
|
||||||
// "falling off a cliff" with too low a number
|
// "falling off a cliff" with too low a number
|
||||||
if (GetGmpFreelist(aClass).Length() > 10) {
|
if (GetGmpFreelist(aClass).Length() > 10) {
|
||||||
Dealloc(GetGmpFreelist(aClass)[0]);
|
Dealloc(std::move(GetGmpFreelist(aClass)[0]));
|
||||||
GetGmpFreelist(aClass).RemoveElementAt(0);
|
GetGmpFreelist(aClass).RemoveElementAt(0);
|
||||||
// The allocation numbers will be fubar on the Child!
|
// The allocation numbers will be fubar on the Child!
|
||||||
mData->mGmpAllocated[aClass]--;
|
mData->mGmpAllocated[aClass]--;
|
||||||
|
|
|
@ -68,7 +68,7 @@ class GMPSharedMemManager {
|
||||||
virtual bool Alloc(size_t aSize,
|
virtual bool Alloc(size_t aSize,
|
||||||
ipc::Shmem::SharedMemory::SharedMemoryType aType,
|
ipc::Shmem::SharedMemory::SharedMemoryType aType,
|
||||||
ipc::Shmem* aMem) = 0;
|
ipc::Shmem* aMem) = 0;
|
||||||
virtual void Dealloc(ipc::Shmem& aMem) = 0;
|
virtual void Dealloc(ipc::Shmem&& aMem) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsTArray<ipc::Shmem>& GetGmpFreelist(GMPSharedMem::GMPMemoryClasses aTypes) {
|
nsTArray<ipc::Shmem>& GetGmpFreelist(GMPSharedMem::GMPMemoryClasses aTypes) {
|
||||||
|
|
|
@ -207,9 +207,9 @@ bool GMPVideoDecoderChild::Alloc(size_t aSize,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMPVideoDecoderChild::Dealloc(Shmem& aMem) {
|
void GMPVideoDecoderChild::Dealloc(Shmem&& aMem) {
|
||||||
#ifndef SHMEM_ALLOC_IN_CHILD
|
#ifndef SHMEM_ALLOC_IN_CHILD
|
||||||
SendParentShmemForPool(aMem);
|
SendParentShmemForPool(std::move(aMem));
|
||||||
#else
|
#else
|
||||||
DeallocShmem(aMem);
|
DeallocShmem(aMem);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,7 @@ class GMPVideoDecoderChild : public PGMPVideoDecoderChild,
|
||||||
// GMPSharedMemManager
|
// GMPSharedMemManager
|
||||||
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
||||||
Shmem* aMem) override;
|
Shmem* aMem) override;
|
||||||
void Dealloc(Shmem& aMem) override;
|
void Dealloc(Shmem&& aMem) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~GMPVideoDecoderChild();
|
virtual ~GMPVideoDecoderChild();
|
||||||
|
|
|
@ -60,7 +60,7 @@ class GMPVideoDecoderParent final : public PGMPVideoDecoderParent,
|
||||||
return AllocUnsafeShmem(aSize, aType, aMem);
|
return AllocUnsafeShmem(aSize, aType, aMem);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void Dealloc(Shmem& aMem) override { DeallocShmem(aMem); }
|
void Dealloc(Shmem&& aMem) override { DeallocShmem(aMem); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~GMPVideoDecoderParent();
|
~GMPVideoDecoderParent();
|
||||||
|
|
|
@ -199,9 +199,9 @@ bool GMPVideoEncoderChild::Alloc(size_t aSize,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMPVideoEncoderChild::Dealloc(Shmem& aMem) {
|
void GMPVideoEncoderChild::Dealloc(Shmem&& aMem) {
|
||||||
#ifndef SHMEM_ALLOC_IN_CHILD
|
#ifndef SHMEM_ALLOC_IN_CHILD
|
||||||
SendParentShmemForPool(aMem);
|
SendParentShmemForPool(std::move(aMem));
|
||||||
#else
|
#else
|
||||||
DeallocShmem(aMem);
|
DeallocShmem(aMem);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,7 +39,7 @@ class GMPVideoEncoderChild : public PGMPVideoEncoderChild,
|
||||||
// GMPSharedMemManager
|
// GMPSharedMemManager
|
||||||
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
||||||
Shmem* aMem) override;
|
Shmem* aMem) override;
|
||||||
void Dealloc(Shmem& aMem) override;
|
void Dealloc(Shmem&& aMem) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~GMPVideoEncoderChild();
|
virtual ~GMPVideoEncoderChild();
|
||||||
|
|
|
@ -58,7 +58,7 @@ class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
|
||||||
return AllocUnsafeShmem(aSize, aType, aMem);
|
return AllocUnsafeShmem(aSize, aType, aMem);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void Dealloc(Shmem& aMem) override { DeallocShmem(aMem); }
|
void Dealloc(Shmem&& aMem) override { DeallocShmem(aMem); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~GMPVideoEncoderParent(){};
|
virtual ~GMPVideoEncoderParent(){};
|
||||||
|
|
|
@ -114,7 +114,7 @@ void RemoteAudioDecoderParent::ProcessDecodedData(
|
||||||
RemoteAudioDataIPDL output(
|
RemoteAudioDataIPDL output(
|
||||||
MediaDataIPDL(data->mOffset, data->mTime, data->mTimecode,
|
MediaDataIPDL(data->mOffset, data->mTime, data->mTimecode,
|
||||||
data->mDuration, data->mKeyframe),
|
data->mDuration, data->mKeyframe),
|
||||||
audio->mChannels, audio->mRate, audio->mChannelMap, buffer);
|
audio->mChannels, audio->mRate, audio->mChannelMap, std::move(buffer));
|
||||||
|
|
||||||
Unused << SendOutput(output);
|
Unused << SendOutput(output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Decode(
|
||||||
MediaRawDataIPDL sample(
|
MediaRawDataIPDL sample(
|
||||||
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
||||||
aSample->mDuration, aSample->mKeyframe),
|
aSample->mDuration, aSample->mKeyframe),
|
||||||
buffer);
|
std::move(buffer));
|
||||||
SendInput(sample);
|
SendInput(sample);
|
||||||
|
|
||||||
return mDecodePromise.Ensure(__func__);
|
return mDecodePromise.Ensure(__func__);
|
||||||
|
|
|
@ -184,7 +184,7 @@ void RemoteVideoDecoderParent::ProcessDecodedData(
|
||||||
if (AllocShmem(image->GetDataSize(), Shmem::SharedMemory::TYPE_BASIC,
|
if (AllocShmem(image->GetDataSize(), Shmem::SharedMemory::TYPE_BASIC,
|
||||||
&buffer) &&
|
&buffer) &&
|
||||||
image->GetDataSize() == buffer.Size<uint8_t>()) {
|
image->GetDataSize() == buffer.Size<uint8_t>()) {
|
||||||
sdBuffer.data() = buffer;
|
sdBuffer.data() = std::move(buffer);
|
||||||
image->BuildSurfaceDescriptorBuffer(sdBuffer);
|
image->BuildSurfaceDescriptorBuffer(sdBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ RefPtr<MediaDataDecoder::DecodePromise> VideoDecoderChild::Decode(
|
||||||
MediaRawDataIPDL sample(
|
MediaRawDataIPDL sample(
|
||||||
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
||||||
aSample->mDuration, aSample->mKeyframe),
|
aSample->mDuration, aSample->mKeyframe),
|
||||||
buffer);
|
std::move(buffer));
|
||||||
SendInput(sample);
|
SendInput(sample);
|
||||||
return mDecodePromise.Ensure(__func__);
|
return mDecodePromise.Ensure(__func__);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,7 +265,7 @@ mozilla::ipc::IPCResult VideoDecoderManagerParent::RecvReadback(
|
||||||
dt->Flush();
|
dt->Flush();
|
||||||
|
|
||||||
*aResult = SurfaceDescriptorBuffer(RGBDescriptor(size, format, true),
|
*aResult = SurfaceDescriptorBuffer(RGBDescriptor(size, format, true),
|
||||||
MemoryOrShmem(buffer));
|
MemoryOrShmem(std::move(buffer)));
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -575,7 +575,7 @@ mozilla::ipc::IPCResult CamerasChild::RecvDeliverFrame(
|
||||||
} else {
|
} else {
|
||||||
LOG(("DeliverFrame called with dead callback"));
|
LOG(("DeliverFrame called with dead callback"));
|
||||||
}
|
}
|
||||||
SendReleaseFrame(shmem);
|
SendReleaseFrame(std::move(shmem));
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -278,14 +278,15 @@ int CamerasParent::DeliverFrameOverIPC(CaptureEngine capEng, uint32_t aStreamId,
|
||||||
// get() and Size() check for proper alignment of the segment
|
// get() and Size() check for proper alignment of the segment
|
||||||
memcpy(shMemBuff.GetBytes(), altbuffer, aProps.bufferSize());
|
memcpy(shMemBuff.GetBytes(), altbuffer, aProps.bufferSize());
|
||||||
|
|
||||||
if (!SendDeliverFrame(capEng, aStreamId, shMemBuff.Get(), aProps)) {
|
if (!SendDeliverFrame(capEng, aStreamId, std::move(shMemBuff.Get()),
|
||||||
|
aProps)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(buffer.Valid());
|
MOZ_ASSERT(buffer.Valid());
|
||||||
// ShmemBuffer was available, we're all good. A single copy happened
|
// ShmemBuffer was available, we're all good. A single copy happened
|
||||||
// in the original webrtc callback.
|
// in the original webrtc callback.
|
||||||
if (!SendDeliverFrame(capEng, aStreamId, buffer.Get(), aProps)) {
|
if (!SendDeliverFrame(capEng, aStreamId, std::move(buffer.Get()), aProps)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2722,8 +2722,8 @@ void PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface* surface,
|
||||||
|
|
||||||
// Need a holder since IPDL zaps the object for mysterious reasons.
|
// Need a holder since IPDL zaps the object for mysterious reasons.
|
||||||
Shmem shmemHolder = bitmap->mShmem;
|
Shmem shmemHolder = bitmap->mShmem;
|
||||||
SendShowDirectBitmap(shmemHolder, bitmap->mFormat, bitmap->mStride,
|
SendShowDirectBitmap(std::move(shmemHolder), bitmap->mFormat,
|
||||||
bitmap->mSize, dirty);
|
bitmap->mStride, bitmap->mSize, dirty);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
|
@ -3569,8 +3569,8 @@ bool PluginInstanceChild::ShowPluginFrame() {
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
|
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
|
||||||
currSurf =
|
currSurf = std::move(
|
||||||
static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
|
static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
|
||||||
} else {
|
} else {
|
||||||
MOZ_CRASH("Surface type is not remotable");
|
MOZ_CRASH("Surface type is not remotable");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -849,8 +849,8 @@ mozilla::ipc::IPCResult PluginInstanceParent::RecvShow(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
|
if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
|
||||||
*prevSurface =
|
*prevSurface = std::move(
|
||||||
static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();
|
static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem());
|
||||||
else
|
else
|
||||||
*prevSurface = null_t();
|
*prevSurface = null_t();
|
||||||
|
|
||||||
|
@ -1161,7 +1161,7 @@ PluginInstanceParent::BackgroundDescriptor() {
|
||||||
"Expected shared image surface");
|
"Expected shared image surface");
|
||||||
gfxSharedImageSurface* shmem =
|
gfxSharedImageSurface* shmem =
|
||||||
static_cast<gfxSharedImageSurface*>(mBackground.get());
|
static_cast<gfxSharedImageSurface*>(mBackground.get());
|
||||||
return shmem->GetShmem();
|
return mozilla::plugins::SurfaceDescriptor(std::move(shmem->GetShmem()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If this is ever used, which it shouldn't be, it will trigger a
|
// If this is ever used, which it shouldn't be, it will trigger a
|
||||||
|
@ -1552,8 +1552,8 @@ int16_t PluginInstanceParent::NPP_HandleEvent(void* event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, &handled,
|
if (!CallNPP_HandleEvent_Shmem(npremoteevent, std::move(mShSurface),
|
||||||
&mShSurface))
|
&handled, &mShSurface))
|
||||||
return false; // no good way to handle errors here...
|
return false; // no good way to handle errors here...
|
||||||
|
|
||||||
if (!mShSurface.IsReadable()) {
|
if (!mShSurface.IsReadable()) {
|
||||||
|
|
|
@ -530,7 +530,7 @@ bool PluginModuleChromeParent::InitCrashReporter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeThreadId threadId;
|
NativeThreadId threadId;
|
||||||
if (!CallInitCrashReporter(shmem, &threadId)) {
|
if (!CallInitCrashReporter(std::move(shmem), &threadId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
// Returns the test H/2 server port, throwing if it's missing or invalid.
|
// Returns the test H/2 server port, throwing if it's missing or invalid.
|
||||||
function getTestServerPort() {
|
function getTestServerPort() {
|
||||||
let portEnv = Cc["@mozilla.org/process/environment;1"]
|
let portEnv = Cc["@mozilla.org/process/environment;1"]
|
||||||
|
@ -10,52 +12,26 @@ function getTestServerPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for making sure we can talk to the invalid cert the server presents
|
function readFile(file) {
|
||||||
var CertOverrideListener = function(host, port, bits) {
|
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||||
this.host = host;
|
.createInstance(Ci.nsIFileInputStream);
|
||||||
this.port = port || 443;
|
fstream.init(file, -1, 0, 0);
|
||||||
this.bits = bits;
|
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
|
||||||
};
|
fstream.close();
|
||||||
|
return data;
|
||||||
CertOverrideListener.prototype = {
|
}
|
||||||
host: null,
|
|
||||||
bits: null,
|
function addCertFromFile(certdb, filename, trustString) {
|
||||||
|
let certFile = do_get_file(filename, false);
|
||||||
getInterface: function(aIID) {
|
let pem = readFile(certFile)
|
||||||
return this.QueryInterface(aIID);
|
.replace(/-----BEGIN CERTIFICATE-----/, "")
|
||||||
},
|
.replace(/-----END CERTIFICATE-----/, "")
|
||||||
|
.replace(/[\r\n]/g, "");
|
||||||
QueryInterface: function(aIID) {
|
certdb.addCertFromBase64(pem, trustString);
|
||||||
if (aIID.equals(Ci.nsIBadCertListener2) ||
|
}
|
||||||
aIID.equals(Ci.nsIInterfaceRequestor) ||
|
|
||||||
aIID.equals(Ci.nsISupports))
|
function trustHttp2CA() {
|
||||||
return this;
|
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
.getService(Ci.nsIX509CertDB);
|
||||||
},
|
addCertFromFile(certdb, "../../../../netwerk/test/unit/http2-ca.pem", "CTu,u,u");
|
||||||
|
|
||||||
notifyCertProblem: function(socketInfo, secInfo, targetHost) {
|
|
||||||
var cert = secInfo.serverCert;
|
|
||||||
var cos = Cc["@mozilla.org/security/certoverride;1"].
|
|
||||||
getService(Ci.nsICertOverrideService);
|
|
||||||
cos.rememberValidityOverride(this.host, this.port, cert, this.bits, false);
|
|
||||||
dump("Certificate Override in place\n");
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function addCertOverride(host, port, bits) {
|
|
||||||
var req = new XMLHttpRequest();
|
|
||||||
try {
|
|
||||||
var url;
|
|
||||||
if (port && (port > 0) && (port !== 443)) {
|
|
||||||
url = "https://" + host + ":" + port + "/";
|
|
||||||
} else {
|
|
||||||
url = "https://" + host + "/";
|
|
||||||
}
|
|
||||||
req.open("GET", url, false);
|
|
||||||
req.channel.notificationCallbacks = new CertOverrideListener(host, port, bits);
|
|
||||||
req.send(null);
|
|
||||||
} catch (e) {
|
|
||||||
// This will fail since the server is not trusted yet
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,7 @@ function run_test() {
|
||||||
prefs.setBoolPref("dom.push.enabled", true);
|
prefs.setBoolPref("dom.push.enabled", true);
|
||||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||||
|
|
||||||
addCertOverride("localhost", serverPort,
|
trustHttp2CA();
|
||||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
|
||||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
|
||||||
Ci.nsICertOverrideService.ERROR_TIME);
|
|
||||||
|
|
||||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||||
|
|
||||||
|
|
|
@ -54,10 +54,7 @@ add_task(async function test_TLS() {
|
||||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||||
|
|
||||||
addCertOverride("localhost", serverPort,
|
trustHttp2CA();
|
||||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
|
||||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
|
||||||
Ci.nsICertOverrideService.ERROR_TIME);
|
|
||||||
|
|
||||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,10 +27,7 @@ function run_test() {
|
||||||
prefs.setBoolPref("dom.push.enabled", true);
|
prefs.setBoolPref("dom.push.enabled", true);
|
||||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||||
|
|
||||||
addCertOverride("localhost", serverPort,
|
trustHttp2CA();
|
||||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
|
||||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
|
||||||
Ci.nsICertOverrideService.ERROR_TIME);
|
|
||||||
|
|
||||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,7 @@ function run_test() {
|
||||||
prefs.setBoolPref("dom.push.enabled", true);
|
prefs.setBoolPref("dom.push.enabled", true);
|
||||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||||
|
|
||||||
addCertOverride("localhost", serverPort,
|
trustHttp2CA();
|
||||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
|
||||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
|
||||||
Ci.nsICertOverrideService.ERROR_TIME);
|
|
||||||
|
|
||||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,9 @@ UniquePtr<SurfaceFactory> GLScreenBuffer::CreateFactory(
|
||||||
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel,
|
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel,
|
||||||
mFlags);
|
mFlags);
|
||||||
#elif defined(MOZ_WIDGET_ANDROID)
|
#elif defined(MOZ_WIDGET_ANDROID)
|
||||||
if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) {
|
// XXX WebRender does not support SurfaceFactory_EGLImage usage.
|
||||||
|
if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled() &&
|
||||||
|
backend != layers::LayersBackend::LAYERS_WR) {
|
||||||
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
|
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
|
||||||
} else {
|
} else {
|
||||||
factory =
|
factory =
|
||||||
|
|
|
@ -1168,9 +1168,9 @@ struct ParamTraits<mozilla::Array<T, Length>> {
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::gfx::PaintFragment> {
|
struct ParamTraits<mozilla::gfx::PaintFragment> {
|
||||||
typedef mozilla::gfx::PaintFragment paramType;
|
typedef mozilla::gfx::PaintFragment paramType;
|
||||||
static void Write(Message* aMsg, paramType& aParam) {
|
static void Write(Message* aMsg, paramType&& aParam) {
|
||||||
WriteParam(aMsg, aParam.mSize);
|
WriteParam(aMsg, aParam.mSize);
|
||||||
WriteParam(aMsg, aParam.mRecording);
|
WriteParam(aMsg, std::move(aParam.mRecording));
|
||||||
WriteParam(aMsg, aParam.mDependencies);
|
WriteParam(aMsg, aParam.mDependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -484,7 +484,8 @@ bool ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem));
|
aOutDescriptor =
|
||||||
|
SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(std::move(mShmem)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,11 @@ already_AddRefed<SourceSurface> D3D11YCbCrImage::GetAsSourceSurface() {
|
||||||
RefPtr<ID3D11Device> dev;
|
RefPtr<ID3D11Device> dev;
|
||||||
texY->GetDevice(getter_AddRefs(dev));
|
texY->GetDevice(getter_AddRefs(dev));
|
||||||
|
|
||||||
|
if (!dev || dev != gfx::DeviceManagerDx::Get()->GetImageDevice()) {
|
||||||
|
gfxCriticalError() << "D3D11Device is obsoleted";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<ID3D10Multithread> mt;
|
RefPtr<ID3D10Multithread> mt;
|
||||||
hr = dev->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
|
hr = dev->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
|
||||||
|
|
||||||
|
|
|
@ -1204,7 +1204,7 @@ void LayerManagerComposite::HandlePixelsTarget() {
|
||||||
gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
|
gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
|
||||||
LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
|
LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
|
||||||
Unused << mScreenPixelsTarget->SendScreenPixels(
|
Unused << mScreenPixelsTarget->SendScreenPixels(
|
||||||
mem, ScreenIntSize(bufferWidth, bufferHeight));
|
std::move(mem), ScreenIntSize(bufferWidth, bufferHeight));
|
||||||
mScreenPixelsTarget = nullptr;
|
mScreenPixelsTarget = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -964,7 +964,7 @@ bool ShadowLayerForwarder::AllocSurfaceDescriptorWithCaps(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferDesc = shmem;
|
bufferDesc = std::move(shmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use an intermediate buffer by default. Skipping the intermediate buffer is
|
// Use an intermediate buffer by default. Skipping the intermediate buffer is
|
||||||
|
|
|
@ -166,7 +166,7 @@ bool UiCompositorControllerChild::ToolbarPixelsToCompositor(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendToolbarPixelsToCompositor(aMem, aSize);
|
return SendToolbarPixelsToCompositor(std::move(aMem), aSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiCompositorControllerChild::Destroy() {
|
void UiCompositorControllerChild::Destroy() {
|
||||||
|
|
|
@ -98,7 +98,8 @@ void WebRenderBridgeChild::UpdateResources(
|
||||||
nsTArray<ipc::Shmem> largeShmems;
|
nsTArray<ipc::Shmem> largeShmems;
|
||||||
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
||||||
|
|
||||||
this->SendUpdateResources(resourceUpdates, smallShmems, largeShmems);
|
this->SendUpdateResources(resourceUpdates, smallShmems,
|
||||||
|
std::move(largeShmems));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRenderBridgeChild::EndTransaction(
|
void WebRenderBridgeChild::EndTransaction(
|
||||||
|
@ -123,12 +124,12 @@ void WebRenderBridgeChild::EndTransaction(
|
||||||
nsTArray<ipc::Shmem> largeShmems;
|
nsTArray<ipc::Shmem> largeShmems;
|
||||||
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
||||||
|
|
||||||
this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
|
this->SendSetDisplayList(
|
||||||
GetFwdTransactionId(), aTransactionId, aContentSize,
|
aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(),
|
||||||
dlData, aDL.dl_desc, aScrollData, resourceUpdates,
|
aTransactionId, aContentSize, std::move(dlData), aDL.dl_desc, aScrollData,
|
||||||
smallShmems, largeShmems, mIdNamespace,
|
resourceUpdates, smallShmems, std::move(largeShmems), mIdNamespace,
|
||||||
aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
aContainsSVGGroup, aVsyncId, aVsyncStartTime, aRefreshStartTime,
|
||||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
aTxnStartTime, aTxnURL, fwdTime);
|
||||||
|
|
||||||
mParentCommands.Clear();
|
mParentCommands.Clear();
|
||||||
mDestroyedActors.Clear();
|
mDestroyedActors.Clear();
|
||||||
|
@ -158,8 +159,8 @@ void WebRenderBridgeChild::EndEmptyTransaction(
|
||||||
this->SendEmptyTransaction(
|
this->SendEmptyTransaction(
|
||||||
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
|
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
|
||||||
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
|
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
|
||||||
smallShmems, largeShmems, mIdNamespace, aVsyncId, aVsyncStartTime,
|
smallShmems, std::move(largeShmems), mIdNamespace, aVsyncId,
|
||||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
aVsyncStartTime, aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
||||||
mParentCommands.Clear();
|
mParentCommands.Clear();
|
||||||
mDestroyedActors.Clear();
|
mDestroyedActors.Clear();
|
||||||
mIsInTransaction = false;
|
mIsInTransaction = false;
|
||||||
|
|
|
@ -1471,7 +1471,7 @@ impl AlphaBatchBuilder {
|
||||||
.expect("bug: surface must be allocated by now");
|
.expect("bug: surface must be allocated by now");
|
||||||
|
|
||||||
|
|
||||||
let filter_data = &ctx.data_stores.filterdata[handle];
|
let filter_data = &ctx.data_stores.filter_data[handle];
|
||||||
let filter_mode : i32 = 13 |
|
let filter_mode : i32 = 13 |
|
||||||
((filter_data.data.r_func.to_int() << 28 |
|
((filter_data.data.r_func.to_int() << 28 |
|
||||||
filter_data.data.g_func.to_int() << 24 |
|
filter_data.data.g_func.to_int() << 24 |
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, DeviceIntSize, LayoutPrimitiveInfo};
|
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, LayoutPrimitiveInfo, PrimitiveKeyKind};
|
||||||
use api::{LayoutRect, LayoutSize, LayoutVector2D, MAX_BLUR_RADIUS};
|
use api::MAX_BLUR_RADIUS;
|
||||||
|
use api::units::*;
|
||||||
use clip::ClipItemKey;
|
use clip::ClipItemKey;
|
||||||
use display_list_flattener::DisplayListFlattener;
|
use display_list_flattener::DisplayListFlattener;
|
||||||
use gpu_cache::GpuCacheHandle;
|
use gpu_cache::GpuCacheHandle;
|
||||||
use gpu_types::BoxShadowStretchMode;
|
use gpu_types::BoxShadowStretchMode;
|
||||||
use prim_store::{ScrollNodeAndClipChain, PrimitiveKeyKind};
|
use prim_store::ScrollNodeAndClipChain;
|
||||||
use render_task::RenderTaskCacheEntryHandle;
|
use render_task::RenderTaskCacheEntryHandle;
|
||||||
use util::RectHelpers;
|
use util::RectHelpers;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS
|
||||||
use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D};
|
use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D};
|
||||||
use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel};
|
use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel};
|
||||||
use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform};
|
use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform};
|
||||||
use api::{ImageKey};
|
use api::{ClipIntern, ImageKey};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use border::{ensure_no_corner_overlap, BorderRadiusAu};
|
use border::{ensure_no_corner_overlap, BorderRadiusAu};
|
||||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
|
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
|
||||||
|
@ -104,8 +104,8 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset};
|
||||||
|
|
||||||
// Type definitions for interning clip nodes.
|
// Type definitions for interning clip nodes.
|
||||||
|
|
||||||
pub use intern_types::clip::Store as ClipDataStore;
|
pub type ClipDataStore = intern::DataStore<ClipIntern>;
|
||||||
use intern_types::clip::Handle as ClipDataHandle;
|
type ClipDataHandle = intern::Handle<ClipIntern>;
|
||||||
|
|
||||||
// Result of comparing a clip node instance against a local rect.
|
// Result of comparing a clip node instance against a local rect.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -847,6 +847,12 @@ impl ClipItemKey {
|
||||||
|
|
||||||
impl intern::InternDebug for ClipItemKey {}
|
impl intern::InternDebug for ClipItemKey {}
|
||||||
|
|
||||||
|
impl intern::Internable for ClipIntern {
|
||||||
|
type Key = ClipItemKey;
|
||||||
|
type StoreData = ClipNode;
|
||||||
|
type InternData = ();
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, MallocSizeOf)]
|
#[derive(Debug, MallocSizeOf)]
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
|
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
|
||||||
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
use api::{ClipId, ColorF, ComplexClipRegion, RasterSpace};
|
||||||
use api::{DisplayItemRef, ExtendMode, ExternalScrollId, AuHelpers};
|
use api::{DisplayItemRef, ExtendMode, ExternalScrollId};
|
||||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, GradientStop};
|
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
|
||||||
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, ColorDepth};
|
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth};
|
||||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
use api::{LayoutPrimitiveInfo, LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||||
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
|
||||||
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
|
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem};
|
||||||
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData, TempFilterData};
|
use api::{ClipMode, PrimitiveKeyKind, TransformStyle, YuvColorSpace, YuvData, TempFilterData};
|
||||||
|
use api::units::*;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
|
use clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
|
||||||
use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex};
|
use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex};
|
||||||
|
@ -19,13 +19,14 @@ use frame_builder::{ChasePrimitive, FrameBuilder, FrameBuilderConfig};
|
||||||
use glyph_rasterizer::FontInstance;
|
use glyph_rasterizer::FontInstance;
|
||||||
use hit_test::{HitTestingItem, HitTestingRun};
|
use hit_test::{HitTestingItem, HitTestingRun};
|
||||||
use image::simplify_repeated_primitive;
|
use image::simplify_repeated_primitive;
|
||||||
use intern::{Handle, Internable, InternDebug};
|
use intern::Interner;
|
||||||
use internal_types::{FastHashMap, FastHashSet};
|
use internal_types::{FastHashMap, FastHashSet};
|
||||||
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
|
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
|
||||||
use picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCache};
|
use picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCache};
|
||||||
use prim_store::{PrimitiveInstance, PrimitiveKeyKind, PrimitiveSceneData};
|
use prim_store::{PrimitiveInstance, PrimitiveSceneData};
|
||||||
use prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
|
use prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
|
||||||
use prim_store::{PrimitiveStoreStats, ScrollNodeAndClipChain, PictureIndex};
|
use prim_store::{PrimitiveStoreStats, ScrollNodeAndClipChain, PictureIndex};
|
||||||
|
use prim_store::InternablePrimitive;
|
||||||
use prim_store::{register_prim_chase_id, get_line_decoration_sizes};
|
use prim_store::{register_prim_chase_id, get_line_decoration_sizes};
|
||||||
use prim_store::borders::{ImageBorder, NormalBorderPrim};
|
use prim_store::borders::{ImageBorder, NormalBorderPrim};
|
||||||
use prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
|
use prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
|
||||||
|
@ -36,7 +37,7 @@ use prim_store::text_run::TextRun;
|
||||||
use render_backend::{DocumentView};
|
use render_backend::{DocumentView};
|
||||||
use resource_cache::{FontInstanceMap, ImageRequest};
|
use resource_cache::{FontInstanceMap, ImageRequest};
|
||||||
use scene::{Scene, StackingContextHelpers};
|
use scene::{Scene, StackingContextHelpers};
|
||||||
use scene_builder::{InternerMut, Interners};
|
use scene_builder::Interners;
|
||||||
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
|
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
|
||||||
use std::{f32, mem, usize};
|
use std::{f32, mem, usize};
|
||||||
use std::collections::vec_deque::VecDeque;
|
use std::collections::vec_deque::VecDeque;
|
||||||
|
@ -1148,16 +1149,14 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
prim: P,
|
prim: P,
|
||||||
) -> PrimitiveInstance
|
) -> PrimitiveInstance
|
||||||
where
|
where
|
||||||
P: Internable<InternData=PrimitiveSceneData>,
|
P: InternablePrimitive,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
{
|
{
|
||||||
// Build a primitive key.
|
// Build a primitive key.
|
||||||
let prim_key = prim.build_key(info);
|
let prim_key = prim.into_key(info);
|
||||||
|
|
||||||
let interner = self.interners.interner_mut();
|
let interner = self.interners.as_mut();
|
||||||
let prim_data_handle =
|
let prim_data_handle = interner
|
||||||
interner
|
|
||||||
.intern(&prim_key, || {
|
.intern(&prim_key, || {
|
||||||
PrimitiveSceneData {
|
PrimitiveSceneData {
|
||||||
prim_size: info.rect.size,
|
prim_size: info.rect.size,
|
||||||
|
@ -1167,7 +1166,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
|
|
||||||
let current_offset = self.rf_mapper.current_offset();
|
let current_offset = self.rf_mapper.current_offset();
|
||||||
|
|
||||||
let instance_kind = prim_key.as_instance_kind(
|
let instance_kind = P::make_instance_kind(
|
||||||
|
prim_key,
|
||||||
prim_data_handle,
|
prim_data_handle,
|
||||||
&mut self.prim_store,
|
&mut self.prim_store,
|
||||||
current_offset,
|
current_offset,
|
||||||
|
@ -1228,9 +1228,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
prim: P,
|
prim: P,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
P: InternablePrimitive + IsVisible,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
{
|
{
|
||||||
if prim.is_visible() {
|
if prim.is_visible() {
|
||||||
let clip_chain_id = self.build_clip_chain(
|
let clip_chain_id = self.build_clip_chain(
|
||||||
|
@ -1255,9 +1254,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
prim: P,
|
prim: P,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
P: InternablePrimitive + IsVisible,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
ShadowItem: From<PendingPrimitive<P>>
|
ShadowItem: From<PendingPrimitive<P>>
|
||||||
{
|
{
|
||||||
// If a shadow context is not active, then add the primitive
|
// If a shadow context is not active, then add the primitive
|
||||||
|
@ -1290,9 +1288,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
prim: P,
|
prim: P,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
P: Internable<InternData = PrimitiveSceneData>,
|
P: InternablePrimitive,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
{
|
{
|
||||||
let prim_instance = self.create_primitive(
|
let prim_instance = self.create_primitive(
|
||||||
info,
|
info,
|
||||||
|
@ -1606,7 +1603,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle = self.interners
|
let handle = self.interners
|
||||||
.filterdata
|
.filter_data
|
||||||
.intern(&filter_data_key, || ());
|
.intern(&filter_data_key, || ());
|
||||||
PictureCompositeMode::ComponentTransferFilter(handle)
|
PictureCompositeMode::ComponentTransferFilter(handle)
|
||||||
}
|
}
|
||||||
|
@ -2129,9 +2126,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
prims: &mut Vec<PrimitiveInstance>,
|
prims: &mut Vec<PrimitiveInstance>,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
|
P: InternablePrimitive + CreateShadow,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
{
|
{
|
||||||
// Offset the local rect and clip rect by the shadow offset.
|
// Offset the local rect and clip rect by the shadow offset.
|
||||||
let mut info = pending_primitive.info.clone();
|
let mut info = pending_primitive.info.clone();
|
||||||
|
@ -2156,9 +2152,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
pending_primitive: PendingPrimitive<P>,
|
pending_primitive: PendingPrimitive<P>,
|
||||||
) where
|
) where
|
||||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
P: InternablePrimitive + IsVisible,
|
||||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
Interners: AsMut<Interner<P>>,
|
||||||
Interners: InternerMut<P>,
|
|
||||||
{
|
{
|
||||||
// For a normal primitive, if it has alpha > 0, then we add this
|
// For a normal primitive, if it has alpha > 0, then we add this
|
||||||
// as a normal primitive to the parent picture.
|
// as a normal primitive to the parent picture.
|
||||||
|
@ -2681,14 +2676,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsInstanceKind<H> {
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: H,
|
|
||||||
prim_store: &mut PrimitiveStore,
|
|
||||||
reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CreateShadow {
|
pub trait CreateShadow {
|
||||||
fn create_shadow(&self, shadow: &Shadow) -> Self;
|
fn create_shadow(&self, shadow: &Shadow) -> Self;
|
||||||
|
|
|
@ -7,10 +7,10 @@ use gpu_cache::{GpuCacheHandle};
|
||||||
use frame_builder::FrameBuildingState;
|
use frame_builder::FrameBuildingState;
|
||||||
use gpu_cache::GpuDataRequest;
|
use gpu_cache::GpuDataRequest;
|
||||||
use intern;
|
use intern;
|
||||||
use api::{ComponentTransferFuncType};
|
use api::{FilterDataIntern, ComponentTransferFuncType};
|
||||||
|
|
||||||
|
|
||||||
pub use intern_types::filterdata::Handle as FilterDataHandle;
|
pub type FilterDataHandle = intern::Handle<FilterDataIntern>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
|
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
@ -144,6 +144,12 @@ impl SFilterDataTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl intern::Internable for FilterDataIntern {
|
||||||
|
type Key = SFilterDataKey;
|
||||||
|
type StoreData = SFilterDataTemplate;
|
||||||
|
type InternData = ();
|
||||||
|
}
|
||||||
|
|
||||||
fn push_component_transfer_data(
|
fn push_component_transfer_data(
|
||||||
func_comp: &SFilterDataComponent,
|
func_comp: &SFilterDataComponent,
|
||||||
request: &mut GpuDataRequest,
|
request: &mut GpuDataRequest,
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
//! stored inside each handle. This is then used for
|
//! stored inside each handle. This is then used for
|
||||||
//! cache invalidation.
|
//! cache invalidation.
|
||||||
|
|
||||||
use api::{LayoutPrimitiveInfo};
|
|
||||||
use internal_types::FastHashMap;
|
use internal_types::FastHashMap;
|
||||||
use malloc_size_of::MallocSizeOf;
|
use malloc_size_of::MallocSizeOf;
|
||||||
use profiler::ResourceProfileCounter;
|
use profiler::ResourceProfileCounter;
|
||||||
|
@ -79,15 +78,28 @@ impl ItemUid {
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(Debug, Copy, Clone, MallocSizeOf)]
|
#[derive(Debug, MallocSizeOf)]
|
||||||
pub struct Handle<M: Copy> {
|
pub struct Handle<I> {
|
||||||
index: u32,
|
index: u32,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
uid: ItemUid,
|
uid: ItemUid,
|
||||||
_marker: PhantomData<M>,
|
_marker: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <M> Handle<M> where M: Copy {
|
impl<I> Clone for Handle<I> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Handle {
|
||||||
|
index: self.index,
|
||||||
|
epoch: self.epoch,
|
||||||
|
uid: self.uid,
|
||||||
|
_marker: self._marker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> Copy for Handle<I> {}
|
||||||
|
|
||||||
|
impl<I> Handle<I> {
|
||||||
pub fn uid(&self) -> ItemUid {
|
pub fn uid(&self) -> ItemUid {
|
||||||
self.uid
|
self.uid
|
||||||
}
|
}
|
||||||
|
@ -118,46 +130,34 @@ pub trait InternDebug {
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
pub struct DataStore<S, T: MallocSizeOf, M> {
|
pub struct DataStore<I: Internable> {
|
||||||
items: Vec<Option<T>>,
|
items: Vec<Option<I::StoreData>>,
|
||||||
_source: PhantomData<S>,
|
|
||||||
_marker: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, T, M> ::std::default::Default for DataStore<S, T, M>
|
impl<I: Internable> Default for DataStore<I> {
|
||||||
where
|
|
||||||
S: Debug + MallocSizeOf,
|
|
||||||
T: From<S> + MallocSizeOf,
|
|
||||||
M: Debug
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
DataStore {
|
DataStore {
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
_source: PhantomData,
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, T, M> DataStore<S, T, M>
|
impl<I: Internable> DataStore<I> {
|
||||||
where
|
|
||||||
S: Debug + MallocSizeOf,
|
|
||||||
T: From<S> + MallocSizeOf,
|
|
||||||
M: Debug
|
|
||||||
{
|
|
||||||
/// Apply any updates from the scene builder thread to
|
/// Apply any updates from the scene builder thread to
|
||||||
/// this data store.
|
/// this data store.
|
||||||
pub fn apply_updates(
|
pub fn apply_updates(
|
||||||
&mut self,
|
&mut self,
|
||||||
update_list: UpdateList<S>,
|
update_list: UpdateList<I::Key>,
|
||||||
profile_counter: &mut ResourceProfileCounter,
|
profile_counter: &mut ResourceProfileCounter,
|
||||||
) {
|
) {
|
||||||
let mut data_iter = update_list.data.into_iter();
|
let mut data_iter = update_list.data.into_iter();
|
||||||
for update in update_list.updates {
|
for update in update_list.updates {
|
||||||
match update.kind {
|
match update.kind {
|
||||||
UpdateKind::Insert => {
|
UpdateKind::Insert => {
|
||||||
self.items.entry(update.index).
|
let value = data_iter.next().unwrap().into();
|
||||||
set(Some(T::from(data_iter.next().unwrap())));
|
self.items
|
||||||
|
.entry(update.index)
|
||||||
|
.set(Some(value));
|
||||||
}
|
}
|
||||||
UpdateKind::Remove => {
|
UpdateKind::Remove => {
|
||||||
self.items[update.index] = None;
|
self.items[update.index] = None;
|
||||||
|
@ -165,7 +165,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let per_item_size = mem::size_of::<S>() + mem::size_of::<T>();
|
let per_item_size = mem::size_of::<I::Key>() + mem::size_of::<I::StoreData>();
|
||||||
profile_counter.set(self.items.len(), per_item_size * self.items.len());
|
profile_counter.set(self.items.len(), per_item_size * self.items.len());
|
||||||
|
|
||||||
debug_assert!(data_iter.next().is_none());
|
debug_assert!(data_iter.next().is_none());
|
||||||
|
@ -173,27 +173,17 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve an item from the store via handle
|
/// Retrieve an item from the store via handle
|
||||||
impl<S, T, M> ops::Index<Handle<M>> for DataStore<S, T, M>
|
impl<I: Internable> ops::Index<Handle<I>> for DataStore<I> {
|
||||||
where
|
type Output = I::StoreData;
|
||||||
S: MallocSizeOf,
|
fn index(&self, handle: Handle<I>) -> &I::StoreData {
|
||||||
T: MallocSizeOf,
|
|
||||||
M: Copy
|
|
||||||
{
|
|
||||||
type Output = T;
|
|
||||||
fn index(&self, handle: Handle<M>) -> &T {
|
|
||||||
self.items[handle.index as usize].as_ref().expect("Bad datastore lookup")
|
self.items[handle.index as usize].as_ref().expect("Bad datastore lookup")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a mutable item from the store via handle
|
/// Retrieve a mutable item from the store via handle
|
||||||
/// Retrieve an item from the store via handle
|
/// Retrieve an item from the store via handle
|
||||||
impl<S, T, M> ops::IndexMut<Handle<M>> for DataStore<S, T, M>
|
impl<I: Internable> ops::IndexMut<Handle<I>> for DataStore<I> {
|
||||||
where
|
fn index_mut(&mut self, handle: Handle<I>) -> &mut I::StoreData {
|
||||||
S: MallocSizeOf,
|
|
||||||
T: MallocSizeOf,
|
|
||||||
M: Copy
|
|
||||||
{
|
|
||||||
fn index_mut(&mut self, handle: Handle<M>) -> &mut T {
|
|
||||||
self.items[handle.index as usize].as_mut().expect("Bad datastore lookup")
|
self.items[handle.index as usize].as_mut().expect("Bad datastore lookup")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,33 +196,23 @@ where
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
pub struct Interner<S, D, M>
|
pub struct Interner<I: Internable> {
|
||||||
where
|
|
||||||
S: Eq + Hash + Clone + Debug + MallocSizeOf,
|
|
||||||
D: MallocSizeOf,
|
|
||||||
M: Copy + MallocSizeOf,
|
|
||||||
{
|
|
||||||
/// Uniquely map an interning key to a handle
|
/// Uniquely map an interning key to a handle
|
||||||
map: FastHashMap<S, Handle<M>>,
|
map: FastHashMap<I::Key, Handle<I>>,
|
||||||
/// List of free slots in the data store for re-use.
|
/// List of free slots in the data store for re-use.
|
||||||
free_list: Vec<usize>,
|
free_list: Vec<usize>,
|
||||||
/// Pending list of updates that need to be applied.
|
/// Pending list of updates that need to be applied.
|
||||||
updates: Vec<Update>,
|
updates: Vec<Update>,
|
||||||
/// Pending new data to insert.
|
/// Pending new data to insert.
|
||||||
update_data: Vec<S>,
|
update_data: Vec<I::Key>,
|
||||||
/// The current epoch for the interner.
|
/// The current epoch for the interner.
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
/// The information associated with each interned
|
/// The information associated with each interned
|
||||||
/// item that can be accessed by the interner.
|
/// item that can be accessed by the interner.
|
||||||
local_data: Vec<D>,
|
local_data: Vec<I::InternData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, D, M> ::std::default::Default for Interner<S, D, M>
|
impl<I: Internable> Default for Interner<I> {
|
||||||
where
|
|
||||||
S: Eq + Hash + Clone + Debug + MallocSizeOf,
|
|
||||||
D: MallocSizeOf,
|
|
||||||
M: Copy + Debug + MallocSizeOf,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Interner {
|
Interner {
|
||||||
map: FastHashMap::default(),
|
map: FastHashMap::default(),
|
||||||
|
@ -245,12 +225,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, D, M> Interner<S, D, M>
|
impl<I: Internable> Interner<I> {
|
||||||
where
|
|
||||||
S: Eq + Hash + Clone + Debug + InternDebug + MallocSizeOf,
|
|
||||||
D: MallocSizeOf,
|
|
||||||
M: Copy + Debug + MallocSizeOf
|
|
||||||
{
|
|
||||||
/// Intern a data structure, and return a handle to
|
/// Intern a data structure, and return a handle to
|
||||||
/// that data. The handle can then be stored in the
|
/// that data. The handle can then be stored in the
|
||||||
/// frame builder, and safely accessed via the data
|
/// frame builder, and safely accessed via the data
|
||||||
|
@ -260,9 +235,9 @@ where
|
||||||
/// key isn't already interned.
|
/// key isn't already interned.
|
||||||
pub fn intern<F>(
|
pub fn intern<F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &S,
|
data: &I::Key,
|
||||||
f: F,
|
fun: F,
|
||||||
) -> Handle<M> where F: FnOnce() -> D {
|
) -> Handle<I> where F: FnOnce() -> I::InternData {
|
||||||
// Use get_mut rather than entry here to avoid
|
// Use get_mut rather than entry here to avoid
|
||||||
// cloning the (sometimes large) key in the common
|
// cloning the (sometimes large) key in the common
|
||||||
// case, where the data already exists in the interner.
|
// case, where the data already exists in the interner.
|
||||||
|
@ -303,7 +278,7 @@ where
|
||||||
|
|
||||||
// Create the local data for this item that is
|
// Create the local data for this item that is
|
||||||
// being interned.
|
// being interned.
|
||||||
self.local_data.entry(index).set(f());
|
self.local_data.entry(index).set(fun());
|
||||||
|
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
@ -311,7 +286,7 @@ where
|
||||||
/// Retrieve the pending list of updates for an interner
|
/// Retrieve the pending list of updates for an interner
|
||||||
/// that need to be applied to the data store. Also run
|
/// that need to be applied to the data store. Also run
|
||||||
/// a GC step that removes old entries.
|
/// a GC step that removes old entries.
|
||||||
pub fn end_frame_and_get_pending_updates(&mut self) -> UpdateList<S> {
|
pub fn end_frame_and_get_pending_updates(&mut self) -> UpdateList<I::Key> {
|
||||||
let mut updates = self.updates.take_and_preallocate();
|
let mut updates = self.updates.take_and_preallocate();
|
||||||
let data = self.update_data.take_and_preallocate();
|
let data = self.update_data.take_and_preallocate();
|
||||||
|
|
||||||
|
@ -354,30 +329,36 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the local data for an item from the interner via handle
|
/// Retrieve the local data for an item from the interner via handle
|
||||||
impl<S, D, M> ops::Index<Handle<M>> for Interner<S, D, M>
|
impl<I: Internable> ops::Index<Handle<I>> for Interner<I> {
|
||||||
where
|
type Output = I::InternData;
|
||||||
S: Eq + Clone + Hash + Debug + MallocSizeOf,
|
fn index(&self, handle: Handle<I>) -> &I::InternData {
|
||||||
D: MallocSizeOf,
|
|
||||||
M: Copy + Debug + MallocSizeOf
|
|
||||||
{
|
|
||||||
type Output = D;
|
|
||||||
fn index(&self, handle: Handle<M>) -> &D {
|
|
||||||
&self.local_data[handle.index as usize]
|
&self.local_data[handle.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement `Internable` for a type that wants participate in interning.
|
// The trick to make trait bounds configurable by features.
|
||||||
///
|
mod dummy {
|
||||||
/// see DisplayListFlattener::add_interned_primitive<P>
|
#[cfg(not(feature = "capture"))]
|
||||||
pub trait Internable {
|
pub trait Serialize {}
|
||||||
type Marker: Copy + Debug + MallocSizeOf;
|
#[cfg(not(feature = "capture"))]
|
||||||
type Source: Eq + Hash + Clone + Debug + MallocSizeOf;
|
impl<T> Serialize for T {}
|
||||||
type StoreData: From<Self::Source> + MallocSizeOf;
|
#[cfg(not(feature = "replay"))]
|
||||||
type InternData: MallocSizeOf;
|
pub trait Deserialize<'a> {}
|
||||||
|
#[cfg(not(feature = "replay"))]
|
||||||
/// Build a new key from self with `info`.
|
impl<'a, T> Deserialize<'a> for T {}
|
||||||
fn build_key(
|
}
|
||||||
self,
|
#[cfg(feature = "capture")]
|
||||||
info: &LayoutPrimitiveInfo,
|
use serde::Serialize as InternSerialize;
|
||||||
) -> Self::Source;
|
#[cfg(not(feature = "capture"))]
|
||||||
|
use self::dummy::Serialize as InternSerialize;
|
||||||
|
#[cfg(feature = "replay")]
|
||||||
|
use serde::Deserialize as InternDeserialize;
|
||||||
|
#[cfg(not(feature = "replay"))]
|
||||||
|
use self::dummy::Deserialize as InternDeserialize;
|
||||||
|
|
||||||
|
/// Implement `Internable` for a type that wants to participate in interning.
|
||||||
|
pub trait Internable: MallocSizeOf {
|
||||||
|
type Key: Eq + Hash + Clone + Debug + MallocSizeOf + InternDebug + InternSerialize + for<'a> InternDeserialize<'a>;
|
||||||
|
type StoreData: From<Self::Key> + MallocSizeOf + InternSerialize + for<'a> InternDeserialize<'a>;
|
||||||
|
type InternData: MallocSizeOf + InternSerialize + for<'a> InternDeserialize<'a>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
macro_rules! common {
|
|
||||||
() => (
|
|
||||||
use ::intern;
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use ::prim_store::PrimitiveSceneData;
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
|
||||||
pub struct Marker;
|
|
||||||
pub type Handle = intern::Handle<Marker>;
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod clip {
|
|
||||||
common!();
|
|
||||||
use ::clip::{ClipItemKey, ClipNode};
|
|
||||||
pub type Store = intern::DataStore<ClipItemKey, ClipNode, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<ClipItemKey>;
|
|
||||||
pub type Interner = intern::Interner<ClipItemKey, (), Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod prim {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::{PrimitiveKey, PrimitiveTemplate};
|
|
||||||
pub type Store = intern::DataStore<PrimitiveKey, PrimitiveTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<PrimitiveKey>;
|
|
||||||
pub type Interner = intern::Interner<PrimitiveKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod normal_border {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::borders::{NormalBorderKey, NormalBorderTemplate};
|
|
||||||
pub type Store = intern::DataStore<NormalBorderKey, NormalBorderTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<NormalBorderKey>;
|
|
||||||
pub type Interner = intern::Interner<NormalBorderKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod image_border {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::borders::{ImageBorderKey, ImageBorderTemplate};
|
|
||||||
pub type Store = intern::DataStore<ImageBorderKey, ImageBorderTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<ImageBorderKey>;
|
|
||||||
pub type Interner = intern::Interner<ImageBorderKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod image {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::image::{ImageKey, ImageTemplate};
|
|
||||||
pub type Store = intern::DataStore<ImageKey, ImageTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<ImageKey>;
|
|
||||||
pub type Interner = intern::Interner<ImageKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod yuv_image {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::image::{YuvImageKey, YuvImageTemplate};
|
|
||||||
pub type Store = intern::DataStore<YuvImageKey, YuvImageTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<YuvImageKey>;
|
|
||||||
pub type Interner = intern::Interner<YuvImageKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod line_decoration {
|
|
||||||
use ::prim_store::line_dec::{LineDecorationKey, LineDecorationTemplate};
|
|
||||||
common!();
|
|
||||||
pub type Store = intern::DataStore<LineDecorationKey, LineDecorationTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<LineDecorationKey>;
|
|
||||||
pub type Interner = intern::Interner<LineDecorationKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod linear_grad {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::gradient::{LinearGradientKey, LinearGradientTemplate};
|
|
||||||
pub type Store = intern::DataStore<LinearGradientKey, LinearGradientTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<LinearGradientKey>;
|
|
||||||
pub type Interner = intern::Interner<LinearGradientKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod radial_grad {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::gradient::{RadialGradientKey, RadialGradientTemplate};
|
|
||||||
pub type Store = intern::DataStore<RadialGradientKey, RadialGradientTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<RadialGradientKey>;
|
|
||||||
pub type Interner = intern::Interner<RadialGradientKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod picture {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::picture::{PictureKey, PictureTemplate};
|
|
||||||
pub type Store = intern::DataStore<PictureKey, PictureTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<PictureKey>;
|
|
||||||
pub type Interner = intern::Interner<PictureKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod text_run {
|
|
||||||
common!();
|
|
||||||
use ::prim_store::text_run::{TextRunKey, TextRunTemplate};
|
|
||||||
pub type Store = intern::DataStore<TextRunKey, TextRunTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<TextRunKey>;
|
|
||||||
pub type Interner = intern::Interner<TextRunKey, PrimitiveSceneData, Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod filterdata {
|
|
||||||
common!();
|
|
||||||
use ::filterdata::{SFilterDataKey, SFilterDataTemplate};
|
|
||||||
pub type Store = intern::DataStore<SFilterDataKey, SFilterDataTemplate, Marker>;
|
|
||||||
pub type UpdateList = intern::UpdateList<SFilterDataKey>;
|
|
||||||
pub type Interner = intern::Interner<SFilterDataKey, (), Marker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,6 @@ mod gpu_types;
|
||||||
mod hit_test;
|
mod hit_test;
|
||||||
mod image;
|
mod image;
|
||||||
mod intern;
|
mod intern;
|
||||||
mod intern_types;
|
|
||||||
mod internal_types;
|
mod internal_types;
|
||||||
mod picture;
|
mod picture;
|
||||||
mod prim_store;
|
mod prim_store;
|
||||||
|
|
|
@ -3114,7 +3114,7 @@ impl PicturePrimitive {
|
||||||
PictureSurface::RenderTask(render_task_id)
|
PictureSurface::RenderTask(render_task_id)
|
||||||
}
|
}
|
||||||
PictureCompositeMode::ComponentTransferFilter(handle) => {
|
PictureCompositeMode::ComponentTransferFilter(handle) => {
|
||||||
let filter_data = &mut data_stores.filterdata[handle];
|
let filter_data = &mut data_stores.filter_data[handle];
|
||||||
filter_data.update(frame_state);
|
filter_data.update(frame_state);
|
||||||
|
|
||||||
let uv_rect_kind = calculate_uv_rect_kind(
|
let uv_rect_kind = calculate_uv_rect_kind(
|
||||||
|
|
|
@ -9,16 +9,15 @@ use api::{
|
||||||
};
|
};
|
||||||
use border::create_border_segments;
|
use border::create_border_segments;
|
||||||
use border::NormalBorderAu;
|
use border::NormalBorderAu;
|
||||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
use display_list_flattener::{CreateShadow, IsVisible};
|
||||||
use frame_builder::{FrameBuildingState};
|
use frame_builder::{FrameBuildingState};
|
||||||
use gpu_cache::GpuDataRequest;
|
use gpu_cache::GpuDataRequest;
|
||||||
use intern;
|
use intern;
|
||||||
use intern_types;
|
|
||||||
use prim_store::{
|
use prim_store::{
|
||||||
BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
|
BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
|
||||||
PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||||
PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
|
PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
|
||||||
PrimitiveStore
|
PrimitiveStore, InternablePrimitive,
|
||||||
};
|
};
|
||||||
use resource_cache::ImageRequest;
|
use resource_cache::ImageRequest;
|
||||||
use storage;
|
use storage;
|
||||||
|
@ -49,22 +48,6 @@ impl NormalBorderKey {
|
||||||
|
|
||||||
impl intern::InternDebug for NormalBorderKey {}
|
impl intern::InternDebug for NormalBorderKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<NormalBorderDataHandle> for NormalBorderKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: NormalBorderDataHandle,
|
|
||||||
_: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::NormalBorder {
|
|
||||||
data_handle,
|
|
||||||
cache_handles: storage::Range::empty(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -160,16 +143,16 @@ impl From<NormalBorderKey> for NormalBorderTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::normal_border::Handle as NormalBorderDataHandle;
|
pub type NormalBorderDataHandle = intern::Handle<NormalBorderPrim>;
|
||||||
|
|
||||||
impl intern::Internable for NormalBorderPrim {
|
impl intern::Internable for NormalBorderPrim {
|
||||||
type Marker = intern_types::normal_border::Marker;
|
type Key = NormalBorderKey;
|
||||||
type Source = NormalBorderKey;
|
|
||||||
type StoreData = NormalBorderTemplate;
|
type StoreData = NormalBorderTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for NormalBorderPrim {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> NormalBorderKey {
|
) -> NormalBorderKey {
|
||||||
|
@ -178,6 +161,18 @@ impl intern::Internable for NormalBorderPrim {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: NormalBorderKey,
|
||||||
|
data_handle: NormalBorderDataHandle,
|
||||||
|
_: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::NormalBorder {
|
||||||
|
data_handle,
|
||||||
|
cache_handles: storage::Range::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateShadow for NormalBorderPrim {
|
impl CreateShadow for NormalBorderPrim {
|
||||||
|
@ -225,20 +220,6 @@ impl ImageBorderKey {
|
||||||
|
|
||||||
impl intern::InternDebug for ImageBorderKey {}
|
impl intern::InternDebug for ImageBorderKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<ImageBorderDataHandle> for ImageBorderKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: ImageBorderDataHandle,
|
|
||||||
_: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::ImageBorder {
|
|
||||||
data_handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
|
@ -330,16 +311,16 @@ impl From<ImageBorderKey> for ImageBorderTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::image_border::Handle as ImageBorderDataHandle;
|
pub type ImageBorderDataHandle = intern::Handle<ImageBorder>;
|
||||||
|
|
||||||
impl intern::Internable for ImageBorder {
|
impl intern::Internable for ImageBorder {
|
||||||
type Marker = intern_types::image_border::Marker;
|
type Key = ImageBorderKey;
|
||||||
type Source = ImageBorderKey;
|
|
||||||
type StoreData = ImageBorderTemplate;
|
type StoreData = ImageBorderTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for ImageBorder {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> ImageBorderKey {
|
) -> ImageBorderKey {
|
||||||
|
@ -348,6 +329,17 @@ impl intern::Internable for ImageBorder {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: ImageBorderKey,
|
||||||
|
data_handle: ImageBorderDataHandle,
|
||||||
|
_: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::ImageBorder {
|
||||||
|
data_handle
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsVisible for ImageBorder {
|
impl IsVisible for ImageBorder {
|
||||||
|
|
|
@ -6,15 +6,14 @@ use api::{
|
||||||
ColorF, ColorU,ExtendMode, GradientStop, LayoutPoint, LayoutSize,
|
ColorF, ColorU,ExtendMode, GradientStop, LayoutPoint, LayoutSize,
|
||||||
LayoutPrimitiveInfo, PremultipliedColorF, LayoutVector2D,
|
LayoutPrimitiveInfo, PremultipliedColorF, LayoutVector2D,
|
||||||
};
|
};
|
||||||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
use display_list_flattener::IsVisible;
|
||||||
use frame_builder::FrameBuildingState;
|
use frame_builder::FrameBuildingState;
|
||||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||||
use intern::{Internable, InternDebug};
|
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||||
use intern_types;
|
|
||||||
use prim_store::{BrushSegment, GradientTileRange};
|
use prim_store::{BrushSegment, GradientTileRange};
|
||||||
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
|
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
|
||||||
use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
|
use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
|
||||||
use prim_store::{NinePatchDescriptor, PointKey, SizeKey};
|
use prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive};
|
||||||
use std::{hash, ops::{Deref, DerefMut}, mem};
|
use std::{hash, ops::{Deref, DerefMut}, mem};
|
||||||
use util::pack_as_float;
|
use util::pack_as_float;
|
||||||
|
|
||||||
|
@ -77,22 +76,6 @@ impl LinearGradientKey {
|
||||||
|
|
||||||
impl InternDebug for LinearGradientKey {}
|
impl InternDebug for LinearGradientKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<LinearGradientDataHandle> for LinearGradientKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: LinearGradientDataHandle,
|
|
||||||
_prim_store: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::LinearGradient {
|
|
||||||
data_handle,
|
|
||||||
visible_tiles_range: GradientTileRange::empty(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -227,8 +210,11 @@ impl LinearGradientTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LinearGradientDataHandle = intern_types::linear_grad::Handle;
|
pub type LinearGradientDataHandle = InternHandle<LinearGradient>;
|
||||||
|
|
||||||
|
#[derive(Debug, MallocSizeOf)]
|
||||||
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
pub struct LinearGradient {
|
pub struct LinearGradient {
|
||||||
pub extend_mode: ExtendMode,
|
pub extend_mode: ExtendMode,
|
||||||
pub start_point: PointKey,
|
pub start_point: PointKey,
|
||||||
|
@ -241,13 +227,13 @@ pub struct LinearGradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Internable for LinearGradient {
|
impl Internable for LinearGradient {
|
||||||
type Marker = intern_types::linear_grad::Marker;
|
type Key = LinearGradientKey;
|
||||||
type Source = LinearGradientKey;
|
|
||||||
type StoreData = LinearGradientTemplate;
|
type StoreData = LinearGradientTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for LinearGradient {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> LinearGradientKey {
|
) -> LinearGradientKey {
|
||||||
|
@ -257,6 +243,18 @@ impl Internable for LinearGradient {
|
||||||
self
|
self
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: LinearGradientKey,
|
||||||
|
data_handle: LinearGradientDataHandle,
|
||||||
|
_prim_store: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::LinearGradient {
|
||||||
|
data_handle,
|
||||||
|
visible_tiles_range: GradientTileRange::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsVisible for LinearGradient {
|
impl IsVisible for LinearGradient {
|
||||||
|
@ -326,22 +324,6 @@ impl RadialGradientKey {
|
||||||
|
|
||||||
impl InternDebug for RadialGradientKey {}
|
impl InternDebug for RadialGradientKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<RadialGradientDataHandle> for RadialGradientKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: RadialGradientDataHandle,
|
|
||||||
_prim_store: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::RadialGradient {
|
|
||||||
data_handle,
|
|
||||||
visible_tiles_range: GradientTileRange::empty(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -447,8 +429,11 @@ impl RadialGradientTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RadialGradientDataHandle = intern_types::radial_grad::Handle;
|
pub type RadialGradientDataHandle = InternHandle<RadialGradient>;
|
||||||
|
|
||||||
|
#[derive(Debug, MallocSizeOf)]
|
||||||
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
pub struct RadialGradient {
|
pub struct RadialGradient {
|
||||||
pub extend_mode: ExtendMode,
|
pub extend_mode: ExtendMode,
|
||||||
pub center: PointKey,
|
pub center: PointKey,
|
||||||
|
@ -460,13 +445,13 @@ pub struct RadialGradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Internable for RadialGradient {
|
impl Internable for RadialGradient {
|
||||||
type Marker = intern_types::radial_grad::Marker;
|
type Key = RadialGradientKey;
|
||||||
type Source = RadialGradientKey;
|
|
||||||
type StoreData = RadialGradientTemplate;
|
type StoreData = RadialGradientTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for RadialGradient {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> RadialGradientKey {
|
) -> RadialGradientKey {
|
||||||
|
@ -476,6 +461,18 @@ impl Internable for RadialGradient {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: RadialGradientKey,
|
||||||
|
data_handle: RadialGradientDataHandle,
|
||||||
|
_prim_store: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::RadialGradient {
|
||||||
|
data_handle,
|
||||||
|
visible_tiles_range: GradientTileRange::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsVisible for RadialGradient {
|
impl IsVisible for RadialGradient {
|
||||||
|
|
|
@ -8,16 +8,15 @@ use api::{
|
||||||
PremultipliedColorF, Shadow, TileOffset, YuvColorSpace, YuvFormat, LayoutVector2D,
|
PremultipliedColorF, Shadow, TileOffset, YuvColorSpace, YuvFormat, LayoutVector2D,
|
||||||
};
|
};
|
||||||
use api::ImageKey as ApiImageKey;
|
use api::ImageKey as ApiImageKey;
|
||||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
use display_list_flattener::{CreateShadow, IsVisible};
|
||||||
use frame_builder::FrameBuildingState;
|
use frame_builder::FrameBuildingState;
|
||||||
use gpu_cache::{GpuDataRequest};
|
use gpu_cache::{GpuDataRequest};
|
||||||
use intern::{Internable, InternDebug};
|
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||||
use intern_types;
|
|
||||||
use prim_store::{
|
use prim_store::{
|
||||||
EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
|
EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
|
||||||
PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
|
PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
|
||||||
PrimTemplate, PrimTemplateCommonData, PrimitiveStore, SegmentInstanceIndex,
|
PrimTemplate, PrimTemplateCommonData, PrimitiveStore, SegmentInstanceIndex,
|
||||||
SizeKey
|
SizeKey, InternablePrimitive,
|
||||||
};
|
};
|
||||||
use render_task::{
|
use render_task::{
|
||||||
BlitSource, RenderTask, RenderTaskCacheEntryHandle, RenderTaskCacheKey,
|
BlitSource, RenderTask, RenderTaskCacheEntryHandle, RenderTaskCacheKey,
|
||||||
|
@ -101,31 +100,6 @@ impl ImageKey {
|
||||||
|
|
||||||
impl InternDebug for ImageKey {}
|
impl InternDebug for ImageKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<ImageDataHandle> for ImageKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: ImageDataHandle,
|
|
||||||
prim_store: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
// TODO(gw): Refactor this to not need a separate image
|
|
||||||
// instance (see ImageInstance struct).
|
|
||||||
let image_instance_index = prim_store.images.push(ImageInstance {
|
|
||||||
opacity_binding_index: OpacityBindingIndex::INVALID,
|
|
||||||
segment_instance_index: SegmentInstanceIndex::INVALID,
|
|
||||||
tight_local_clip_rect: LayoutRect::zero(),
|
|
||||||
visible_tiles: Vec::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
PrimitiveInstanceKind::Image {
|
|
||||||
data_handle,
|
|
||||||
image_instance_index,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Where to find the texture data for an image primitive.
|
// Where to find the texture data for an image primitive.
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
|
@ -338,16 +312,16 @@ impl From<ImageKey> for ImageTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::image::Handle as ImageDataHandle;
|
pub type ImageDataHandle = InternHandle<Image>;
|
||||||
|
|
||||||
impl Internable for Image {
|
impl Internable for Image {
|
||||||
type Marker = intern_types::image::Marker;
|
type Key = ImageKey;
|
||||||
type Source = ImageKey;
|
|
||||||
type StoreData = ImageTemplate;
|
type StoreData = ImageTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for Image {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> ImageKey {
|
) -> ImageKey {
|
||||||
|
@ -357,6 +331,27 @@ impl Internable for Image {
|
||||||
self
|
self
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: ImageKey,
|
||||||
|
data_handle: ImageDataHandle,
|
||||||
|
prim_store: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
// TODO(gw): Refactor this to not need a separate image
|
||||||
|
// instance (see ImageInstance struct).
|
||||||
|
let image_instance_index = prim_store.images.push(ImageInstance {
|
||||||
|
opacity_binding_index: OpacityBindingIndex::INVALID,
|
||||||
|
segment_instance_index: SegmentInstanceIndex::INVALID,
|
||||||
|
tight_local_clip_rect: LayoutRect::zero(),
|
||||||
|
visible_tiles: Vec::new(),
|
||||||
|
});
|
||||||
|
|
||||||
|
PrimitiveInstanceKind::Image {
|
||||||
|
data_handle,
|
||||||
|
image_instance_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateShadow for Image {
|
impl CreateShadow for Image {
|
||||||
|
@ -413,22 +408,6 @@ impl YuvImageKey {
|
||||||
|
|
||||||
impl InternDebug for YuvImageKey {}
|
impl InternDebug for YuvImageKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<YuvImageDataHandle> for YuvImageKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: YuvImageDataHandle,
|
|
||||||
_prim_store: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::YuvImage {
|
|
||||||
data_handle,
|
|
||||||
segment_instance_index: SegmentInstanceIndex::INVALID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -505,25 +484,37 @@ impl From<YuvImageKey> for YuvImageTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::yuv_image::Handle as YuvImageDataHandle;
|
pub type YuvImageDataHandle = InternHandle<YuvImage>;
|
||||||
|
|
||||||
impl Internable for YuvImage {
|
impl Internable for YuvImage {
|
||||||
type Marker = intern_types::yuv_image::Marker;
|
type Key = YuvImageKey;
|
||||||
type Source = YuvImageKey;
|
|
||||||
type StoreData = YuvImageTemplate;
|
type StoreData = YuvImageTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for YuvImage {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> YuvImageKey {
|
) -> YuvImageKey {
|
||||||
YuvImageKey::new(
|
YuvImageKey::new(
|
||||||
info.is_backface_visible,
|
info.is_backface_visible,
|
||||||
info.rect.size,
|
info.rect.size,
|
||||||
self
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: YuvImageKey,
|
||||||
|
data_handle: YuvImageDataHandle,
|
||||||
|
_prim_store: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::YuvImage {
|
||||||
|
data_handle,
|
||||||
|
segment_instance_index: SegmentInstanceIndex::INVALID
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsVisible for YuvImage {
|
impl IsVisible for YuvImage {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
// list of all interned primitives to match enumerate_interners!
|
||||||
|
|
||||||
|
pub use prim_store::borders::{ImageBorder, NormalBorderPrim};
|
||||||
|
pub use prim_store::image::{Image, YuvImage};
|
||||||
|
pub use prim_store::line_dec::{LineDecoration};
|
||||||
|
pub use prim_store::gradient::{LinearGradient, RadialGradient};
|
||||||
|
pub use prim_store::picture::Picture;
|
||||||
|
pub use prim_store::text_run::TextRun;
|
|
@ -7,17 +7,17 @@ use api::{
|
||||||
LineOrientation, LineStyle, PremultipliedColorF, Shadow,
|
LineOrientation, LineStyle, PremultipliedColorF, Shadow,
|
||||||
};
|
};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
use display_list_flattener::{CreateShadow, IsVisible};
|
||||||
use frame_builder::{FrameBuildingState};
|
use frame_builder::{FrameBuildingState};
|
||||||
use gpu_cache::GpuDataRequest;
|
use gpu_cache::GpuDataRequest;
|
||||||
use intern;
|
use intern;
|
||||||
use intern_types;
|
|
||||||
use prim_store::{
|
use prim_store::{
|
||||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||||
PrimitiveSceneData, PrimitiveStore,
|
InternablePrimitive, PrimitiveSceneData, PrimitiveStore,
|
||||||
};
|
};
|
||||||
use prim_store::PrimitiveInstanceKind;
|
use prim_store::PrimitiveInstanceKind;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
|
#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
|
@ -59,22 +59,6 @@ impl LineDecorationKey {
|
||||||
|
|
||||||
impl intern::InternDebug for LineDecorationKey {}
|
impl intern::InternDebug for LineDecorationKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<LineDecorationDataHandle> for LineDecorationKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: LineDecorationDataHandle,
|
|
||||||
_: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
PrimitiveInstanceKind::LineDecoration {
|
|
||||||
data_handle,
|
|
||||||
cache_handle: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -135,16 +119,16 @@ impl From<LineDecorationKey> for LineDecorationTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::line_decoration::Handle as LineDecorationDataHandle;
|
pub type LineDecorationDataHandle = intern::Handle<LineDecoration>;
|
||||||
|
|
||||||
impl intern::Internable for LineDecoration {
|
impl intern::Internable for LineDecoration {
|
||||||
type Marker = intern_types::line_decoration::Marker;
|
type Key = LineDecorationKey;
|
||||||
type Source = LineDecorationKey;
|
|
||||||
type StoreData = LineDecorationTemplate;
|
type StoreData = LineDecorationTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for LineDecoration {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> LineDecorationKey {
|
) -> LineDecorationKey {
|
||||||
|
@ -153,6 +137,18 @@ impl intern::Internable for LineDecoration {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: LineDecorationKey,
|
||||||
|
data_handle: LineDecorationDataHandle,
|
||||||
|
_: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
PrimitiveInstanceKind::LineDecoration {
|
||||||
|
data_handle,
|
||||||
|
cache_handle: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateShadow for LineDecoration {
|
impl CreateShadow for LineDecoration {
|
||||||
|
|
|
@ -2,15 +2,12 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{BorderRadius, ClipMode, ColorF, PictureRect, ColorU, LayoutVector2D};
|
use api::{BorderRadius, ClipMode, ColorF};
|
||||||
use api::{DeviceIntRect, DevicePixelScale, DeviceRect, WorldVector2D};
|
|
||||||
use api::{FilterOp, ImageRendering, TileOffset, RepeatMode, WorldPoint, WorldSize};
|
use api::{FilterOp, ImageRendering, TileOffset, RepeatMode, WorldPoint, WorldSize};
|
||||||
use api::{LayoutPoint, LayoutRect, LayoutSideOffsets, LayoutSize, PicturePoint};
|
use api::{PremultipliedColorF, PropertyBinding, Shadow};
|
||||||
use api::{PremultipliedColorF, PropertyBinding, Shadow, DeviceVector2D};
|
use api::{BoxShadowClipMode, LineStyle, LineOrientation, AuHelpers};
|
||||||
use api::{WorldPixel, BoxShadowClipMode, WorldRect, LayoutToWorldScale};
|
use api::{LayoutPrimitiveInfo, PrimitiveKeyKind};
|
||||||
use api::{PicturePixel, RasterPixel, LineStyle, LineOrientation, AuHelpers};
|
use api::units::*;
|
||||||
use api::{LayoutPrimitiveInfo};
|
|
||||||
use api::DevicePoint;
|
|
||||||
use border::{get_max_scale_for_border, build_border_instances};
|
use border::{get_max_scale_for_border, build_border_instances};
|
||||||
use border::BorderSegmentCacheKey;
|
use border::BorderSegmentCacheKey;
|
||||||
use clip::{ClipStore};
|
use clip::{ClipStore};
|
||||||
|
@ -18,7 +15,7 @@ use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex
|
||||||
use clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance, ClipItem};
|
use clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance, ClipItem};
|
||||||
use debug_colors;
|
use debug_colors;
|
||||||
use debug_render::DebugItem;
|
use debug_render::DebugItem;
|
||||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
use display_list_flattener::{CreateShadow, IsVisible};
|
||||||
use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D};
|
use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D};
|
||||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||||
use frame_builder::{PrimitiveContext, FrameVisibilityContext, FrameVisibilityState};
|
use frame_builder::{PrimitiveContext, FrameVisibilityContext, FrameVisibilityState};
|
||||||
|
@ -60,6 +57,7 @@ pub mod image;
|
||||||
pub mod line_dec;
|
pub mod line_dec;
|
||||||
pub mod picture;
|
pub mod picture;
|
||||||
pub mod text_run;
|
pub mod text_run;
|
||||||
|
pub mod interned;
|
||||||
|
|
||||||
/// Counter for unique primitive IDs for debug tracing.
|
/// Counter for unique primitive IDs for debug tracing.
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -329,19 +327,6 @@ pub struct PrimitiveSceneData {
|
||||||
pub is_backface_visible: bool,
|
pub is_backface_visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information specific to a primitive type that
|
|
||||||
/// uniquely identifies a primitive template by key.
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
|
||||||
#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
|
|
||||||
pub enum PrimitiveKeyKind {
|
|
||||||
/// Clear an existing rect, used for special effects on some platforms.
|
|
||||||
Clear,
|
|
||||||
Rectangle {
|
|
||||||
color: ColorU,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
|
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
|
||||||
|
@ -634,32 +619,6 @@ impl PrimitiveKey {
|
||||||
|
|
||||||
impl intern::InternDebug for PrimitiveKey {}
|
impl intern::InternDebug for PrimitiveKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<PrimitiveDataHandle> for PrimitiveKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: PrimitiveDataHandle,
|
|
||||||
_: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
match self.kind {
|
|
||||||
PrimitiveKeyKind::Clear => {
|
|
||||||
PrimitiveInstanceKind::Clear {
|
|
||||||
data_handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PrimitiveKeyKind::Rectangle { .. } => {
|
|
||||||
PrimitiveInstanceKind::Rectangle {
|
|
||||||
data_handle,
|
|
||||||
opacity_binding_index: OpacityBindingIndex::INVALID,
|
|
||||||
segment_instance_index: SegmentInstanceIndex::INVALID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The shared information for a given primitive. This is interned and retained
|
/// The shared information for a given primitive. This is interned and retained
|
||||||
/// both across frames and display lists, by comparing the matching PrimitiveKey.
|
/// both across frames and display lists, by comparing the matching PrimitiveKey.
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
@ -675,9 +634,9 @@ pub enum PrimitiveTemplateKind {
|
||||||
/// Construct the primitive template data from a primitive key. This
|
/// Construct the primitive template data from a primitive key. This
|
||||||
/// is invoked when a primitive key is created and the interner
|
/// is invoked when a primitive key is created and the interner
|
||||||
/// doesn't currently contain a primitive with this key.
|
/// doesn't currently contain a primitive with this key.
|
||||||
impl PrimitiveKeyKind {
|
impl From<PrimitiveKeyKind> for PrimitiveTemplateKind {
|
||||||
fn into_template(self) -> PrimitiveTemplateKind {
|
fn from(kind: PrimitiveKeyKind) -> Self {
|
||||||
match self {
|
match kind {
|
||||||
PrimitiveKeyKind::Clear => {
|
PrimitiveKeyKind::Clear => {
|
||||||
PrimitiveTemplateKind::Clear
|
PrimitiveTemplateKind::Clear
|
||||||
}
|
}
|
||||||
|
@ -746,10 +705,10 @@ impl ops::DerefMut for PrimitiveTemplate {
|
||||||
|
|
||||||
impl From<PrimitiveKey> for PrimitiveTemplate {
|
impl From<PrimitiveKey> for PrimitiveTemplate {
|
||||||
fn from(item: PrimitiveKey) -> Self {
|
fn from(item: PrimitiveKey) -> Self {
|
||||||
let common = PrimTemplateCommonData::with_key_common(item.common);
|
PrimitiveTemplate {
|
||||||
let kind = item.kind.into_template();
|
common: PrimTemplateCommonData::with_key_common(item.common),
|
||||||
|
kind: item.kind.into(),
|
||||||
PrimitiveTemplate { common, kind, }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,13 +754,16 @@ impl PrimitiveTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PrimitiveDataHandle = intern::Handle<PrimitiveKeyKind>;
|
||||||
|
|
||||||
impl intern::Internable for PrimitiveKeyKind {
|
impl intern::Internable for PrimitiveKeyKind {
|
||||||
type Marker = ::intern_types::prim::Marker;
|
type Key = PrimitiveKey;
|
||||||
type Source = PrimitiveKey;
|
|
||||||
type StoreData = PrimitiveTemplate;
|
type StoreData = PrimitiveTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
fn build_key(
|
impl InternablePrimitive for PrimitiveKeyKind {
|
||||||
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> PrimitiveKey {
|
) -> PrimitiveKey {
|
||||||
|
@ -811,9 +773,29 @@ impl intern::Internable for PrimitiveKeyKind {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
use intern_types::prim::Handle as PrimitiveDataHandle;
|
fn make_instance_kind(
|
||||||
|
key: PrimitiveKey,
|
||||||
|
data_handle: PrimitiveDataHandle,
|
||||||
|
_: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
match key.kind {
|
||||||
|
PrimitiveKeyKind::Clear => {
|
||||||
|
PrimitiveInstanceKind::Clear {
|
||||||
|
data_handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrimitiveKeyKind::Rectangle { .. } => {
|
||||||
|
PrimitiveInstanceKind::Rectangle {
|
||||||
|
data_handle,
|
||||||
|
opacity_binding_index: OpacityBindingIndex::INVALID,
|
||||||
|
segment_instance_index: SegmentInstanceIndex::INVALID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Maintains a list of opacity bindings that have been collapsed into
|
// Maintains a list of opacity bindings that have been collapsed into
|
||||||
// the color of a single primitive. This is an important optimization
|
// the color of a single primitive. This is an important optimization
|
||||||
|
@ -3706,6 +3688,24 @@ fn update_opacity_binding(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for primitives that are directly internable.
|
||||||
|
/// see DisplayListFlattener::add_primitive<P>
|
||||||
|
pub trait InternablePrimitive: intern::Internable<InternData = PrimitiveSceneData> + Sized {
|
||||||
|
/// Build a new key from self with `info`.
|
||||||
|
fn into_key(
|
||||||
|
self,
|
||||||
|
info: &LayoutPrimitiveInfo,
|
||||||
|
) -> Self::Key;
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
key: Self::Key,
|
||||||
|
data_handle: intern::Handle<Self>,
|
||||||
|
prim_store: &mut PrimitiveStore,
|
||||||
|
reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
fn test_struct_sizes() {
|
fn test_struct_sizes() {
|
||||||
|
|
|
@ -8,13 +8,13 @@ use api::{
|
||||||
};
|
};
|
||||||
use intern::ItemUid;
|
use intern::ItemUid;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
use display_list_flattener::IsVisible;
|
||||||
use intern::{Internable, InternDebug};
|
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||||
use intern_types;
|
|
||||||
use picture::PictureCompositeMode;
|
use picture::PictureCompositeMode;
|
||||||
use prim_store::{
|
use prim_store::{
|
||||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||||
PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
|
PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
|
||||||
|
InternablePrimitive,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a hashable description of how a picture primitive
|
/// Represents a hashable description of how a picture primitive
|
||||||
|
@ -161,21 +161,6 @@ impl PictureKey {
|
||||||
|
|
||||||
impl InternDebug for PictureKey {}
|
impl InternDebug for PictureKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<PictureDataHandle> for PictureKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
_: PictureDataHandle,
|
|
||||||
_: &mut PrimitiveStore,
|
|
||||||
_reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
// Should never be hit as this method should not be
|
|
||||||
// called for pictures.
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -194,25 +179,36 @@ impl From<PictureKey> for PictureTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::picture::Handle as PictureDataHandle;
|
pub type PictureDataHandle = InternHandle<Picture>;
|
||||||
|
|
||||||
impl Internable for Picture {
|
impl Internable for Picture {
|
||||||
type Marker = intern_types::picture::Marker;
|
type Key = PictureKey;
|
||||||
type Source = PictureKey;
|
|
||||||
type StoreData = PictureTemplate;
|
type StoreData = PictureTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for Picture {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> PictureKey {
|
) -> PictureKey {
|
||||||
PictureKey::new(
|
PictureKey::new(
|
||||||
info.is_backface_visible,
|
info.is_backface_visible,
|
||||||
info.rect.size,
|
info.rect.size,
|
||||||
self
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
_key: PictureKey,
|
||||||
|
_: PictureDataHandle,
|
||||||
|
_: &mut PrimitiveStore,
|
||||||
|
_reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
// Should never be hit as this method should not be
|
||||||
|
// called for pictures.
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsVisible for Picture {
|
impl IsVisible for Picture {
|
||||||
|
|
|
@ -5,20 +5,19 @@
|
||||||
use api::{ColorF, DevicePixelScale, GlyphInstance, LayoutPrimitiveInfo};
|
use api::{ColorF, DevicePixelScale, GlyphInstance, LayoutPrimitiveInfo};
|
||||||
use api::{LayoutToWorldTransform, RasterSpace};
|
use api::{LayoutToWorldTransform, RasterSpace};
|
||||||
use api::{LayoutVector2D, Shadow};
|
use api::{LayoutVector2D, Shadow};
|
||||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
use display_list_flattener::{CreateShadow, IsVisible};
|
||||||
use frame_builder::{FrameBuildingState, PictureContext};
|
use frame_builder::{FrameBuildingState, PictureContext};
|
||||||
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||||
use gpu_cache::GpuCache;
|
use gpu_cache::GpuCache;
|
||||||
use gpu_types::RasterizationSpace;
|
use gpu_types::RasterizationSpace;
|
||||||
use intern;
|
use intern;
|
||||||
use intern_types;
|
|
||||||
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
|
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
|
||||||
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData};
|
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData};
|
||||||
use render_task::{RenderTaskTree};
|
use render_task::{RenderTaskTree};
|
||||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||||
use resource_cache::{ResourceCache};
|
use resource_cache::{ResourceCache};
|
||||||
use util::{MatrixHelpers};
|
use util::{MatrixHelpers};
|
||||||
use prim_store::PrimitiveInstanceKind;
|
use prim_store::{InternablePrimitive, PrimitiveInstanceKind};
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use storage;
|
use storage;
|
||||||
|
@ -53,28 +52,6 @@ impl TextRunKey {
|
||||||
|
|
||||||
impl intern::InternDebug for TextRunKey {}
|
impl intern::InternDebug for TextRunKey {}
|
||||||
|
|
||||||
impl AsInstanceKind<TextRunDataHandle> for TextRunKey {
|
|
||||||
/// Construct a primitive instance that matches the type
|
|
||||||
/// of primitive key.
|
|
||||||
fn as_instance_kind(
|
|
||||||
&self,
|
|
||||||
data_handle: TextRunDataHandle,
|
|
||||||
prim_store: &mut PrimitiveStore,
|
|
||||||
reference_frame_relative_offset: LayoutVector2D,
|
|
||||||
) -> PrimitiveInstanceKind {
|
|
||||||
let run_index = prim_store.text_runs.push(TextRunPrimitive {
|
|
||||||
used_font: self.font.clone(),
|
|
||||||
glyph_keys_range: storage::Range::empty(),
|
|
||||||
reference_frame_relative_offset,
|
|
||||||
shadow: self.shadow,
|
|
||||||
raster_space: RasterizationSpace::Screen,
|
|
||||||
inverse_raster_scale: 1.0,
|
|
||||||
});
|
|
||||||
|
|
||||||
PrimitiveInstanceKind::TextRun{ data_handle, run_index }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
#[derive(MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
|
@ -157,22 +134,26 @@ impl TextRunTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use intern_types::text_run::Handle as TextRunDataHandle;
|
pub type TextRunDataHandle = intern::Handle<TextRun>;
|
||||||
|
|
||||||
|
#[derive(Debug, MallocSizeOf)]
|
||||||
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
pub struct TextRun {
|
pub struct TextRun {
|
||||||
pub font: FontInstance,
|
pub font: FontInstance,
|
||||||
|
#[ignore_malloc_size_of = "Measured via PrimaryArc"]
|
||||||
pub glyphs: Arc<Vec<GlyphInstance>>,
|
pub glyphs: Arc<Vec<GlyphInstance>>,
|
||||||
pub shadow: bool,
|
pub shadow: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl intern::Internable for TextRun {
|
impl intern::Internable for TextRun {
|
||||||
type Marker = intern_types::text_run::Marker;
|
type Key = TextRunKey;
|
||||||
type Source = TextRunKey;
|
|
||||||
type StoreData = TextRunTemplate;
|
type StoreData = TextRunTemplate;
|
||||||
type InternData = PrimitiveSceneData;
|
type InternData = PrimitiveSceneData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a new key from self with `info`.
|
impl InternablePrimitive for TextRun {
|
||||||
fn build_key(
|
fn into_key(
|
||||||
self,
|
self,
|
||||||
info: &LayoutPrimitiveInfo,
|
info: &LayoutPrimitiveInfo,
|
||||||
) -> TextRunKey {
|
) -> TextRunKey {
|
||||||
|
@ -181,6 +162,24 @@ impl intern::Internable for TextRun {
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_instance_kind(
|
||||||
|
key: TextRunKey,
|
||||||
|
data_handle: TextRunDataHandle,
|
||||||
|
prim_store: &mut PrimitiveStore,
|
||||||
|
reference_frame_relative_offset: LayoutVector2D,
|
||||||
|
) -> PrimitiveInstanceKind {
|
||||||
|
let run_index = prim_store.text_runs.push(TextRunPrimitive {
|
||||||
|
used_font: key.font.clone(),
|
||||||
|
glyph_keys_range: storage::Range::empty(),
|
||||||
|
reference_frame_relative_offset,
|
||||||
|
shadow: key.shadow,
|
||||||
|
raster_space: RasterizationSpace::Screen,
|
||||||
|
inverse_raster_scale: 1.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
PrimitiveInstanceKind::TextRun{ data_handle, run_index }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateShadow for TextRun {
|
impl CreateShadow for TextRun {
|
||||||
|
|
|
@ -453,7 +453,7 @@ pub struct IpcProfileCounters {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! declare_intern_profile_counters {
|
macro_rules! declare_intern_profile_counters {
|
||||||
( $( $name: ident, )+ ) => {
|
( $( $name:ident : $ty:ty, )+ ) => {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct InternProfileCounters {
|
pub struct InternProfileCounters {
|
||||||
$(
|
$(
|
||||||
|
@ -522,6 +522,7 @@ impl BackendProfileCounters {
|
||||||
total_time: TimeProfileCounter::new("Total Display List Time", false),
|
total_time: TimeProfileCounter::new("Total Display List Time", false),
|
||||||
display_lists: ResourceProfileCounter::new("Display Lists Sent"),
|
display_lists: ResourceProfileCounter::new("Display Lists Sent"),
|
||||||
},
|
},
|
||||||
|
//TODO: generate this by a macro
|
||||||
intern: InternProfileCounters {
|
intern: InternProfileCounters {
|
||||||
prim: ResourceProfileCounter::new("Interned primitives"),
|
prim: ResourceProfileCounter::new("Interned primitives"),
|
||||||
image: ResourceProfileCounter::new("Interned images"),
|
image: ResourceProfileCounter::new("Interned images"),
|
||||||
|
@ -534,7 +535,7 @@ impl BackendProfileCounters {
|
||||||
text_run: ResourceProfileCounter::new("Interned text runs"),
|
text_run: ResourceProfileCounter::new("Interned text runs"),
|
||||||
yuv_image: ResourceProfileCounter::new("Interned YUV images"),
|
yuv_image: ResourceProfileCounter::new("Interned YUV images"),
|
||||||
clip: ResourceProfileCounter::new("Interned clips"),
|
clip: ResourceProfileCounter::new("Interned clips"),
|
||||||
filterdata: ResourceProfileCounter::new("Interned filterdata"),
|
filter_data: ResourceProfileCounter::new("Interned filter data"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче