зеркало из 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
|
||||
// appropriate MIME-type headers and then prompt the user with a
|
||||
// file picker
|
||||
function saveAsListener() {}
|
||||
function saveAsListener(principal) {
|
||||
this._triggeringPrincipal = principal;
|
||||
}
|
||||
saveAsListener.prototype = {
|
||||
extListener: null,
|
||||
|
||||
|
@ -1146,7 +1148,7 @@ nsContextMenu.prototype = {
|
|||
// do it the old fashioned way, which will pick the best filename
|
||||
// it can without waiting.
|
||||
saveURL(linkURL, linkText, dialogTitle, bypassCache, false, docURI,
|
||||
doc, isContentWindowPrivate);
|
||||
doc, isContentWindowPrivate, this._triggeringPrincipal);
|
||||
}
|
||||
if (this.extListener)
|
||||
this.extListener.onStopRequest(aRequest, aStatusCode);
|
||||
|
@ -1226,7 +1228,7 @@ nsContextMenu.prototype = {
|
|||
timer.TYPE_ONE_SHOT);
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.tab-icon-pending[preopened],
|
||||
.tab-icon-image[preopened] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tab-sharing-icon-overlay[sharing]:not([selected]),
|
||||
.tab-icon-overlay[soundplaying][pinned],
|
||||
.tab-icon-overlay[muted][pinned],
|
||||
|
|
|
@ -32,6 +32,7 @@ window._gBrowser = {
|
|||
window.addEventListener("occlusionstatechange", this);
|
||||
|
||||
this._setupInitialBrowserAndTab();
|
||||
this._preopenPinnedTabs();
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
|
||||
this.tabpanels.style.backgroundColor = "-moz-default-background-color";
|
||||
|
@ -383,6 +384,29 @@ window._gBrowser = {
|
|||
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
|
||||
* MAKE SURE TO ADD IT HERE AS WELL.
|
||||
|
@ -593,14 +617,32 @@ window._gBrowser = {
|
|||
this.tabContainer._updateCloseButtons();
|
||||
},
|
||||
|
||||
_notifyPinnedStatus(aTab) {
|
||||
_sendPinnedTabContentMessage(aTab) {
|
||||
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: aTab.pinned });
|
||||
},
|
||||
|
||||
_notifyPinnedStatus(aTab, aDeferContentMessage = false) {
|
||||
if (!aDeferContentMessage) {
|
||||
this._sendPinnedTabContentMessage(aTab);
|
||||
}
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent(aTab.pinned ? "TabPinned" : "TabUnpinned", true, false);
|
||||
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) {
|
||||
if (aTab.pinned)
|
||||
return;
|
||||
|
@ -612,6 +654,7 @@ window._gBrowser = {
|
|||
aTab.setAttribute("pinned", "true");
|
||||
this._updateTabBarForPinnedTabs();
|
||||
this._notifyPinnedStatus(aTab);
|
||||
this._maybeUpdateNumPinnedTabsPref();
|
||||
},
|
||||
|
||||
unpinTab(aTab) {
|
||||
|
@ -623,6 +666,7 @@ window._gBrowser = {
|
|||
aTab.style.marginInlineStart = "";
|
||||
this._updateTabBarForPinnedTabs();
|
||||
this._notifyPinnedStatus(aTab);
|
||||
this._maybeUpdateNumPinnedTabsPref();
|
||||
},
|
||||
|
||||
previewTab(aTab, aCallback) {
|
||||
|
@ -2306,6 +2350,7 @@ window._gBrowser = {
|
|||
forceNotRemote,
|
||||
fromExternal,
|
||||
index,
|
||||
isForFirstWindowRestore,
|
||||
lazyTabTitle,
|
||||
name,
|
||||
nextTabParentId,
|
||||
|
@ -2489,6 +2534,9 @@ window._gBrowser = {
|
|||
|
||||
if (pinned) {
|
||||
this._updateTabBarForPinnedTabs();
|
||||
if (!isForFirstWindowRestore) {
|
||||
this._maybeUpdateNumPinnedTabsPref();
|
||||
}
|
||||
}
|
||||
this.tabContainer._setPositionalAttributes();
|
||||
|
||||
|
@ -2568,13 +2616,15 @@ window._gBrowser = {
|
|||
userContextId);
|
||||
b.registeredOpenURI = lazyBrowserURI;
|
||||
}
|
||||
SessionStore.setTabState(t, {
|
||||
entries: [{
|
||||
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
|
||||
title: lazyTabTitle,
|
||||
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
|
||||
}],
|
||||
});
|
||||
if (!isForFirstWindowRestore) {
|
||||
SessionStore.setTabState(t, {
|
||||
entries: [{
|
||||
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
|
||||
title: lazyTabTitle,
|
||||
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
|
||||
}],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._insertBrowser(t, true);
|
||||
}
|
||||
|
@ -2612,7 +2662,9 @@ window._gBrowser = {
|
|||
|
||||
// If we didn't swap docShells with a preloaded browser
|
||||
// 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
|
||||
// the document successfully loads
|
||||
if (aURI && !gInitialPages.includes(aURI)) {
|
||||
|
@ -2665,7 +2717,7 @@ window._gBrowser = {
|
|||
|
||||
// Additionally send pinned tab events
|
||||
if (pinned) {
|
||||
this._notifyPinnedStatus(t);
|
||||
this._notifyPinnedStatus(t, isForFirstWindowRestore);
|
||||
}
|
||||
|
||||
return t;
|
||||
|
@ -3163,8 +3215,10 @@ window._gBrowser = {
|
|||
this.tabs[i]._tPos = i;
|
||||
|
||||
if (!this._windowIsClosing) {
|
||||
if (wasPinned)
|
||||
if (wasPinned) {
|
||||
this.tabContainer._positionPinnedTabs();
|
||||
this._maybeUpdateNumPinnedTabsPref();
|
||||
}
|
||||
|
||||
// update tab close buttons state
|
||||
this.tabContainer._updateCloseButtons();
|
||||
|
@ -3837,7 +3891,6 @@ window._gBrowser = {
|
|||
skipAnimation: true,
|
||||
index: aIndex,
|
||||
createLazyBrowser,
|
||||
allowInheritPrincipal: createLazyBrowser,
|
||||
};
|
||||
|
||||
let numPinned = this._numPinnedTabs;
|
||||
|
@ -5014,6 +5067,7 @@ class TabProgressListener {
|
|||
this.mTab.removeAttribute("crashed");
|
||||
}
|
||||
|
||||
this.mTab.removeAttribute("preopened");
|
||||
if (this._shouldShowProgress(aRequest)) {
|
||||
if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_RESTORING) &&
|
||||
aWebProgress && aWebProgress.isTopLevel) {
|
||||
|
|
|
@ -1937,10 +1937,10 @@
|
|||
anonid="tab-throbber"
|
||||
class="tab-throbber"
|
||||
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"
|
||||
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"
|
||||
class="tab-icon-image"
|
||||
validate="never"
|
||||
|
|
|
@ -66,7 +66,7 @@ add_task(async function() {
|
|||
// Click once:
|
||||
document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
|
||||
});
|
||||
await promiseWaitForCondition(() => !testTab.parentNode);
|
||||
await TestUtils.waitForCondition(() => !testTab.parentNode);
|
||||
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
|
||||
[browser_tabclose_grow.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_tabopen.js]
|
||||
skip-if = (verify && (os == 'mac'))
|
||||
|
|
|
@ -126,6 +126,30 @@ add_task(async function testGloballyBlockedOnNewWindow() {
|
|||
add_task(async function testBFCache() {
|
||||
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.loadURI(browser, AUTOPLAY_PAGE);
|
||||
await blockedIconShown(browser);
|
||||
|
|
|
@ -26,7 +26,7 @@ add_task(async function() {
|
|||
ok(!isFullscreenSizeMode(), "Should not be in fullscreen sizemode before we enter fullscreen.");
|
||||
|
||||
BrowserFullScreen();
|
||||
await waitForCondition(() => isFullscreenSizeMode());
|
||||
await TestUtils.waitForCondition(() => isFullscreenSizeMode());
|
||||
ok(fullscreenButton.checked, "Fullscreen button should be checked when in fullscreen.");
|
||||
|
||||
await startCustomizing();
|
||||
|
@ -41,7 +41,7 @@ add_task(async function() {
|
|||
|
||||
BrowserFullScreen();
|
||||
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.");
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
|
|
|
@ -249,8 +249,8 @@ var SessionStore = {
|
|||
return SessionStoreInternal.getWindowState(aWindow);
|
||||
},
|
||||
|
||||
setWindowState: function ss_setWindowState(aWindow, aState, aOverwrite) {
|
||||
SessionStoreInternal.setWindowState(aWindow, aState, aOverwrite);
|
||||
setWindowState: function ss_setWindowState(aWindow, aState, aOverwrite, aFirstWindow) {
|
||||
SessionStoreInternal.setWindowState(aWindow, aState, aOverwrite, aFirstWindow);
|
||||
},
|
||||
|
||||
getTabState: function ss_getTabState(aTab) {
|
||||
|
@ -731,6 +731,7 @@ var SessionStoreInternal = {
|
|||
this._prefBranch.addObserver("sessionstore.max_windows_undo", this, true);
|
||||
|
||||
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);
|
||||
|
||||
gResistFingerprintingEnabled = Services.prefs.getBoolPref("privacy.resistFingerprinting");
|
||||
|
@ -2499,12 +2500,15 @@ var SessionStoreInternal = {
|
|||
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) {
|
||||
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.
|
||||
this._notifyOfClosedObjectsChange();
|
||||
|
@ -3203,6 +3207,7 @@ var SessionStoreInternal = {
|
|||
if (!uriObj || (uriObj && !window.gBrowser.isLocalAboutURI(uriObj))) {
|
||||
tab.setAttribute("busy", "true");
|
||||
}
|
||||
tab.removeAttribute("preopened");
|
||||
|
||||
// Hack to ensure that the about:home, about:newtab, and about:welcome
|
||||
// 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));
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param aWindow
|
||||
|
@ -3650,7 +3685,7 @@ var SessionStoreInternal = {
|
|||
|
||||
// We need to keep track of the initially open tabs so that they
|
||||
// can be moved to the end of the restored tabs.
|
||||
let initialTabs;
|
||||
let initialTabs = [];
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
initialTabs = Array.slice(tabbrowser.tabs);
|
||||
}
|
||||
|
@ -3658,8 +3693,11 @@ var SessionStoreInternal = {
|
|||
// Get rid of tabs that aren't needed anymore.
|
||||
if (overwriteTabs) {
|
||||
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]);
|
||||
} else if (tabbrowser.tabs[i].hasAttribute("preopened")) {
|
||||
initialTabs.push(tabbrowser.tabs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3677,14 +3715,18 @@ var SessionStoreInternal = {
|
|||
// selecting a new tab.
|
||||
if (select &&
|
||||
tabbrowser.selectedTab.userContextId == userContextId) {
|
||||
tab = tabbrowser.selectedTab;
|
||||
if (!tabData.pinned) {
|
||||
tabbrowser.unpinTab(tab);
|
||||
}
|
||||
tab = this._updateRestoredSelectedTabPinnedState(aWindow, winData, t);
|
||||
|
||||
tabbrowser.moveTabToEnd();
|
||||
if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
|
||||
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.
|
||||
|
@ -3733,11 +3775,14 @@ var SessionStoreInternal = {
|
|||
}
|
||||
|
||||
// Move the originally open tabs to the end.
|
||||
if (initialTabs) {
|
||||
let endPosition = tabbrowser.tabs.length - 1;
|
||||
for (let i = 0; i < initialTabs.length; i++) {
|
||||
tabbrowser.unpinTab(initialTabs[i]);
|
||||
tabbrowser.moveTabTo(initialTabs[i], endPosition);
|
||||
let endPosition = tabbrowser.tabs.length - 1;
|
||||
for (let tab of initialTabs) {
|
||||
if (tab.hasAttribute("preopened") &&
|
||||
!tab.linkedPanel) {
|
||||
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++) {
|
||||
if (t != selectedIndex) {
|
||||
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_page_title.js]
|
||||
[browser_pending_tabs.js]
|
||||
[browser_preopened_apptabs.js]
|
||||
[browser_privatetabs.js]
|
||||
[browser_purge_shistory.js]
|
||||
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);
|
||||
}
|
||||
|
||||
async function setWindowState(win, state, overwrite = false) {
|
||||
ss.setWindowState(win, typeof state != "string" ? JSON.stringify(state) : state, overwrite);
|
||||
async function setWindowState(win, state, overwrite = false, firstWindow = false) {
|
||||
ss.setWindowState(win, typeof state != "string" ? JSON.stringify(state) : state,
|
||||
overwrite, firstWindow);
|
||||
await promiseWindowRestored(win);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,11 @@ function _untrackWindowOrder(window) {
|
|||
_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.
|
||||
var WindowHelper = {
|
||||
addWindow(window) {
|
||||
|
@ -138,6 +143,7 @@ var WindowHelper = {
|
|||
|
||||
_untrackWindowOrder(window);
|
||||
_trackWindowOrder(window);
|
||||
_trackPinnedTabs(window);
|
||||
|
||||
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
|
||||
},
|
||||
|
|
|
@ -185,6 +185,8 @@
|
|||
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-urlbar-sendToDevice:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
|
|
|
@ -13,7 +13,7 @@ const { bootstrap, L10N } = require("devtools-launchpad");
|
|||
|
||||
window.L10N = L10N;
|
||||
// $FlowIgnore:
|
||||
window.L10N.setBundle(require("../assets/panel/debugger.properties"));
|
||||
window.L10N.setBundle(require("../../../locales/en-US/debugger.properties"));
|
||||
|
||||
bootstrap(React, ReactDOM).then(connection => {
|
||||
onConnect(connection, require("devtools-source-map"), {
|
||||
|
|
|
@ -3193,8 +3193,8 @@ Toolbox.prototype = {
|
|||
* Opens source in style editor. Falls back to plain "view-source:".
|
||||
* @see devtools/client/shared/source-utils.js
|
||||
*/
|
||||
viewSourceInStyleEditor: function(sourceURL, sourceLine) {
|
||||
return viewSource.viewSourceInStyleEditor(this, sourceURL, sourceLine);
|
||||
viewSourceInStyleEditor: function(sourceURL, sourceLine, sourceColumn) {
|
||||
return viewSource.viewSourceInStyleEditor(this, sourceURL, sourceLine, sourceColumn);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,6 +95,7 @@ class DominatorTreeSiblingLinkClass extends Component {
|
|||
},
|
||||
dom.a(
|
||||
{
|
||||
className: "load-more-link",
|
||||
onClick: () => onLoadMoreSiblings(item),
|
||||
},
|
||||
L10N.getStr("tree-item.load-more")
|
||||
|
|
|
@ -21,11 +21,11 @@ var { gDevTools } = require("devtools/client/framework/devtools");
|
|||
* @return {Promise<boolean>}
|
||||
*/
|
||||
exports.viewSourceInStyleEditor = async function(toolbox, sourceURL,
|
||||
sourceLine) {
|
||||
sourceLine, sourceColumn) {
|
||||
const panel = await toolbox.loadTool("styleeditor");
|
||||
|
||||
try {
|
||||
await panel.selectStyleSheet(sourceURL, sourceLine);
|
||||
await panel.selectStyleSheet(sourceURL, sourceLine, sourceColumn);
|
||||
await toolbox.selectTool("styleeditor");
|
||||
return true;
|
||||
} 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(
|
||||
'AbstractTreeItem.jsm',
|
||||
'BarGraphWidget.js',
|
||||
'BreadcrumbsWidget.jsm',
|
||||
'Chart.js',
|
||||
'CubicBezierPresets.js',
|
||||
'CubicBezierWidget.js',
|
||||
'FastListWidget.js',
|
||||
'FilterWidget.js',
|
||||
'FlameGraph.js',
|
||||
'Graphs.js',
|
||||
|
|
|
@ -13,12 +13,6 @@
|
|||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
/* FastListWidget */
|
||||
|
||||
.fast-list-widget-container {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
--focus-cell-border-color: rgba(255,255,255,0.5);
|
||||
--row-alt-background-color: rgba(86, 117, 185, 0.15);
|
||||
--row-hover-background-color: rgba(86, 117, 185, 0.25);
|
||||
--link-color: var(--blue-40);
|
||||
--link-color-active: var(--blue-30);
|
||||
}
|
||||
|
||||
.theme-light {
|
||||
|
@ -17,6 +19,8 @@
|
|||
--focus-cell-border-color: rgba(0,0,0,0.3);
|
||||
--row-alt-background-color: rgba(76,158,217,0.1);
|
||||
--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 {
|
||||
|
@ -278,7 +282,7 @@ html, body, #app, #memory-tool {
|
|||
/**
|
||||
* Flex: contains a .heap-view-panel which needs to fill out all the
|
||||
* available space, horizontally and vertically.
|
||||
*/;
|
||||
*/
|
||||
display: flex;
|
||||
/**
|
||||
* Flexing to fill out remaining horizontal space. The preceeding sibling
|
||||
|
@ -550,6 +554,19 @@ html, body, #app, #memory-tool {
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -963,12 +963,18 @@ body {
|
|||
height: 10px;
|
||||
background: url("chrome://devtools/skin/images/arrow.svg") no-repeat center;
|
||||
background-size: 10px;
|
||||
transform: rotate(-90deg);
|
||||
/* Needed for alignment */
|
||||
margin-top: -1px;
|
||||
-moz-context-properties: fill;
|
||||
fill: var(--theme-icon-dimmed-color);
|
||||
}
|
||||
|
||||
.webconsole-app .tree .arrow.expanded,
|
||||
.webconsole-app .object-inspector .tree-node .arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
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 */
|
||||
|
||||
.side-menu-widget-container {
|
||||
|
|
|
@ -82,6 +82,21 @@ async function performTests() {
|
|||
is(getL10NContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
||||
"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);
|
||||
// Close the browser console.
|
||||
await HUDService.toggleBrowserConsole();
|
||||
|
|
|
@ -23,18 +23,29 @@ add_task(async function() {
|
|||
info("Test Copy URL menu item for text log");
|
||||
|
||||
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, () => {
|
||||
content.wrappedJSObject.console.log("simple text message");
|
||||
content.wrappedJSObject.stringLog();
|
||||
});
|
||||
let message = await onLogMessage;
|
||||
ok(message, "Text log found in the console");
|
||||
|
||||
info("Open and check the context menu for the logged text message");
|
||||
let menuPopup = await openContextMenu(hud, message.node);
|
||||
|
||||
let copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
||||
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);
|
||||
hud.ui.clearOutput();
|
||||
|
||||
|
|
|
@ -41,11 +41,12 @@ async function testViewSource(hud, toolbox, text) {
|
|||
info("style editor window focused");
|
||||
const href = frameLinkNode.getAttribute("data-url");
|
||||
const line = frameLinkNode.getAttribute("data-line");
|
||||
const column = frameLinkNode.getAttribute("data-column");
|
||||
ok(line, "found source line");
|
||||
|
||||
const editor = getEditorForHref(panel.UI, 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) {
|
||||
|
@ -72,13 +73,15 @@ function getEditorForHref(styleEditorUI, href) {
|
|||
return foundEditor;
|
||||
}
|
||||
|
||||
async function performLineCheck(styleEditorUI, editor, line) {
|
||||
async function checkCursorPosition(styleEditorUI, editor, line, column) {
|
||||
info("wait for source editor to load");
|
||||
// Get out of the styleeditor-selected event loop.
|
||||
await waitForTick();
|
||||
|
||||
is(editor.sourceEditor.getCursor().line, line,
|
||||
"correct line is selected");
|
||||
is(editor.sourceEditor.getCursor().ch, column,
|
||||
"correct column is selected");
|
||||
is(styleEditorUI.selectedStyleSheetIndex, editor.styleSheet.styleSheetIndex,
|
||||
"correct stylesheet is selected in the editor");
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ function createContextMenu(webConsoleUI, parentNode, {
|
|||
rootActorId,
|
||||
executionPoint,
|
||||
toolbox,
|
||||
url,
|
||||
}) {
|
||||
const win = parentNode.ownerDocument.defaultView;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -198,6 +198,9 @@ class WebConsoleWrapper {
|
|||
const messageEl = target.closest(".message");
|
||||
const clipboardText = getElementText(messageEl);
|
||||
|
||||
const linkEl = target.closest("a[href]");
|
||||
const url = linkEl && linkEl.href;
|
||||
|
||||
const messageVariable = target.closest(".objectBox");
|
||||
// Ensure that console.group and console.groupCollapsed commands are not captured
|
||||
const variableText = (messageVariable
|
||||
|
@ -233,6 +236,7 @@ class WebConsoleWrapper {
|
|||
rootActorId,
|
||||
executionPoint,
|
||||
toolbox: this.toolbox,
|
||||
url,
|
||||
});
|
||||
|
||||
// Emit the "menu-open" event for testing.
|
||||
|
@ -279,7 +283,8 @@ class WebConsoleWrapper {
|
|||
}),
|
||||
onViewSourceInStyleEditor: frame => this.toolbox.viewSourceInStyleEditor(
|
||||
frame.url,
|
||||
frame.line
|
||||
frame.line,
|
||||
frame.column
|
||||
).then(() => {
|
||||
this.telemetry.recordEvent("jump_to_source", "webconsole",
|
||||
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}) {
|
||||
if (isTopLevel) {
|
||||
this.stopAnimationPlayerUpdates();
|
||||
|
|
|
@ -3871,7 +3871,7 @@ Element* Document::GetRootElement() const {
|
|||
: GetRootElementInternal();
|
||||
}
|
||||
|
||||
nsIContent* Document::GetUnfocusedKeyEventTarget() { return GetRootElement(); }
|
||||
Element* Document::GetUnfocusedKeyEventTarget() { return GetRootElement(); }
|
||||
|
||||
Element* Document::GetRootElementInternal() const {
|
||||
// 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
|
||||
* content in the document.
|
||||
*/
|
||||
virtual nsIContent* GetUnfocusedKeyEventTarget();
|
||||
virtual Element* GetUnfocusedKeyEventTarget();
|
||||
|
||||
/**
|
||||
* Retrieve information about the viewport as a data structure.
|
||||
|
|
|
@ -7509,7 +7509,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
|||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = dataAsShmem;
|
||||
item->data() = std::move(dataAsShmem);
|
||||
} else if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
|
||||
// Images to be pasted on the clipboard are nsIInputStreams
|
||||
nsCString imageData;
|
||||
|
@ -7522,7 +7522,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
|||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = imageDataShmem;
|
||||
item->data() = std::move(imageDataShmem);
|
||||
} else if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
|
||||
// Images to be placed on the clipboard are imgIContainers.
|
||||
RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
|
||||
|
@ -7550,7 +7550,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
|||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
// Turn item->data() into an nsCString prior to accessing it.
|
||||
item->data() = surfaceData.ref();
|
||||
item->data() = std::move(surfaceData.ref());
|
||||
|
||||
IPCDataTransferImage& imageDetails = item->imageDetails();
|
||||
mozilla::gfx::IntSize size = dataSurface->GetSize();
|
||||
|
@ -7581,7 +7581,7 @@ void nsContentUtils::TransferableToIPCTransferable(
|
|||
IPCDataTransferItem* item =
|
||||
aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = type;
|
||||
item->data() = dataAsShmem;
|
||||
item->data() = std::move(dataAsShmem);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
|
@ -396,11 +396,21 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
||||
}
|
||||
|
||||
// Currently we query the CSP from the principal, but after
|
||||
// Bug 1529877 we should query the CSP from within GetURL and
|
||||
// store it as a member, similar to mTriggeringPrincipal.
|
||||
// Expanded Principals override the CSP of the document, hence we first check
|
||||
// if the triggeringPrincipal overrides the document's principal. If so, let's
|
||||
// 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;
|
||||
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);
|
||||
|
||||
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
|
||||
iframe1_bug426646.html
|
||||
iframe2_bug426646.html
|
||||
iframe_shared_compartment2a.html
|
||||
iframe_shared_compartment2b.html
|
||||
file1_setting_opener.html
|
||||
file2_setting_opener.html
|
||||
file3_setting_opener.html
|
||||
|
@ -791,6 +793,8 @@ skip-if = debug == false
|
|||
[test_settimeout_inner.html]
|
||||
[test_setTimeoutWith0.html]
|
||||
[test_setting_opener.html]
|
||||
[test_shared_compartment1.html]
|
||||
[test_shared_compartment2.html]
|
||||
[test_style_cssText.html]
|
||||
[test_text_wholeText.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();
|
||||
ReportToConsole(nsIScriptError::warningFlag, "BlockAutoplayError");
|
||||
mHasPlayEverBeenBlocked = true;
|
||||
mHasEverBeenBlockedForAutoplay = true;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::PlayInternal(bool aHandlingUserInput) {
|
||||
|
@ -5985,6 +5986,14 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement,
|
|||
mEventDeliveryPaused = false;
|
||||
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.
|
||||
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:
|
||||
// Helper class to measure times for playback telemetry stats
|
||||
class TimeDurationAccumulator {
|
||||
|
|
|
@ -755,7 +755,7 @@ void nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode) {
|
|||
}
|
||||
}
|
||||
|
||||
nsIContent* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
|
||||
Element* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
|
||||
if (nsGenericHTMLElement* body = GetBody()) {
|
||||
return body;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
|
||||
virtual bool IsWriting() override { return mWriteLevel != uint32_t(0); }
|
||||
|
||||
virtual nsIContent* GetUnfocusedKeyEventTarget() override;
|
||||
virtual Element* GetUnfocusedKeyEventTarget() override;
|
||||
|
||||
nsContentList* GetExistingForms() const { return mForms; }
|
||||
|
||||
|
|
|
@ -2018,7 +2018,7 @@ bool ContentChild::DeallocPPSMContentDownloaderChild(
|
|||
|
||||
PExternalHelperAppChild* ContentChild::AllocPExternalHelperAppChild(
|
||||
const OptionalURIParams& uri,
|
||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
|
@ -3555,7 +3555,7 @@ mozilla::ipc::IPCResult ContentChild::RecvSaveRecording(
|
|||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
|
||||
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) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
nsresult rv =
|
||||
|
|
|
@ -280,7 +280,7 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
PExternalHelperAppChild* AllocPExternalHelperAppChild(
|
||||
const OptionalURIParams& uri,
|
||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
|
@ -680,9 +680,8 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
mozilla::ipc::IPCResult RecvCrossProcessRedirect(
|
||||
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
|
||||
const OptionalLoadInfoArgs& aLoadInfoForwarder,
|
||||
const uint64_t& aChannelId, nsIURI* aOriginalURI,
|
||||
const uint64_t& aIdentifier);
|
||||
const Maybe<LoadInfoArgs>& aLoadInfoForwarder, const uint64_t& aChannelId,
|
||||
nsIURI* aOriginalURI, const uint64_t& aIdentifier);
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// Fetch the current number of pending input events.
|
||||
|
|
|
@ -3632,7 +3632,7 @@ bool ContentParent::DeallocPPSMContentDownloaderParent(
|
|||
|
||||
PExternalHelperAppParent* ContentParent::AllocPExternalHelperAppParent(
|
||||
const OptionalURIParams& uri,
|
||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
|
@ -3655,8 +3655,9 @@ bool ContentParent::DeallocPExternalHelperAppParent(
|
|||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvPExternalHelperAppConstructor(
|
||||
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
||||
const OptionalLoadInfoArgs& loadInfoArgs, const nsCString& aMimeContentType,
|
||||
const nsCString& aContentDisposition, const uint32_t& aContentDispositionHint,
|
||||
const Maybe<LoadInfoArgs>& loadInfoArgs, const nsCString& aMimeContentType,
|
||||
const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
const int64_t& aContentLength, const bool& aWasFileChannel,
|
||||
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) {
|
||||
|
|
|
@ -876,7 +876,7 @@ class ContentParent final : public PContentParent,
|
|||
|
||||
PExternalHelperAppParent* AllocPExternalHelperAppParent(
|
||||
const OptionalURIParams& aUri,
|
||||
const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
|
||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
|
@ -887,8 +887,9 @@ class ContentParent final : public PContentParent,
|
|||
|
||||
mozilla::ipc::IPCResult RecvPExternalHelperAppConstructor(
|
||||
PExternalHelperAppParent* actor, const OptionalURIParams& uri,
|
||||
const OptionalLoadInfoArgs& loadInfoArgs, const nsCString& aMimeContentType,
|
||||
const nsCString& aContentDisposition, const uint32_t& aContentDispositionHint,
|
||||
const Maybe<LoadInfoArgs>& loadInfoArgs,
|
||||
const nsCString& aMimeContentType, const nsCString& aContentDisposition,
|
||||
const uint32_t& aContentDispositionHint,
|
||||
const nsString& aContentDispositionFilename, const bool& aForceSave,
|
||||
const int64_t& aContentLength, const bool& aWasFileChannel,
|
||||
const OptionalURIParams& aReferrer, PBrowserParent* aBrowser) override;
|
||||
|
|
|
@ -773,7 +773,7 @@ child:
|
|||
async CrossProcessRedirect(uint32_t aRegistrarId,
|
||||
nsIURI aURI,
|
||||
uint32_t aNewLoadFlags,
|
||||
OptionalLoadInfoArgs aLoadInfo,
|
||||
LoadInfoArgs? aLoadInfo,
|
||||
uint64_t aChannelId,
|
||||
nsIURI aOriginalURI,
|
||||
uint64_t aIdentifier);
|
||||
|
@ -901,7 +901,7 @@ parent:
|
|||
async PPSMContentDownloader(uint32_t aCertType);
|
||||
|
||||
async PExternalHelperApp(OptionalURIParams uri,
|
||||
OptionalLoadInfoArgs loadInfoArgs,
|
||||
LoadInfoArgs? loadInfoArgs,
|
||||
nsCString aMimeContentType,
|
||||
nsCString aContentDisposition,
|
||||
uint32_t aContentDispositionHint,
|
||||
|
|
|
@ -671,7 +671,7 @@ mozilla::ipc::IPCResult ChromiumCDMChild::RecvDecrypt(
|
|||
// Success! Return the decrypted sample to parent.
|
||||
MOZ_ASSERT(!HasShmemOfSize(outputShmemSize));
|
||||
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
|
||||
// to the content process.
|
||||
autoDeallocateOutputShmem.release();
|
||||
|
@ -820,7 +820,7 @@ void ChromiumCDMChild::ReturnOutput(WidevineVideoFrame& aFrame) {
|
|||
CDMBuffer* base = reinterpret_cast<CDMBuffer*>(aFrame.FrameBuffer());
|
||||
if (base->AsShmemBuffer()) {
|
||||
ipc::Shmem shmem = base->AsShmemBuffer()->ExtractShmem();
|
||||
Unused << SendDecodedShmem(output, shmem);
|
||||
Unused << SendDecodedShmem(output, std::move(shmem));
|
||||
} else {
|
||||
MOZ_ASSERT(base->AsArrayBuffer());
|
||||
Unused << SendDecodedData(output, base->AsArrayBuffer()->ExtractBuffer());
|
||||
|
|
|
@ -270,7 +270,7 @@ bool ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer,
|
|||
? crypto.mIV
|
||||
: crypto.mConstantIV;
|
||||
aBuffer = gmp::CDMInputBuffer(
|
||||
shmem, crypto.mKeyId, iv, aSample->mTime.ToMicroseconds(),
|
||||
std::move(shmem), crypto.mKeyId, iv, aSample->mTime.ToMicroseconds(),
|
||||
aSample->mDuration.ToMicroseconds(), crypto.mPlainSizes,
|
||||
crypto.mEncryptedSizes, crypto.mCryptByteBlock, crypto.mSkipByteBlock,
|
||||
encryptionScheme);
|
||||
|
@ -291,7 +291,7 @@ bool ChromiumCDMParent::SendBufferToCDM(uint32_t aSizeInBytes) {
|
|||
if (!AllocShmem(aSizeInBytes, Shmem::SharedMemory::TYPE_BASIC, &shmem)) {
|
||||
return false;
|
||||
}
|
||||
if (!SendGiveBuffer(shmem)) {
|
||||
if (!SendGiveBuffer(std::move(shmem))) {
|
||||
DeallocShmem(shmem);
|
||||
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
|
||||
// another frame.
|
||||
if (!SendGiveBuffer(aShmem)) {
|
||||
if (!SendGiveBuffer(std::move(aShmem))) {
|
||||
mDecodePromise.RejectIfExists(
|
||||
MediaResult(NS_ERROR_OUT_OF_MEMORY,
|
||||
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
|
||||
// "falling off a cliff" with too low a number
|
||||
if (GetGmpFreelist(aClass).Length() > 10) {
|
||||
Dealloc(GetGmpFreelist(aClass)[0]);
|
||||
Dealloc(std::move(GetGmpFreelist(aClass)[0]));
|
||||
GetGmpFreelist(aClass).RemoveElementAt(0);
|
||||
// The allocation numbers will be fubar on the Child!
|
||||
mData->mGmpAllocated[aClass]--;
|
||||
|
|
|
@ -68,7 +68,7 @@ class GMPSharedMemManager {
|
|||
virtual bool Alloc(size_t aSize,
|
||||
ipc::Shmem::SharedMemory::SharedMemoryType aType,
|
||||
ipc::Shmem* aMem) = 0;
|
||||
virtual void Dealloc(ipc::Shmem& aMem) = 0;
|
||||
virtual void Dealloc(ipc::Shmem&& aMem) = 0;
|
||||
|
||||
private:
|
||||
nsTArray<ipc::Shmem>& GetGmpFreelist(GMPSharedMem::GMPMemoryClasses aTypes) {
|
||||
|
|
|
@ -207,9 +207,9 @@ bool GMPVideoDecoderChild::Alloc(size_t aSize,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void GMPVideoDecoderChild::Dealloc(Shmem& aMem) {
|
||||
void GMPVideoDecoderChild::Dealloc(Shmem&& aMem) {
|
||||
#ifndef SHMEM_ALLOC_IN_CHILD
|
||||
SendParentShmemForPool(aMem);
|
||||
SendParentShmemForPool(std::move(aMem));
|
||||
#else
|
||||
DeallocShmem(aMem);
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ class GMPVideoDecoderChild : public PGMPVideoDecoderChild,
|
|||
// GMPSharedMemManager
|
||||
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
||||
Shmem* aMem) override;
|
||||
void Dealloc(Shmem& aMem) override;
|
||||
void Dealloc(Shmem&& aMem) override;
|
||||
|
||||
private:
|
||||
virtual ~GMPVideoDecoderChild();
|
||||
|
|
|
@ -60,7 +60,7 @@ class GMPVideoDecoderParent final : public PGMPVideoDecoderParent,
|
|||
return AllocUnsafeShmem(aSize, aType, aMem);
|
||||
#endif
|
||||
}
|
||||
void Dealloc(Shmem& aMem) override { DeallocShmem(aMem); }
|
||||
void Dealloc(Shmem&& aMem) override { DeallocShmem(aMem); }
|
||||
|
||||
private:
|
||||
~GMPVideoDecoderParent();
|
||||
|
|
|
@ -199,9 +199,9 @@ bool GMPVideoEncoderChild::Alloc(size_t aSize,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void GMPVideoEncoderChild::Dealloc(Shmem& aMem) {
|
||||
void GMPVideoEncoderChild::Dealloc(Shmem&& aMem) {
|
||||
#ifndef SHMEM_ALLOC_IN_CHILD
|
||||
SendParentShmemForPool(aMem);
|
||||
SendParentShmemForPool(std::move(aMem));
|
||||
#else
|
||||
DeallocShmem(aMem);
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,7 @@ class GMPVideoEncoderChild : public PGMPVideoEncoderChild,
|
|||
// GMPSharedMemManager
|
||||
bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType,
|
||||
Shmem* aMem) override;
|
||||
void Dealloc(Shmem& aMem) override;
|
||||
void Dealloc(Shmem&& aMem) override;
|
||||
|
||||
private:
|
||||
virtual ~GMPVideoEncoderChild();
|
||||
|
|
|
@ -58,7 +58,7 @@ class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
|
|||
return AllocUnsafeShmem(aSize, aType, aMem);
|
||||
#endif
|
||||
}
|
||||
void Dealloc(Shmem& aMem) override { DeallocShmem(aMem); }
|
||||
void Dealloc(Shmem&& aMem) override { DeallocShmem(aMem); }
|
||||
|
||||
private:
|
||||
virtual ~GMPVideoEncoderParent(){};
|
||||
|
|
|
@ -114,7 +114,7 @@ void RemoteAudioDecoderParent::ProcessDecodedData(
|
|||
RemoteAudioDataIPDL output(
|
||||
MediaDataIPDL(data->mOffset, data->mTime, data->mTimecode,
|
||||
data->mDuration, data->mKeyframe),
|
||||
audio->mChannels, audio->mRate, audio->mChannelMap, buffer);
|
||||
audio->mChannels, audio->mRate, audio->mChannelMap, std::move(buffer));
|
||||
|
||||
Unused << SendOutput(output);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Decode(
|
|||
MediaRawDataIPDL sample(
|
||||
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
||||
aSample->mDuration, aSample->mKeyframe),
|
||||
buffer);
|
||||
std::move(buffer));
|
||||
SendInput(sample);
|
||||
|
||||
return mDecodePromise.Ensure(__func__);
|
||||
|
|
|
@ -184,7 +184,7 @@ void RemoteVideoDecoderParent::ProcessDecodedData(
|
|||
if (AllocShmem(image->GetDataSize(), Shmem::SharedMemory::TYPE_BASIC,
|
||||
&buffer) &&
|
||||
image->GetDataSize() == buffer.Size<uint8_t>()) {
|
||||
sdBuffer.data() = buffer;
|
||||
sdBuffer.data() = std::move(buffer);
|
||||
image->BuildSurfaceDescriptorBuffer(sdBuffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ RefPtr<MediaDataDecoder::DecodePromise> VideoDecoderChild::Decode(
|
|||
MediaRawDataIPDL sample(
|
||||
MediaDataIPDL(aSample->mOffset, aSample->mTime, aSample->mTimecode,
|
||||
aSample->mDuration, aSample->mKeyframe),
|
||||
buffer);
|
||||
std::move(buffer));
|
||||
SendInput(sample);
|
||||
return mDecodePromise.Ensure(__func__);
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ mozilla::ipc::IPCResult VideoDecoderManagerParent::RecvReadback(
|
|||
dt->Flush();
|
||||
|
||||
*aResult = SurfaceDescriptorBuffer(RGBDescriptor(size, format, true),
|
||||
MemoryOrShmem(buffer));
|
||||
MemoryOrShmem(std::move(buffer)));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -575,7 +575,7 @@ mozilla::ipc::IPCResult CamerasChild::RecvDeliverFrame(
|
|||
} else {
|
||||
LOG(("DeliverFrame called with dead callback"));
|
||||
}
|
||||
SendReleaseFrame(shmem);
|
||||
SendReleaseFrame(std::move(shmem));
|
||||
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
|
||||
memcpy(shMemBuff.GetBytes(), altbuffer, aProps.bufferSize());
|
||||
|
||||
if (!SendDeliverFrame(capEng, aStreamId, shMemBuff.Get(), aProps)) {
|
||||
if (!SendDeliverFrame(capEng, aStreamId, std::move(shMemBuff.Get()),
|
||||
aProps)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(buffer.Valid());
|
||||
// ShmemBuffer was available, we're all good. A single copy happened
|
||||
// in the original webrtc callback.
|
||||
if (!SendDeliverFrame(capEng, aStreamId, buffer.Get(), aProps)) {
|
||||
if (!SendDeliverFrame(capEng, aStreamId, std::move(buffer.Get()), aProps)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2722,8 +2722,8 @@ void PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface* surface,
|
|||
|
||||
// Need a holder since IPDL zaps the object for mysterious reasons.
|
||||
Shmem shmemHolder = bitmap->mShmem;
|
||||
SendShowDirectBitmap(shmemHolder, bitmap->mFormat, bitmap->mStride,
|
||||
bitmap->mSize, dirty);
|
||||
SendShowDirectBitmap(std::move(shmemHolder), bitmap->mFormat,
|
||||
bitmap->mStride, bitmap->mSize, dirty);
|
||||
break;
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
|
@ -3569,8 +3569,8 @@ bool PluginInstanceChild::ShowPluginFrame() {
|
|||
} else
|
||||
#endif
|
||||
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
|
||||
currSurf =
|
||||
static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
|
||||
currSurf = std::move(
|
||||
static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
|
||||
} else {
|
||||
MOZ_CRASH("Surface type is not remotable");
|
||||
return false;
|
||||
|
|
|
@ -849,8 +849,8 @@ mozilla::ipc::IPCResult PluginInstanceParent::RecvShow(
|
|||
}
|
||||
|
||||
if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
|
||||
*prevSurface =
|
||||
static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();
|
||||
*prevSurface = std::move(
|
||||
static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem());
|
||||
else
|
||||
*prevSurface = null_t();
|
||||
|
||||
|
@ -1161,7 +1161,7 @@ PluginInstanceParent::BackgroundDescriptor() {
|
|||
"Expected shared image surface");
|
||||
gfxSharedImageSurface* shmem =
|
||||
static_cast<gfxSharedImageSurface*>(mBackground.get());
|
||||
return shmem->GetShmem();
|
||||
return mozilla::plugins::SurfaceDescriptor(std::move(shmem->GetShmem()));
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, &handled,
|
||||
&mShSurface))
|
||||
if (!CallNPP_HandleEvent_Shmem(npremoteevent, std::move(mShSurface),
|
||||
&handled, &mShSurface))
|
||||
return false; // no good way to handle errors here...
|
||||
|
||||
if (!mShSurface.IsReadable()) {
|
||||
|
|
|
@ -530,7 +530,7 @@ bool PluginModuleChromeParent::InitCrashReporter() {
|
|||
}
|
||||
|
||||
NativeThreadId threadId;
|
||||
if (!CallInitCrashReporter(shmem, &threadId)) {
|
||||
if (!CallInitCrashReporter(std::move(shmem), &threadId)) {
|
||||
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.
|
||||
function getTestServerPort() {
|
||||
let portEnv = Cc["@mozilla.org/process/environment;1"]
|
||||
|
@ -10,52 +12,26 @@ function getTestServerPort() {
|
|||
return port;
|
||||
}
|
||||
|
||||
// Support for making sure we can talk to the invalid cert the server presents
|
||||
var CertOverrideListener = function(host, port, bits) {
|
||||
this.host = host;
|
||||
this.port = port || 443;
|
||||
this.bits = bits;
|
||||
};
|
||||
|
||||
CertOverrideListener.prototype = {
|
||||
host: null,
|
||||
bits: null,
|
||||
|
||||
getInterface: function(aIID) {
|
||||
return this.QueryInterface(aIID);
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.nsIBadCertListener2) ||
|
||||
aIID.equals(Ci.nsIInterfaceRequestor) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
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
|
||||
}
|
||||
function readFile(file) {
|
||||
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fstream.init(file, -1, 0, 0);
|
||||
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
|
||||
fstream.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function addCertFromFile(certdb, filename, trustString) {
|
||||
let certFile = do_get_file(filename, false);
|
||||
let pem = readFile(certFile)
|
||||
.replace(/-----BEGIN CERTIFICATE-----/, "")
|
||||
.replace(/-----END CERTIFICATE-----/, "")
|
||||
.replace(/[\r\n]/g, "");
|
||||
certdb.addCertFromBase64(pem, trustString);
|
||||
}
|
||||
|
||||
function trustHttp2CA() {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
addCertFromFile(certdb, "../../../../netwerk/test/unit/http2-ca.pem", "CTu,u,u");
|
||||
}
|
||||
|
|
|
@ -24,10 +24,7 @@ function run_test() {
|
|||
prefs.setBoolPref("dom.push.enabled", true);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
trustHttp2CA();
|
||||
|
||||
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");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
trustHttp2CA();
|
||||
|
||||
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.connection.enabled", true);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
trustHttp2CA();
|
||||
|
||||
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.connection.enabled", true);
|
||||
|
||||
addCertOverride("localhost", serverPort,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME);
|
||||
trustHttp2CA();
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
|
|
|
@ -88,7 +88,9 @@ UniquePtr<SurfaceFactory> GLScreenBuffer::CreateFactory(
|
|||
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel,
|
||||
mFlags);
|
||||
#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);
|
||||
} else {
|
||||
factory =
|
||||
|
|
|
@ -1168,9 +1168,9 @@ struct ParamTraits<mozilla::Array<T, Length>> {
|
|||
template <>
|
||||
struct ParamTraits<mozilla::gfx::PaintFragment> {
|
||||
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.mRecording);
|
||||
WriteParam(aMsg, std::move(aParam.mRecording));
|
||||
WriteParam(aMsg, aParam.mDependencies);
|
||||
}
|
||||
|
||||
|
|
|
@ -484,7 +484,8 @@ bool ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
|||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem));
|
||||
aOutDescriptor =
|
||||
SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(std::move(mShmem)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -143,6 +143,11 @@ already_AddRefed<SourceSurface> D3D11YCbCrImage::GetAsSourceSurface() {
|
|||
RefPtr<ID3D11Device> dev;
|
||||
texY->GetDevice(getter_AddRefs(dev));
|
||||
|
||||
if (!dev || dev != gfx::DeviceManagerDx::Get()->GetImageDevice()) {
|
||||
gfxCriticalError() << "D3D11Device is obsoleted";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Multithread> mt;
|
||||
hr = dev->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
|
||||
|
||||
|
|
|
@ -1204,7 +1204,7 @@ void LayerManagerComposite::HandlePixelsTarget() {
|
|||
gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
|
||||
Unused << mScreenPixelsTarget->SendScreenPixels(
|
||||
mem, ScreenIntSize(bufferWidth, bufferHeight));
|
||||
std::move(mem), ScreenIntSize(bufferWidth, bufferHeight));
|
||||
mScreenPixelsTarget = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -964,7 +964,7 @@ bool ShadowLayerForwarder::AllocSurfaceDescriptorWithCaps(
|
|||
return false;
|
||||
}
|
||||
|
||||
bufferDesc = shmem;
|
||||
bufferDesc = std::move(shmem);
|
||||
}
|
||||
|
||||
// Use an intermediate buffer by default. Skipping the intermediate buffer is
|
||||
|
|
|
@ -166,7 +166,7 @@ bool UiCompositorControllerChild::ToolbarPixelsToCompositor(
|
|||
return false;
|
||||
}
|
||||
|
||||
return SendToolbarPixelsToCompositor(aMem, aSize);
|
||||
return SendToolbarPixelsToCompositor(std::move(aMem), aSize);
|
||||
}
|
||||
|
||||
void UiCompositorControllerChild::Destroy() {
|
||||
|
|
|
@ -98,7 +98,8 @@ void WebRenderBridgeChild::UpdateResources(
|
|||
nsTArray<ipc::Shmem> largeShmems;
|
||||
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
||||
|
||||
this->SendUpdateResources(resourceUpdates, smallShmems, largeShmems);
|
||||
this->SendUpdateResources(resourceUpdates, smallShmems,
|
||||
std::move(largeShmems));
|
||||
}
|
||||
|
||||
void WebRenderBridgeChild::EndTransaction(
|
||||
|
@ -123,12 +124,12 @@ void WebRenderBridgeChild::EndTransaction(
|
|||
nsTArray<ipc::Shmem> largeShmems;
|
||||
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
||||
|
||||
this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
|
||||
GetFwdTransactionId(), aTransactionId, aContentSize,
|
||||
dlData, aDL.dl_desc, aScrollData, resourceUpdates,
|
||||
smallShmems, largeShmems, mIdNamespace,
|
||||
aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
||||
this->SendSetDisplayList(
|
||||
aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(),
|
||||
aTransactionId, aContentSize, std::move(dlData), aDL.dl_desc, aScrollData,
|
||||
resourceUpdates, smallShmems, std::move(largeShmems), mIdNamespace,
|
||||
aContainsSVGGroup, aVsyncId, aVsyncStartTime, aRefreshStartTime,
|
||||
aTxnStartTime, aTxnURL, fwdTime);
|
||||
|
||||
mParentCommands.Clear();
|
||||
mDestroyedActors.Clear();
|
||||
|
@ -158,8 +159,8 @@ void WebRenderBridgeChild::EndEmptyTransaction(
|
|||
this->SendEmptyTransaction(
|
||||
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
|
||||
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
|
||||
smallShmems, largeShmems, mIdNamespace, aVsyncId, aVsyncStartTime,
|
||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
||||
smallShmems, std::move(largeShmems), mIdNamespace, aVsyncId,
|
||||
aVsyncStartTime, aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
||||
mParentCommands.Clear();
|
||||
mDestroyedActors.Clear();
|
||||
mIsInTransaction = false;
|
||||
|
|
|
@ -1471,7 +1471,7 @@ impl AlphaBatchBuilder {
|
|||
.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 |
|
||||
((filter_data.data.r_func.to_int() << 28 |
|
||||
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
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, DeviceIntSize, LayoutPrimitiveInfo};
|
||||
use api::{LayoutRect, LayoutSize, LayoutVector2D, MAX_BLUR_RADIUS};
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, LayoutPrimitiveInfo, PrimitiveKeyKind};
|
||||
use api::MAX_BLUR_RADIUS;
|
||||
use api::units::*;
|
||||
use clip::ClipItemKey;
|
||||
use display_list_flattener::DisplayListFlattener;
|
||||
use gpu_cache::GpuCacheHandle;
|
||||
use gpu_types::BoxShadowStretchMode;
|
||||
use prim_store::{ScrollNodeAndClipChain, PrimitiveKeyKind};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use render_task::RenderTaskCacheEntryHandle;
|
||||
use util::RectHelpers;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS
|
|||
use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D};
|
||||
use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel};
|
||||
use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform};
|
||||
use api::{ImageKey};
|
||||
use api::{ClipIntern, ImageKey};
|
||||
use app_units::Au;
|
||||
use border::{ensure_no_corner_overlap, BorderRadiusAu};
|
||||
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.
|
||||
|
||||
pub use intern_types::clip::Store as ClipDataStore;
|
||||
use intern_types::clip::Handle as ClipDataHandle;
|
||||
pub type ClipDataStore = intern::DataStore<ClipIntern>;
|
||||
type ClipDataHandle = intern::Handle<ClipIntern>;
|
||||
|
||||
// Result of comparing a clip node instance against a local rect.
|
||||
#[derive(Debug)]
|
||||
|
@ -847,6 +847,12 @@ impl ClipItemKey {
|
|||
|
||||
impl intern::InternDebug for ClipItemKey {}
|
||||
|
||||
impl intern::Internable for ClipIntern {
|
||||
type Key = ClipItemKey;
|
||||
type StoreData = ClipNode;
|
||||
type InternData = ();
|
||||
}
|
||||
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
|
||||
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{DisplayItemRef, ExtendMode, ExternalScrollId, AuHelpers};
|
||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, GradientStop};
|
||||
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, ColorDepth};
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||
use api::{ClipId, ColorF, ComplexClipRegion, RasterSpace};
|
||||
use api::{DisplayItemRef, ExtendMode, ExternalScrollId};
|
||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
|
||||
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth};
|
||||
use api::{LayoutPrimitiveInfo, LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData, TempFilterData};
|
||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem};
|
||||
use api::{ClipMode, PrimitiveKeyKind, TransformStyle, YuvColorSpace, YuvData, TempFilterData};
|
||||
use api::units::*;
|
||||
use app_units::Au;
|
||||
use clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
|
||||
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 hit_test::{HitTestingItem, HitTestingRun};
|
||||
use image::simplify_repeated_primitive;
|
||||
use intern::{Handle, Internable, InternDebug};
|
||||
use intern::Interner;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
|
||||
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::{PrimitiveStoreStats, ScrollNodeAndClipChain, PictureIndex};
|
||||
use prim_store::InternablePrimitive;
|
||||
use prim_store::{register_prim_chase_id, get_line_decoration_sizes};
|
||||
use prim_store::borders::{ImageBorder, NormalBorderPrim};
|
||||
use prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
|
||||
|
@ -36,7 +37,7 @@ use prim_store::text_run::TextRun;
|
|||
use render_backend::{DocumentView};
|
||||
use resource_cache::{FontInstanceMap, ImageRequest};
|
||||
use scene::{Scene, StackingContextHelpers};
|
||||
use scene_builder::{InternerMut, Interners};
|
||||
use scene_builder::Interners;
|
||||
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
|
||||
use std::{f32, mem, usize};
|
||||
use std::collections::vec_deque::VecDeque;
|
||||
|
@ -1148,16 +1149,14 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
prim: P,
|
||||
) -> PrimitiveInstance
|
||||
where
|
||||
P: Internable<InternData=PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
{
|
||||
// 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 prim_data_handle =
|
||||
interner
|
||||
let interner = self.interners.as_mut();
|
||||
let prim_data_handle = interner
|
||||
.intern(&prim_key, || {
|
||||
PrimitiveSceneData {
|
||||
prim_size: info.rect.size,
|
||||
|
@ -1167,7 +1166,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
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,
|
||||
&mut self.prim_store,
|
||||
current_offset,
|
||||
|
@ -1228,9 +1228,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
prim: P,
|
||||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive + IsVisible,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
{
|
||||
if prim.is_visible() {
|
||||
let clip_chain_id = self.build_clip_chain(
|
||||
|
@ -1255,9 +1254,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
prim: P,
|
||||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive + IsVisible,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
ShadowItem: From<PendingPrimitive<P>>
|
||||
{
|
||||
// If a shadow context is not active, then add the primitive
|
||||
|
@ -1290,9 +1288,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
prim: P,
|
||||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
{
|
||||
let prim_instance = self.create_primitive(
|
||||
info,
|
||||
|
@ -1606,7 +1603,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
};
|
||||
|
||||
let handle = self.interners
|
||||
.filterdata
|
||||
.filter_data
|
||||
.intern(&filter_data_key, || ());
|
||||
PictureCompositeMode::ComponentTransferFilter(handle)
|
||||
}
|
||||
|
@ -2129,9 +2126,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
prims: &mut Vec<PrimitiveInstance>,
|
||||
)
|
||||
where
|
||||
P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive + CreateShadow,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
{
|
||||
// Offset the local rect and clip rect by the shadow offset.
|
||||
let mut info = pending_primitive.info.clone();
|
||||
|
@ -2156,9 +2152,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&mut self,
|
||||
pending_primitive: PendingPrimitive<P>,
|
||||
) where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
Interners: InternerMut<P>,
|
||||
P: InternablePrimitive + IsVisible,
|
||||
Interners: AsMut<Interner<P>>,
|
||||
{
|
||||
// For a normal primitive, if it has alpha > 0, then we add this
|
||||
// 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 {
|
||||
fn create_shadow(&self, shadow: &Shadow) -> Self;
|
||||
|
|
|
@ -7,10 +7,10 @@ use gpu_cache::{GpuCacheHandle};
|
|||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::GpuDataRequest;
|
||||
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)]
|
||||
#[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(
|
||||
func_comp: &SFilterDataComponent,
|
||||
request: &mut GpuDataRequest,
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
//! stored inside each handle. This is then used for
|
||||
//! cache invalidation.
|
||||
|
||||
use api::{LayoutPrimitiveInfo};
|
||||
use internal_types::FastHashMap;
|
||||
use malloc_size_of::MallocSizeOf;
|
||||
use profiler::ResourceProfileCounter;
|
||||
|
@ -79,15 +78,28 @@ impl ItemUid {
|
|||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Debug, Copy, Clone, MallocSizeOf)]
|
||||
pub struct Handle<M: Copy> {
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
pub struct Handle<I> {
|
||||
index: u32,
|
||||
epoch: Epoch,
|
||||
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 {
|
||||
self.uid
|
||||
}
|
||||
|
@ -118,46 +130,34 @@ pub trait InternDebug {
|
|||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(MallocSizeOf)]
|
||||
pub struct DataStore<S, T: MallocSizeOf, M> {
|
||||
items: Vec<Option<T>>,
|
||||
_source: PhantomData<S>,
|
||||
_marker: PhantomData<M>,
|
||||
pub struct DataStore<I: Internable> {
|
||||
items: Vec<Option<I::StoreData>>,
|
||||
}
|
||||
|
||||
impl<S, T, M> ::std::default::Default for DataStore<S, T, M>
|
||||
where
|
||||
S: Debug + MallocSizeOf,
|
||||
T: From<S> + MallocSizeOf,
|
||||
M: Debug
|
||||
{
|
||||
impl<I: Internable> Default for DataStore<I> {
|
||||
fn default() -> Self {
|
||||
DataStore {
|
||||
items: Vec::new(),
|
||||
_source: PhantomData,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T, M> DataStore<S, T, M>
|
||||
where
|
||||
S: Debug + MallocSizeOf,
|
||||
T: From<S> + MallocSizeOf,
|
||||
M: Debug
|
||||
{
|
||||
impl<I: Internable> DataStore<I> {
|
||||
/// Apply any updates from the scene builder thread to
|
||||
/// this data store.
|
||||
pub fn apply_updates(
|
||||
&mut self,
|
||||
update_list: UpdateList<S>,
|
||||
update_list: UpdateList<I::Key>,
|
||||
profile_counter: &mut ResourceProfileCounter,
|
||||
) {
|
||||
let mut data_iter = update_list.data.into_iter();
|
||||
for update in update_list.updates {
|
||||
match update.kind {
|
||||
UpdateKind::Insert => {
|
||||
self.items.entry(update.index).
|
||||
set(Some(T::from(data_iter.next().unwrap())));
|
||||
let value = data_iter.next().unwrap().into();
|
||||
self.items
|
||||
.entry(update.index)
|
||||
.set(Some(value));
|
||||
}
|
||||
UpdateKind::Remove => {
|
||||
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());
|
||||
|
||||
debug_assert!(data_iter.next().is_none());
|
||||
|
@ -173,27 +173,17 @@ where
|
|||
}
|
||||
|
||||
/// Retrieve an item from the store via handle
|
||||
impl<S, T, M> ops::Index<Handle<M>> for DataStore<S, T, M>
|
||||
where
|
||||
S: MallocSizeOf,
|
||||
T: MallocSizeOf,
|
||||
M: Copy
|
||||
{
|
||||
type Output = T;
|
||||
fn index(&self, handle: Handle<M>) -> &T {
|
||||
impl<I: Internable> ops::Index<Handle<I>> for DataStore<I> {
|
||||
type Output = I::StoreData;
|
||||
fn index(&self, handle: Handle<I>) -> &I::StoreData {
|
||||
self.items[handle.index as usize].as_ref().expect("Bad datastore lookup")
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve a mutable 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>
|
||||
where
|
||||
S: MallocSizeOf,
|
||||
T: MallocSizeOf,
|
||||
M: Copy
|
||||
{
|
||||
fn index_mut(&mut self, handle: Handle<M>) -> &mut T {
|
||||
impl<I: Internable> ops::IndexMut<Handle<I>> for DataStore<I> {
|
||||
fn index_mut(&mut self, handle: Handle<I>) -> &mut I::StoreData {
|
||||
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 = "replay", derive(Deserialize))]
|
||||
#[derive(MallocSizeOf)]
|
||||
pub struct Interner<S, D, M>
|
||||
where
|
||||
S: Eq + Hash + Clone + Debug + MallocSizeOf,
|
||||
D: MallocSizeOf,
|
||||
M: Copy + MallocSizeOf,
|
||||
{
|
||||
pub struct Interner<I: Internable> {
|
||||
/// 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.
|
||||
free_list: Vec<usize>,
|
||||
/// Pending list of updates that need to be applied.
|
||||
updates: Vec<Update>,
|
||||
/// Pending new data to insert.
|
||||
update_data: Vec<S>,
|
||||
update_data: Vec<I::Key>,
|
||||
/// The current epoch for the interner.
|
||||
current_epoch: Epoch,
|
||||
/// The information associated with each interned
|
||||
/// 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>
|
||||
where
|
||||
S: Eq + Hash + Clone + Debug + MallocSizeOf,
|
||||
D: MallocSizeOf,
|
||||
M: Copy + Debug + MallocSizeOf,
|
||||
{
|
||||
impl<I: Internable> Default for Interner<I> {
|
||||
fn default() -> Self {
|
||||
Interner {
|
||||
map: FastHashMap::default(),
|
||||
|
@ -245,12 +225,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, D, M> Interner<S, D, M>
|
||||
where
|
||||
S: Eq + Hash + Clone + Debug + InternDebug + MallocSizeOf,
|
||||
D: MallocSizeOf,
|
||||
M: Copy + Debug + MallocSizeOf
|
||||
{
|
||||
impl<I: Internable> Interner<I> {
|
||||
/// Intern a data structure, and return a handle to
|
||||
/// that data. The handle can then be stored in the
|
||||
/// frame builder, and safely accessed via the data
|
||||
|
@ -260,9 +235,9 @@ where
|
|||
/// key isn't already interned.
|
||||
pub fn intern<F>(
|
||||
&mut self,
|
||||
data: &S,
|
||||
f: F,
|
||||
) -> Handle<M> where F: FnOnce() -> D {
|
||||
data: &I::Key,
|
||||
fun: F,
|
||||
) -> Handle<I> where F: FnOnce() -> I::InternData {
|
||||
// Use get_mut rather than entry here to avoid
|
||||
// cloning the (sometimes large) key in the common
|
||||
// case, where the data already exists in the interner.
|
||||
|
@ -303,7 +278,7 @@ where
|
|||
|
||||
// Create the local data for this item that is
|
||||
// being interned.
|
||||
self.local_data.entry(index).set(f());
|
||||
self.local_data.entry(index).set(fun());
|
||||
|
||||
handle
|
||||
}
|
||||
|
@ -311,7 +286,7 @@ where
|
|||
/// Retrieve the pending list of updates for an interner
|
||||
/// that need to be applied to the data store. Also run
|
||||
/// 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 data = self.update_data.take_and_preallocate();
|
||||
|
||||
|
@ -354,30 +329,36 @@ where
|
|||
}
|
||||
|
||||
/// 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>
|
||||
where
|
||||
S: Eq + Clone + Hash + Debug + MallocSizeOf,
|
||||
D: MallocSizeOf,
|
||||
M: Copy + Debug + MallocSizeOf
|
||||
{
|
||||
type Output = D;
|
||||
fn index(&self, handle: Handle<M>) -> &D {
|
||||
impl<I: Internable> ops::Index<Handle<I>> for Interner<I> {
|
||||
type Output = I::InternData;
|
||||
fn index(&self, handle: Handle<I>) -> &I::InternData {
|
||||
&self.local_data[handle.index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement `Internable` for a type that wants participate in interning.
|
||||
///
|
||||
/// see DisplayListFlattener::add_interned_primitive<P>
|
||||
pub trait Internable {
|
||||
type Marker: Copy + Debug + MallocSizeOf;
|
||||
type Source: Eq + Hash + Clone + Debug + MallocSizeOf;
|
||||
type StoreData: From<Self::Source> + MallocSizeOf;
|
||||
type InternData: MallocSizeOf;
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> Self::Source;
|
||||
// The trick to make trait bounds configurable by features.
|
||||
mod dummy {
|
||||
#[cfg(not(feature = "capture"))]
|
||||
pub trait Serialize {}
|
||||
#[cfg(not(feature = "capture"))]
|
||||
impl<T> Serialize for T {}
|
||||
#[cfg(not(feature = "replay"))]
|
||||
pub trait Deserialize<'a> {}
|
||||
#[cfg(not(feature = "replay"))]
|
||||
impl<'a, T> Deserialize<'a> for T {}
|
||||
}
|
||||
#[cfg(feature = "capture")]
|
||||
use serde::Serialize as InternSerialize;
|
||||
#[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 image;
|
||||
mod intern;
|
||||
mod intern_types;
|
||||
mod internal_types;
|
||||
mod picture;
|
||||
mod prim_store;
|
||||
|
|
|
@ -3114,7 +3114,7 @@ impl PicturePrimitive {
|
|||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
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);
|
||||
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
|
|
|
@ -9,16 +9,15 @@ use api::{
|
|||
};
|
||||
use border::create_border_segments;
|
||||
use border::NormalBorderAu;
|
||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
||||
use display_list_flattener::{CreateShadow, IsVisible};
|
||||
use frame_builder::{FrameBuildingState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{
|
||||
BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
|
||||
PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
|
||||
PrimitiveStore
|
||||
PrimitiveStore, InternablePrimitive,
|
||||
};
|
||||
use resource_cache::ImageRequest;
|
||||
use storage;
|
||||
|
@ -49,22 +48,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 {
|
||||
type Marker = intern_types::normal_border::Marker;
|
||||
type Source = NormalBorderKey;
|
||||
type Key = NormalBorderKey;
|
||||
type StoreData = NormalBorderTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for NormalBorderPrim {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> NormalBorderKey {
|
||||
|
@ -178,6 +161,18 @@ impl intern::Internable for NormalBorderPrim {
|
|||
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 {
|
||||
|
@ -225,20 +220,6 @@ impl 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 = "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 {
|
||||
type Marker = intern_types::image_border::Marker;
|
||||
type Source = ImageBorderKey;
|
||||
type Key = ImageBorderKey;
|
||||
type StoreData = ImageBorderTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for ImageBorder {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> ImageBorderKey {
|
||||
|
@ -348,6 +329,17 @@ impl intern::Internable for ImageBorder {
|
|||
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 {
|
||||
|
|
|
@ -6,15 +6,14 @@ use api::{
|
|||
ColorF, ColorU,ExtendMode, GradientStop, LayoutPoint, LayoutSize,
|
||||
LayoutPrimitiveInfo, PremultipliedColorF, LayoutVector2D,
|
||||
};
|
||||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
||||
use display_list_flattener::IsVisible;
|
||||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||
use prim_store::{BrushSegment, GradientTileRange};
|
||||
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
|
||||
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 util::pack_as_float;
|
||||
|
||||
|
@ -77,22 +76,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 extend_mode: ExtendMode,
|
||||
pub start_point: PointKey,
|
||||
|
@ -241,13 +227,13 @@ pub struct LinearGradient {
|
|||
}
|
||||
|
||||
impl Internable for LinearGradient {
|
||||
type Marker = intern_types::linear_grad::Marker;
|
||||
type Source = LinearGradientKey;
|
||||
type Key = LinearGradientKey;
|
||||
type StoreData = LinearGradientTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for LinearGradient {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> LinearGradientKey {
|
||||
|
@ -257,6 +243,18 @@ impl Internable for LinearGradient {
|
|||
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 {
|
||||
|
@ -326,22 +324,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 extend_mode: ExtendMode,
|
||||
pub center: PointKey,
|
||||
|
@ -460,13 +445,13 @@ pub struct RadialGradient {
|
|||
}
|
||||
|
||||
impl Internable for RadialGradient {
|
||||
type Marker = intern_types::radial_grad::Marker;
|
||||
type Source = RadialGradientKey;
|
||||
type Key = RadialGradientKey;
|
||||
type StoreData = RadialGradientTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for RadialGradient {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> RadialGradientKey {
|
||||
|
@ -476,6 +461,18 @@ impl Internable for RadialGradient {
|
|||
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 {
|
||||
|
|
|
@ -8,16 +8,15 @@ use api::{
|
|||
PremultipliedColorF, Shadow, TileOffset, YuvColorSpace, YuvFormat, LayoutVector2D,
|
||||
};
|
||||
use api::ImageKey as ApiImageKey;
|
||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
||||
use display_list_flattener::{CreateShadow, IsVisible};
|
||||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::{GpuDataRequest};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||
use prim_store::{
|
||||
EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
|
||||
PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
|
||||
PrimTemplate, PrimTemplateCommonData, PrimitiveStore, SegmentInstanceIndex,
|
||||
SizeKey
|
||||
SizeKey, InternablePrimitive,
|
||||
};
|
||||
use render_task::{
|
||||
BlitSource, RenderTask, RenderTaskCacheEntryHandle, RenderTaskCacheKey,
|
||||
|
@ -101,31 +100,6 @@ impl 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.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[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 {
|
||||
type Marker = intern_types::image::Marker;
|
||||
type Source = ImageKey;
|
||||
type Key = ImageKey;
|
||||
type StoreData = ImageTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for Image {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> ImageKey {
|
||||
|
@ -357,6 +331,27 @@ impl Internable for Image {
|
|||
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 {
|
||||
|
@ -413,22 +408,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 {
|
||||
type Marker = intern_types::yuv_image::Marker;
|
||||
type Source = YuvImageKey;
|
||||
type Key = YuvImageKey;
|
||||
type StoreData = YuvImageTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for YuvImage {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> YuvImageKey {
|
||||
YuvImageKey::new(
|
||||
info.is_backface_visible,
|
||||
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 {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
use app_units::Au;
|
||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
||||
use display_list_flattener::{CreateShadow, IsVisible};
|
||||
use frame_builder::{FrameBuildingState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{
|
||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
PrimitiveSceneData, PrimitiveStore,
|
||||
InternablePrimitive, PrimitiveSceneData, PrimitiveStore,
|
||||
};
|
||||
use prim_store::PrimitiveInstanceKind;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -59,22 +59,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 {
|
||||
type Marker = intern_types::line_decoration::Marker;
|
||||
type Source = LineDecorationKey;
|
||||
type Key = LineDecorationKey;
|
||||
type StoreData = LineDecorationTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for LineDecoration {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> LineDecorationKey {
|
||||
|
@ -153,6 +137,18 @@ impl intern::Internable for LineDecoration {
|
|||
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 {
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
* 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 api::{BorderRadius, ClipMode, ColorF, PictureRect, ColorU, LayoutVector2D};
|
||||
use api::{DeviceIntRect, DevicePixelScale, DeviceRect, WorldVector2D};
|
||||
use api::{BorderRadius, ClipMode, ColorF};
|
||||
use api::{FilterOp, ImageRendering, TileOffset, RepeatMode, WorldPoint, WorldSize};
|
||||
use api::{LayoutPoint, LayoutRect, LayoutSideOffsets, LayoutSize, PicturePoint};
|
||||
use api::{PremultipliedColorF, PropertyBinding, Shadow, DeviceVector2D};
|
||||
use api::{WorldPixel, BoxShadowClipMode, WorldRect, LayoutToWorldScale};
|
||||
use api::{PicturePixel, RasterPixel, LineStyle, LineOrientation, AuHelpers};
|
||||
use api::{LayoutPrimitiveInfo};
|
||||
use api::DevicePoint;
|
||||
use api::{PremultipliedColorF, PropertyBinding, Shadow};
|
||||
use api::{BoxShadowClipMode, LineStyle, LineOrientation, AuHelpers};
|
||||
use api::{LayoutPrimitiveInfo, PrimitiveKeyKind};
|
||||
use api::units::*;
|
||||
use border::{get_max_scale_for_border, build_border_instances};
|
||||
use border::BorderSegmentCacheKey;
|
||||
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 debug_colors;
|
||||
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 frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||
use frame_builder::{PrimitiveContext, FrameVisibilityContext, FrameVisibilityState};
|
||||
|
@ -60,6 +57,7 @@ pub mod image;
|
|||
pub mod line_dec;
|
||||
pub mod picture;
|
||||
pub mod text_run;
|
||||
pub mod interned;
|
||||
|
||||
/// Counter for unique primitive IDs for debug tracing.
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -329,19 +327,6 @@ pub struct PrimitiveSceneData {
|
|||
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 = "replay", derive(Deserialize))]
|
||||
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
|
||||
|
@ -634,32 +619,6 @@ impl 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
|
||||
/// both across frames and display lists, by comparing the matching PrimitiveKey.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -675,9 +634,9 @@ pub enum PrimitiveTemplateKind {
|
|||
/// Construct the primitive template data from a primitive key. This
|
||||
/// is invoked when a primitive key is created and the interner
|
||||
/// doesn't currently contain a primitive with this key.
|
||||
impl PrimitiveKeyKind {
|
||||
fn into_template(self) -> PrimitiveTemplateKind {
|
||||
match self {
|
||||
impl From<PrimitiveKeyKind> for PrimitiveTemplateKind {
|
||||
fn from(kind: PrimitiveKeyKind) -> Self {
|
||||
match kind {
|
||||
PrimitiveKeyKind::Clear => {
|
||||
PrimitiveTemplateKind::Clear
|
||||
}
|
||||
|
@ -746,10 +705,10 @@ impl ops::DerefMut for PrimitiveTemplate {
|
|||
|
||||
impl From<PrimitiveKey> for PrimitiveTemplate {
|
||||
fn from(item: PrimitiveKey) -> Self {
|
||||
let common = PrimTemplateCommonData::with_key_common(item.common);
|
||||
let kind = item.kind.into_template();
|
||||
|
||||
PrimitiveTemplate { common, kind, }
|
||||
PrimitiveTemplate {
|
||||
common: PrimTemplateCommonData::with_key_common(item.common),
|
||||
kind: item.kind.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,13 +754,16 @@ impl PrimitiveTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
type PrimitiveDataHandle = intern::Handle<PrimitiveKeyKind>;
|
||||
|
||||
impl intern::Internable for PrimitiveKeyKind {
|
||||
type Marker = ::intern_types::prim::Marker;
|
||||
type Source = PrimitiveKey;
|
||||
type Key = PrimitiveKey;
|
||||
type StoreData = PrimitiveTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
fn build_key(
|
||||
impl InternablePrimitive for PrimitiveKeyKind {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> PrimitiveKey {
|
||||
|
@ -811,9 +773,29 @@ impl intern::Internable for PrimitiveKeyKind {
|
|||
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
|
||||
// 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]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn test_struct_sizes() {
|
||||
|
|
|
@ -8,13 +8,13 @@ use api::{
|
|||
};
|
||||
use intern::ItemUid;
|
||||
use app_units::Au;
|
||||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use display_list_flattener::IsVisible;
|
||||
use intern::{Internable, InternDebug, Handle as InternHandle};
|
||||
use picture::PictureCompositeMode;
|
||||
use prim_store::{
|
||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
|
||||
InternablePrimitive,
|
||||
};
|
||||
|
||||
/// Represents a hashable description of how a picture primitive
|
||||
|
@ -161,21 +161,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 {
|
||||
type Marker = intern_types::picture::Marker;
|
||||
type Source = PictureKey;
|
||||
type Key = PictureKey;
|
||||
type StoreData = PictureTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for Picture {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> PictureKey {
|
||||
PictureKey::new(
|
||||
info.is_backface_visible,
|
||||
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 {
|
||||
|
|
|
@ -5,20 +5,19 @@
|
|||
use api::{ColorF, DevicePixelScale, GlyphInstance, LayoutPrimitiveInfo};
|
||||
use api::{LayoutToWorldTransform, RasterSpace};
|
||||
use api::{LayoutVector2D, Shadow};
|
||||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
||||
use display_list_flattener::{CreateShadow, IsVisible};
|
||||
use frame_builder::{FrameBuildingState, PictureContext};
|
||||
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::RasterizationSpace;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
|
||||
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData};
|
||||
use render_task::{RenderTaskTree};
|
||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
use resource_cache::{ResourceCache};
|
||||
use util::{MatrixHelpers};
|
||||
use prim_store::PrimitiveInstanceKind;
|
||||
use prim_store::{InternablePrimitive, PrimitiveInstanceKind};
|
||||
use std::ops;
|
||||
use std::sync::Arc;
|
||||
use storage;
|
||||
|
@ -53,28 +52,6 @@ impl 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 = "replay", derive(Deserialize))]
|
||||
#[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 font: FontInstance,
|
||||
#[ignore_malloc_size_of = "Measured via PrimaryArc"]
|
||||
pub glyphs: Arc<Vec<GlyphInstance>>,
|
||||
pub shadow: bool,
|
||||
}
|
||||
|
||||
impl intern::Internable for TextRun {
|
||||
type Marker = intern_types::text_run::Marker;
|
||||
type Source = TextRunKey;
|
||||
type Key = TextRunKey;
|
||||
type StoreData = TextRunTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
}
|
||||
|
||||
/// Build a new key from self with `info`.
|
||||
fn build_key(
|
||||
impl InternablePrimitive for TextRun {
|
||||
fn into_key(
|
||||
self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
) -> TextRunKey {
|
||||
|
@ -181,6 +162,24 @@ impl intern::Internable for TextRun {
|
|||
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 {
|
||||
|
|
|
@ -453,7 +453,7 @@ pub struct IpcProfileCounters {
|
|||
}
|
||||
|
||||
macro_rules! declare_intern_profile_counters {
|
||||
( $( $name: ident, )+ ) => {
|
||||
( $( $name:ident : $ty:ty, )+ ) => {
|
||||
#[derive(Clone)]
|
||||
pub struct InternProfileCounters {
|
||||
$(
|
||||
|
@ -522,6 +522,7 @@ impl BackendProfileCounters {
|
|||
total_time: TimeProfileCounter::new("Total Display List Time", false),
|
||||
display_lists: ResourceProfileCounter::new("Display Lists Sent"),
|
||||
},
|
||||
//TODO: generate this by a macro
|
||||
intern: InternProfileCounters {
|
||||
prim: ResourceProfileCounter::new("Interned primitives"),
|
||||
image: ResourceProfileCounter::new("Interned images"),
|
||||
|
@ -534,7 +535,7 @@ impl BackendProfileCounters {
|
|||
text_run: ResourceProfileCounter::new("Interned text runs"),
|
||||
yuv_image: ResourceProfileCounter::new("Interned YUV images"),
|
||||
clip: ResourceProfileCounter::new("Interned clips"),
|
||||
filterdata: ResourceProfileCounter::new("Interned filterdata"),
|
||||
filter_data: ResourceProfileCounter::new("Interned filter data"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче