Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-09-24 12:07:23 +02:00
Родитель 706e18d0b6 2376775adf
Коммит 4a6b9ecd83
207 изменённых файлов: 4078 добавлений и 1217 удалений

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "8472f0c736660072799aaae60e4b6001a6aaceb4",
"git_revision": "4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "e4b5ba76d5a4de0cd220310e0fe2ba334f0e250a",
"revision": "0bdd0b54cb40d7e928e9e6de720c0506dc7e52db",
"repo_path": "integration/gaia-central"
}

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -14,6 +14,11 @@ var {
// WeakMap[Extension -> BrowserAction]
var browserActionMap = new WeakMap();
// WeakMap[Extension -> docshell]
// This map is a cache of the windowless browser that's used to render ImageData
// for the browser_action icon.
let imageRendererMap = new WeakMap();
function browserActionOf(extension)
{
return browserActionMap.get(extension);
@ -41,9 +46,6 @@ function BrowserAction(options, extension)
this.icon = new DefaultWeakMap(options.default_icon);
this.popup = new DefaultWeakMap(options.default_popup);
// Make the default something that won't compare equal to anything.
this.prevPopups = new DefaultWeakMap({});
this.context = null;
}
@ -63,12 +65,14 @@ BrowserAction.prototype = {
this.updateTab(null, node);
let tabbrowser = document.defaultView.gBrowser;
tabbrowser.ownerDocument.addEventListener("TabSelect", () => {
this.updateTab(tabbrowser.selectedTab, node);
});
tabbrowser.tabContainer.addEventListener("TabSelect", this);
node.addEventListener("command", event => {
if (node.getAttribute("type") != "panel") {
let tab = tabbrowser.selectedTab;
let popup = this.getProperty(tab, "popup");
if (popup) {
this.togglePopup(node, popup);
} else {
this.emit("click");
}
});
@ -79,6 +83,81 @@ BrowserAction.prototype = {
this.widget = widget;
},
handleEvent(event) {
if (event.type == "TabSelect") {
let window = event.target.ownerDocument.defaultView;
let tabbrowser = window.gBrowser;
let instance = CustomizableUI.getWidget(this.id).forWindow(window);
if (instance) {
this.updateTab(tabbrowser.selectedTab, instance.node);
}
}
},
togglePopup(node, popupResource) {
let popupURL = this.extension.baseURI.resolve(popupResource);
let document = node.ownerDocument;
let panel = document.createElement("panel");
panel.setAttribute("class", "browser-action-panel");
panel.setAttribute("type", "arrow");
panel.setAttribute("flip", "slide");
node.appendChild(panel);
panel.addEventListener("popuphidden", () => {
this.context.unload();
this.context = null;
panel.remove();
});
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let browser = document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
panel.appendChild(browser);
let loadListener = () => {
panel.removeEventListener("load", loadListener);
this.context = new ExtensionPage(this.extension, {
type: "popup",
contentWindow: browser.contentWindow,
uri: Services.io.newURI(popupURL, null, null),
docShell: browser.docShell,
});
GlobalManager.injectInDocShell(browser.docShell, this.extension, this.context);
browser.setAttribute("src", popupURL);
let contentLoadListener = () => {
browser.removeEventListener("load", contentLoadListener);
let contentViewer = browser.docShell.contentViewer;
let width = {}, height = {};
try {
contentViewer.getContentSize(width, height);
[width, height] = [width.value, height.value];
} catch (e) {
// getContentSize can throw
[width, height] = [400, 400];
}
let window = document.defaultView;
width /= window.devicePixelRatio;
height /= window.devicePixelRatio;
width = Math.min(width, 800);
height = Math.min(height, 800);
browser.setAttribute("width", width);
browser.setAttribute("height", height);
let anchor = document.getAnonymousElementByAttribute(node, "class", "toolbarbutton-icon");
panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
};
browser.addEventListener("load", contentLoadListener, true);
};
panel.addEventListener("load", loadListener);
},
// Initialize the toolbar icon and popup given that |tab| is the
// current tab and |node| is the CustomizableUI node. Note: |tab|
// will be null if we don't know the current tab yet (during
@ -118,57 +197,6 @@ BrowserAction.prototype = {
let iconURL = this.getIcon(tab, node);
node.setAttribute("image", iconURL);
let popup = this.getProperty(tab, "popup");
if (popup != this.prevPopups.get(window)) {
this.prevPopups.set(window, popup);
let panel = node.querySelector("panel");
if (panel) {
panel.remove();
}
if (popup) {
let popupURL = this.extension.baseURI.resolve(popup);
node.setAttribute("type", "panel");
let document = node.ownerDocument;
let panel = document.createElement("panel");
panel.setAttribute("class", "browser-action-panel");
panel.setAttribute("type", "arrow");
panel.setAttribute("flip", "slide");
node.appendChild(panel);
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let browser = document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("width", "500");
browser.setAttribute("height", "500");
panel.appendChild(browser);
let loadListener = () => {
panel.removeEventListener("load", loadListener);
if (this.context) {
this.context.unload();
}
this.context = new ExtensionPage(this.extension, {
type: "popup",
contentWindow: browser.contentWindow,
uri: Services.io.newURI(popupURL, null, null),
docShell: browser.docShell,
});
GlobalManager.injectInDocShell(browser.docShell, this.extension, this.context);
browser.setAttribute("src", popupURL);
};
panel.addEventListener("load", loadListener);
} else {
node.removeAttribute("type");
}
}
},
// Note: tab is allowed to be null here.
@ -236,6 +264,13 @@ BrowserAction.prototype = {
},
shutdown() {
let widget = CustomizableUI.getWidget(this.id);
for (let instance of widget.instances) {
let window = instance.node.ownerDocument.defaultView;
let tabbrowser = window.gBrowser;
tabbrowser.tabContainer.removeEventListener("TabSelect", this);
}
CustomizableUI.destroyWidget(this.id);
},
};
@ -253,8 +288,37 @@ extensions.on("shutdown", (type, extension) => {
browserActionMap.get(extension).shutdown();
browserActionMap.delete(extension);
}
imageRendererMap.delete(extension);
});
function convertImageDataToPNG(extension, imageData)
{
let webNav = imageRendererMap.get(extension);
if (!webNav) {
webNav = Services.appShell.createWindowlessBrowser(false);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(extension.baseURI,
{addonId: extension.id});
let interfaceRequestor = webNav.QueryInterface(Ci.nsIInterfaceRequestor);
let docShell = interfaceRequestor.getInterface(Ci.nsIDocShell);
GlobalManager.injectInDocShell(docShell, extension, null);
docShell.createAboutBlankContentViewer(principal);
}
let document = webNav.document;
let canvas = document.createElement("canvas");
canvas.width = imageData.width;
canvas.height = imageData.height;
canvas.getContext("2d").putImageData(imageData, 0, 0);
let url = canvas.toDataURL("image/png");
canvas.remove();
return url;
}
extensions.registerAPI((extension, context) => {
return {
browserAction: {
@ -283,10 +347,11 @@ extensions.registerAPI((extension, context) => {
setIcon: function(details, callback) {
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
if (details.imageData) {
// FIXME: Support the imageData attribute.
return;
let url = convertImageDataToPNG(extension, details.imageData);
browserActionOf(extension).setProperty(tab, "icon", url);
} else {
browserActionOf(extension).setProperty(tab, "icon", details.path);
}
browserActionOf(extension).setProperty(tab, "icon", details.path);
},
setBadgeText: function(details) {

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

@ -42,11 +42,18 @@ var pageDataMap = new WeakMap();
// in some tab-specific details and keep data around about the
// ExtensionPage.
extensions.on("page-load", (type, page, params, sender, delegate) => {
if (params.type == "tab") {
if (params.type == "tab" || params.type == "popup") {
let browser = params.docShell.chromeEventHandler;
let parentWindow = browser.ownerDocument.defaultView;
let tab = parentWindow.gBrowser.getTabForBrowser(browser);
sender.tabId = TabManager.getId(tab);
page.windowId = WindowManager.getId(parentWindow);
let tab = null;
if (params.type == "tab") {
tab = parentWindow.gBrowser.getTabForBrowser(browser);
sender.tabId = TabManager.getId(tab);
page.tabId = TabManager.getId(tab);
}
pageDataMap.set(page, {tab, parentWindow});
}
@ -63,7 +70,9 @@ extensions.on("page-shutdown", (type, page) => {
let {tab, parentWindow} = pageDataMap.get(page);
pageDataMap.delete(page);
parentWindow.gBrowser.removeTab(tab);
if (tab) {
parentWindow.gBrowser.removeTab(tab);
}
}
});
@ -77,6 +86,15 @@ extensions.on("fill-browser-data", (type, browser, data, result) => {
data.tabId = tabId;
});
global.currentWindow = function(context)
{
let pageData = pageDataMap.get(context);
if (pageData) {
return pageData.parentWindow;
}
return WindowManager.topWindow;
}
// TODO: activeTab permission
extensions.registerAPI((extension, context) => {
@ -257,7 +275,7 @@ extensions.registerAPI((extension, context) => {
}
}
let window = createProperties.windowId ?
let window = "windowId" in createProperties ?
WindowManager.getWindow(createProperties.windowId) :
WindowManager.topWindow;
if (!window.gBrowser) {
@ -382,7 +400,7 @@ extensions.registerAPI((extension, context) => {
if ("windowId" in queryInfo) {
if (queryInfo.windowId == WindowManager.WINDOW_ID_CURRENT) {
if (context.contentWindow != window) {
if (currentWindow(context) != window) {
return false;
}
} else {
@ -393,7 +411,7 @@ extensions.registerAPI((extension, context) => {
}
if ("currentWindow" in queryInfo) {
let eq = window == context.contentWindow;
let eq = window == currentWindow(context);
if (queryInfo.currentWindow != eq) {
return false;
}
@ -406,6 +424,9 @@ extensions.registerAPI((extension, context) => {
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let window = e.getNext();
if (window.document.readyState != "complete") {
continue;
}
let tabs = TabManager.getTabs(extension, window);
for (let tab of tabs) {
if (matches(window, tab)) {

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

@ -45,7 +45,11 @@ extensions.registerAPI((extension, context) => {
},
getCurrent: function(getInfo, callback) {
let window = context.contentWindow;
if (!callback) {
callback = getInfo;
getInfo = {};
}
let window = currentWindow(context);
runSafe(context, callback, WindowManager.convert(extension, window, getInfo));
},
@ -65,7 +69,9 @@ extensions.registerAPI((extension, context) => {
let windows = [];
while (e.hasMoreElements()) {
let window = e.getNext();
windows.push(WindowManager.convert(extension, window, getInfo));
if (window.document.readyState == "complete") {
windows.push(WindowManager.convert(extension, window, getInfo));
}
}
runSafe(context, callback, windows);
},

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

@ -1,8 +1,13 @@
[DEFAULT]
skip-if = os == 'android' || buildapp == 'b2g' || os == 'mac'
support-files =
head.js
[browser_extensions_simple.js]
[browser_ext_simple.js]
[browser_ext_currentWindow.js]
[browser_ext_browserAction_simple.js]
[browser_ext_browserAction_icon.js]
[browser_ext_getViews.js]
[browser_ext_tabs_executeScript.js]
[browser_ext_tabs_query.js]
[browser_ext_tabs_update.js]

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

@ -0,0 +1,40 @@
add_task(function* () {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {},
"background": {
"page": "background.html",
}
},
files: {
"background.html": `<canvas id="canvas" width="2" height="2">
<script src="background.js"></script>`,
"background.js": function() {
var canvas = document.getElementById("canvas");
var canvasContext = canvas.getContext("2d");
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
canvasContext.fillStyle = "green";
canvasContext.fillRect(0, 0, 1, 1);
var url = canvas.toDataURL("image/png");
var imageData = canvasContext.getImageData(0, 0, canvas.width, canvas.height);
browser.browserAction.setIcon({imageData});
browser.test.sendMessage("imageURL", url);
}
},
});
let [_, url] = yield Promise.all([extension.startup(), extension.awaitMessage("imageURL")]);
let widgetId = makeWidgetId(extension.id) + "-browser-action";
let node = CustomizableUI.getWidget(widgetId).forWindow(window).node;
let image = node.getAttribute("image");
is(image, url, "image is correct");
yield extension.unload();
});

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

@ -22,15 +22,31 @@ add_task(function* () {
background: function() {
browser.runtime.onMessage.addListener(msg => {
browser.test.assertEq(msg, "from-popup", "correct message received");
browser.test.notifyPass("browser_action.simple");
browser.test.sendMessage("popup");
});
},
});
yield extension.startup();
// FIXME: Should really test opening the popup here.
let widgetId = makeWidgetId(extension.id) + "-browser-action";
let node = CustomizableUI.getWidget(widgetId).forWindow(window).node;
// Do this a few times to make sure the pop-up is reloaded each time.
for (let i = 0; i < 3; i++) {
let evt = new CustomEvent("command", {
bubbles: true,
cancelable: true
});
node.dispatchEvent(evt);
yield extension.awaitMessage("popup");
let panel = node.querySelector("panel");
if (panel) {
panel.hidePopup();
}
}
yield extension.awaitFinish("browser_action.simple");
yield extension.unload();
});

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

@ -0,0 +1,173 @@
function* focusWindow(win)
{
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
if (fm.activeWindow == win) {
return;
}
let promise = new Promise(resolve => {
win.addEventListener("focus", function listener() {
win.removeEventListener("focus", listener, true);
resolve();
}, true);
});
win.focus();
yield promise;
}
function genericChecker()
{
var kind = "background";
var path = window.location.pathname;
if (path.indexOf("popup") != -1) {
kind = "popup";
} else if (path.indexOf("page") != -1) {
kind = "page";
}
browser.test.onMessage.addListener((msg, ...args) => {
if (msg == kind + "-check-current1") {
browser.tabs.query({
currentWindow: true
}, function(tabs) {
browser.test.sendMessage("result", tabs[0].windowId);
});
} else if (msg == kind + "-check-current2") {
browser.tabs.query({
windowId: browser.windows.WINDOW_ID_CURRENT
}, function(tabs) {
browser.test.sendMessage("result", tabs[0].windowId);
});
} else if (msg == kind + "-check-current3") {
browser.windows.getCurrent(function(window) {
browser.test.sendMessage("result", window.id);
});
} else if (msg == kind + "-open-page") {
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("page.html")});
} else if (msg == kind + "-close-page") {
browser.tabs.query({
windowId: args[0],
}, tabs => {
var tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
browser.tabs.remove(tab.id, () => {
browser.test.sendMessage("closed");
});
});
}
});
browser.test.sendMessage(kind + "-ready");
}
add_task(function* () {
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
yield focusWindow(win2);
yield BrowserTestUtils.loadURI(win1.gBrowser.selectedBrowser, "about:robots");
yield BrowserTestUtils.browserLoaded(win1.gBrowser.selectedBrowser);
yield BrowserTestUtils.loadURI(win2.gBrowser.selectedBrowser, "about:config");
yield BrowserTestUtils.browserLoaded(win2.gBrowser.selectedBrowser);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
"browser_action": {
"default_popup": "popup.html"
},
},
files: {
"page.html": `
<!DOCTYPE html>
<html><body>
<script src="page.js"></script>
</body></html>
`,
"page.js": genericChecker,
"popup.html": `
<!DOCTYPE html>
<html><body>
<script src="popup.js"></script>
</body></html>
`,
"popup.js": genericChecker,
},
background: genericChecker,
});
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
let winId1 = WindowManager.getId(win1);
let winId2 = WindowManager.getId(win2);
function* checkWindow(kind, winId, name) {
extension.sendMessage(kind + "-check-current1");
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 1) [${kind}]`);
extension.sendMessage(kind + "-check-current2");
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 2) [${kind}]`);
extension.sendMessage(kind + "-check-current3");
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 3) [${kind}]`);
}
yield focusWindow(win1);
yield checkWindow("background", winId1, "win1");
yield focusWindow(win2);
yield checkWindow("background", winId2, "win2");
function* triggerPopup(win, callback) {
let widgetId = makeWidgetId(extension.id) + "-browser-action";
let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
let evt = new CustomEvent("command", {
bubbles: true,
cancelable: true
});
node.dispatchEvent(evt);
yield extension.awaitMessage("popup-ready");
yield callback();
let panel = node.querySelector("panel");
if (panel) {
panel.hidePopup();
}
}
// Set focus to some other window.
yield focusWindow(window);
yield triggerPopup(win1, function*() {
yield checkWindow("popup", winId1, "win1");
});
yield triggerPopup(win2, function*() {
yield checkWindow("popup", winId2, "win2");
});
function* triggerPage(winId, name) {
extension.sendMessage("background-open-page", winId);
yield extension.awaitMessage("page-ready");
yield checkWindow("page", winId, name);
extension.sendMessage("background-close-page", winId);
yield extension.awaitMessage("closed");
}
yield triggerPage(winId1, "win1");
yield triggerPage(winId2, "win2");
yield extension.unload();
yield BrowserTestUtils.closeWindow(win1);
yield BrowserTestUtils.closeWindow(win2);
});

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

@ -0,0 +1,178 @@
function genericChecker()
{
var kind = "background";
var path = window.location.pathname;
if (path.indexOf("popup") != -1) {
kind = "popup";
} else if (path.indexOf("tab") != -1) {
kind = "tab";
}
window.kind = kind;
browser.test.onMessage.addListener((msg, ...args) => {
if (msg == kind + "-check-views") {
var views = browser.extension.getViews();
var counts = {
"background": 0,
"tab": 0,
"popup": 0
};
for (var i = 0; i < views.length; i++) {
var view = views[i];
browser.test.assertTrue(view.kind in counts, "view type is valid");
counts[view.kind]++;
if (view.kind == "background") {
browser.test.assertTrue(view === browser.extension.getBackgroundPage(),
"background page is correct");
}
}
browser.test.sendMessage("counts", counts);
} else if (msg == kind + "-open-tab") {
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("tab.html")});
} else if (msg == kind + "-close-tab") {
browser.tabs.query({
windowId: args[0],
}, tabs => {
var tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
browser.tabs.remove(tab.id, () => {
browser.test.sendMessage("closed");
});
});
}
});
browser.test.sendMessage(kind + "-ready");
}
add_task(function* () {
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
"browser_action": {
"default_popup": "popup.html"
},
},
files: {
"tab.html": `
<!DOCTYPE html>
<html><body>
<script src="tab.js"></script>
</body></html>
`,
"tab.js": genericChecker,
"popup.html": `
<!DOCTYPE html>
<html><body>
<script src="popup.js"></script>
</body></html>
`,
"popup.js": genericChecker,
},
background: genericChecker,
});
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
info("started");
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
let winId1 = WindowManager.getId(win1);
let winId2 = WindowManager.getId(win2);
function* openTab(winId) {
extension.sendMessage("background-open-tab", winId);
yield extension.awaitMessage("tab-ready");
}
function* checkViews(kind, tabCount, popupCount) {
extension.sendMessage(kind + "-check-views");
let counts = yield extension.awaitMessage("counts");
is(counts.background, 1, "background count correct");
is(counts.tab, tabCount, "tab count correct");
is(counts.popup, popupCount, "popup count correct");
}
yield checkViews("background", 0, 0);
yield openTab(winId1);
yield checkViews("background", 1, 0);
yield checkViews("tab", 1, 0);
yield openTab(winId2);
yield checkViews("background", 2, 0);
function* triggerPopup(win, callback) {
let widgetId = makeWidgetId(extension.id) + "-browser-action";
let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
let evt = new CustomEvent("command", {
bubbles: true,
cancelable: true
});
node.dispatchEvent(evt);
yield extension.awaitMessage("popup-ready");
yield callback();
let panel = node.querySelector("panel");
if (panel) {
panel.hidePopup();
}
}
yield triggerPopup(win1, function*() {
yield checkViews("background", 2, 1);
yield checkViews("popup", 2, 1);
});
yield triggerPopup(win2, function*() {
yield checkViews("background", 2, 1);
yield checkViews("popup", 2, 1);
});
info("checking counts after popups");
yield checkViews("background", 2, 0);
info("closing one tab");
extension.sendMessage("background-close-tab", winId1);
yield extension.awaitMessage("closed");
info("one tab closed, one remains");
yield checkViews("background", 1, 0);
info("opening win1 popup");
yield triggerPopup(win1, function*() {
yield checkViews("background", 1, 1);
yield checkViews("tab", 1, 1);
yield checkViews("popup", 1, 1);
});
info("opening win2 popup");
yield triggerPopup(win2, function*() {
yield checkViews("background", 1, 1);
yield checkViews("tab", 1, 1);
yield checkViews("popup", 1, 1);
});
yield extension.unload();
yield BrowserTestUtils.closeWindow(win1);
yield BrowserTestUtils.closeWindow(win2);
});

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

@ -0,0 +1,7 @@
let {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
function makeWidgetId(id)
{
id = id.toLowerCase();
return id.replace(/[^a-z0-9_-]/g, "_");
}

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

@ -7251,6 +7251,9 @@ if test -z "$MOZ_MEMORY"; then
esac
else
AC_DEFINE(MOZ_MEMORY)
if test -n "$NIGHTLY_BUILD"; then
MOZ_JEMALLOC4=1
fi
if test -n "$MOZ_JEMALLOC4"; then
AC_DEFINE(MOZ_JEMALLOC4)
fi

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

@ -9,17 +9,7 @@
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console-workers.html";
function pushPrefEnv() {
let deferred = promise.defer();
let options = {
set: [["dom.workers.sharedWorkers.enabled", true]]
};
SpecialPowers.pushPrefEnv(options, deferred.resolve);
return deferred.promise;
}
var test = asyncTest(function*() {
yield pushPrefEnv();
yield loadTab(TEST_URI);
let hud = yield openConsole();

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

@ -108,8 +108,8 @@ class DeserializedEdgeRange : public EdgeRange
}
public:
explicit DeserializedEdgeRange(JSContext* cx)
: edges(cx)
explicit DeserializedEdgeRange()
: edges()
, i(0)
{
settle();
@ -160,10 +160,10 @@ Concrete<DeserializedNode>::allocationStack() const
UniquePtr<EdgeRange>
Concrete<DeserializedNode>::edges(JSContext* cx, bool) const
Concrete<DeserializedNode>::edges(JSRuntime* rt, bool) const
{
UniquePtr<DeserializedEdgeRange, JS::DeletePolicy<DeserializedEdgeRange>> range(
js_new<DeserializedEdgeRange>(cx));
js_new<DeserializedEdgeRange>());
if (!range || !range->init(get()))
return nullptr;

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

@ -265,7 +265,7 @@ public:
// We ignore the `bool wantNames` parameter because we can't control whether
// the core dump was serialized with edge names or not.
UniquePtr<EdgeRange> edges(JSContext* cx, bool) const override;
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool) const override;
};
template<>

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

@ -384,7 +384,7 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
{
JS::AutoCheckCannotGC nogc;
JS::ubi::CensusTraversal traversal(cx, handler, nogc);
JS::ubi::CensusTraversal traversal(JS_GetRuntime(cx), handler, nogc);
if (NS_WARN_IF(!traversal.init())) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
@ -684,7 +684,7 @@ public:
}
if (includeEdges) {
auto edges = ubiNode.edges(cx, wantNames);
auto edges = ubiNode.edges(JS_GetRuntime(cx), wantNames);
if (NS_WARN_IF(!edges))
return false;
@ -795,7 +795,7 @@ WriteHeapGraph(JSContext* cx,
// core dump.
HeapSnapshotHandler handler(writer, zones);
HeapSnapshotHandler::Traversal traversal(cx, handler, noGC);
HeapSnapshotHandler::Traversal traversal(JS_GetRuntime(cx), handler, noGC);
if (!traversal.init())
return false;
traversal.wantNames = wantNames;
@ -960,7 +960,7 @@ ThreadSafeChromeUtils::SaveHeapSnapshot(GlobalObject& global,
{
Maybe<AutoCheckCannotGC> maybeNoGC;
ubi::RootList rootList(cx, maybeNoGC, wantNames);
ubi::RootList rootList(JS_GetRuntime(cx), maybeNoGC, wantNames);
if (!EstablishBoundaries(cx, rv, boundaries, rootList, zones))
return;

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

@ -97,5 +97,5 @@ DEF_TEST(DeserializedNodeUbiNodes, {
.Times(1)
.WillOnce(Return(JS::ubi::Node(referent3.get())));
ubi.edges(cx);
ubi.edges(JS_GetRuntime(cx));
});

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

@ -162,8 +162,8 @@ public:
JS::Zone* zone;
size_t size;
explicit FakeNode(JSContext* cx)
: edges(cx),
explicit FakeNode()
: edges(),
compartment(nullptr),
zone(nullptr),
size(1)
@ -182,8 +182,8 @@ class Concrete<FakeNode> : public Base
return concreteTypeName;
}
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override {
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(cx, get().edges));
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override {
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
}
Size size(mozilla::MallocSizeOf) const override {
@ -233,8 +233,8 @@ void AddEdge(FakeNode& node, FakeNode& referent, const char16_t* edgeName = null
namespace testing {
// Ensure that given node has the expected number of edges.
MATCHER_P2(EdgesLength, cx, expectedLength, "") {
auto edges = arg.edges(cx);
MATCHER_P2(EdgesLength, rt, expectedLength, "") {
auto edges = arg.edges(rt);
if (!edges)
return false;
@ -247,8 +247,8 @@ MATCHER_P2(EdgesLength, cx, expectedLength, "") {
}
// Get the nth edge and match it with the given matcher.
MATCHER_P3(Edge, cx, n, matcher, "") {
auto edges = arg.edges(cx);
MATCHER_P3(Edge, rt, n, matcher, "") {
auto edges = arg.edges(rt);
if (!edges)
return false;

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

@ -29,10 +29,10 @@ DEF_TEST(DoesCrossZoneBoundaries, {
ASSERT_TRUE(targetZones.put(zone));
ASSERT_TRUE(targetZones.put(newZone));
FakeNode nodeA(cx);
FakeNode nodeB(cx);
FakeNode nodeC(cx);
FakeNode nodeD(cx);
FakeNode nodeA;
FakeNode nodeB;
FakeNode nodeC;
FakeNode nodeD;
nodeA.zone = zone;
nodeB.zone = nullptr;

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

@ -29,9 +29,9 @@ DEF_TEST(DoesntCrossZoneBoundaries, {
ASSERT_TRUE(targetZones.init());
ASSERT_TRUE(targetZones.put(zone));
FakeNode nodeA(cx);
FakeNode nodeB(cx);
FakeNode nodeC(cx);
FakeNode nodeA;
FakeNode nodeB;
FakeNode nodeC;
nodeA.zone = zone;
nodeB.zone = nullptr;

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

@ -13,8 +13,8 @@ using testing::Property;
using testing::Return;
DEF_TEST(SerializesEdgeNames, {
FakeNode node(cx);
FakeNode referent(cx);
FakeNode node;
FakeNode referent;
const char16_t edgeName[] = MOZ_UTF16("edge name");
const char16_t emptyStr[] = MOZ_UTF16("");
@ -28,12 +28,12 @@ DEF_TEST(SerializesEdgeNames, {
// Should get the node with edges once.
EXPECT_CALL(
writer,
writeNode(AllOf(EdgesLength(cx, 3),
Edge(cx, 0, Field(&JS::ubi::Edge::name,
writeNode(AllOf(EdgesLength(rt, 3),
Edge(rt, 0, Field(&JS::ubi::Edge::name,
UTF16StrEq(edgeName))),
Edge(cx, 1, Field(&JS::ubi::Edge::name,
Edge(rt, 1, Field(&JS::ubi::Edge::name,
UTF16StrEq(emptyStr))),
Edge(cx, 2, Field(&JS::ubi::Edge::name,
Edge(rt, 2, Field(&JS::ubi::Edge::name,
IsNull()))),
_)
)

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

@ -8,10 +8,10 @@
#include "DevTools.h"
DEF_TEST(SerializesEverythingInHeapGraphOnce, {
FakeNode nodeA(cx);
FakeNode nodeB(cx);
FakeNode nodeC(cx);
FakeNode nodeD(cx);
FakeNode nodeA;
FakeNode nodeB;
FakeNode nodeC;
FakeNode nodeD;
AddEdge(nodeA, nodeB);
AddEdge(nodeB, nodeC);

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

@ -11,7 +11,7 @@ using testing::Property;
using testing::Return;
DEF_TEST(SerializesTypeNames, {
FakeNode node(cx);
FakeNode node;
::testing::NiceMock<MockWriter> writer;
EXPECT_CALL(writer, writeNode(Property(&JS::ubi::Node::typeName,

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

@ -80,6 +80,7 @@ skip-if = os == 'linux' || os == 'mac' # Bug 1026815
[test_bug690056.xul]
[test_bug789773.xul]
[test_bug846906.xul]
skip-if = os == 'linux' && asan # Bug 1207161
[test_bug89419.xul]
[test_bug909218.html]
[test_bug92598.xul]

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

@ -44,7 +44,7 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.workers.sharedWorkers.enabled", true]]}, runTests);
runTests();
</script>
</pre>

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

@ -946,6 +946,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
, mZero(false), mOpaque(false)
, mResetLayer(true)
, mIPC(false)
, mIsSkiaGL(false)
, mDrawObserver(nullptr)
, mIsEntireFrameInvalid(false)
, mPredictManyRedrawCalls(false)
@ -1376,6 +1377,8 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
}
}
mIsSkiaGL = false;
// Check that the dimensions are sane
IntSize size(mWidth, mHeight);
if (size.width <= gfxPrefs::MaxCanvasSize() &&
@ -1409,6 +1412,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
mIsSkiaGL = true;
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
mode = RenderingMode::SoftwareBackendMode;
@ -5560,9 +5564,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (mOpaque) {
if (mOpaque || mIsSkiaGL) {
// If we're opaque then make sure we have a surface so we paint black
// instead of transparent.
// If we're using SkiaGL, then SkiaGLTex() below needs the target to
// be accessible.
EnsureTarget();
}

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

@ -718,6 +718,9 @@ protected:
bool mResetLayer;
// This is needed for drawing in drawAsyncXULElement
bool mIPC;
// True if the current DrawTarget is using skia-gl, used so we can avoid
// requesting the DT from mBufferProvider to check.
bool mIsSkiaGL;
nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;

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

@ -159,4 +159,4 @@ pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidV
# Check that captureStream() displays in a local video element
skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
fuzzy-if(azureSkiaGL,1,2) fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html

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

@ -114,6 +114,7 @@
#include "nsIClipboard.h"
#include "nsContentPermissionHelper.h"
#include "nsICycleCollectorListener.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocument.h"
#include "nsIDOMGeoGeolocation.h"
#include "nsIDOMGeoPositionError.h"
@ -124,6 +125,7 @@
#include "nsIFormProcessor.h"
#include "nsIGfxInfo.h"
#include "nsIIdleService.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIMemoryInfoDumper.h"
#include "nsIMemoryReporter.h"
#include "nsIMozBrowserFrame.h"
@ -1234,7 +1236,18 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
constructorSender->ChildID());
}
if (constructorSender) {
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
if (!treeOwner) {
return nullptr;
}
nsCOMPtr<nsIWebBrowserChrome> wbc = do_GetInterface(treeOwner);
if (!wbc) {
return nullptr;
}
uint32_t chromeFlags = 0;
wbc->GetChromeFlags(&chromeFlags);
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (loadContext && loadContext->UsePrivateBrowsing()) {
@ -2189,7 +2202,7 @@ ContentParent::StartForceKillTimer()
return;
}
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 0);
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
if (timeoutSecs > 0) {
mForceKillTimer = do_CreateInstance("@mozilla.org/timer;1");
MOZ_ASSERT(mForceKillTimer);
@ -3471,6 +3484,14 @@ ContentParent::DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParen
/* static */ void
ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
{
#ifdef ENABLE_TESTS
// We don't want to time out the content process during XPCShell tests. This
// is the easiest way to ensure that.
if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
return;
}
#endif
auto self = static_cast<ContentParent*>(aClosure);
self->KillHard("ShutDownKill");
}

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

@ -15,6 +15,8 @@
#include "nsThreadUtils.h"
#include "nsReadableUtils.h"
#include "nsIObserverService.h"
#include "mozilla/Telemetry.h"
#include "mozilla/ArrayUtils.h"
// NSPR_LOG_MODULES=LoadManager:5
PRLogModuleInfo *gLoadManagerLog = nullptr;
@ -53,6 +55,11 @@ LoadManagerSingleton::LoadManagerSingleton(int aLoadMeasurementInterval,
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
mLoadMonitor->Init(mLoadMonitor);
mLoadMonitor->SetLoadChangeCallback(this);
mLastStateChange = TimeStamp::Now();
for (auto &in_state : mTimeInState) {
in_state = 0;
}
}
LoadManagerSingleton::~LoadManagerSingleton()
@ -100,21 +107,22 @@ LoadManagerSingleton::LoadChanged(float aSystemLoad, float aProcesLoad)
if (mLoadSumMeasurements >= mAveragingMeasurements) {
double averagedLoad = mLoadSum / (float)mLoadSumMeasurements;
webrtc::CPULoadState oldState = mCurrentState;
webrtc::CPULoadState newState = mCurrentState;
if (mOveruseActive || averagedLoad > mHighLoadThreshold) {
LOG(("LoadManager - LoadStressed"));
mCurrentState = webrtc::kLoadStressed;
newState = webrtc::kLoadStressed;
} else if (averagedLoad < mLowLoadThreshold) {
LOG(("LoadManager - LoadRelaxed"));
mCurrentState = webrtc::kLoadRelaxed;
newState = webrtc::kLoadRelaxed;
} else {
LOG(("LoadManager - LoadNormal"));
mCurrentState = webrtc::kLoadNormal;
newState = webrtc::kLoadNormal;
}
if (oldState != mCurrentState)
LoadHasChanged();
if (newState != mCurrentState) {
LoadHasChanged(newState);
}
mLoadSum = 0;
mLoadSumMeasurements = 0;
@ -128,8 +136,7 @@ LoadManagerSingleton::OveruseDetected()
MutexAutoLock lock(mLock);
mOveruseActive = true;
if (mCurrentState != webrtc::kLoadStressed) {
mCurrentState = webrtc::kLoadStressed;
LoadHasChanged();
LoadHasChanged(webrtc::kLoadStressed);
}
}
@ -142,10 +149,18 @@ LoadManagerSingleton::NormalUsage()
}
void
LoadManagerSingleton::LoadHasChanged()
LoadManagerSingleton::LoadHasChanged(webrtc::CPULoadState aNewState)
{
mLock.AssertCurrentThreadOwns();
LOG(("LoadManager - Signaling LoadHasChanged to %d listeners", mObservers.Length()));
LOG(("LoadManager - Signaling LoadHasChanged from %d to %d to %d listeners",
mCurrentState, aNewState, mObservers.Length()));
// Record how long we spent in this state for later Telemetry or display
TimeStamp now = TimeStamp::Now();
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
mLastStateChange = now;
mCurrentState = aNewState;
for (size_t i = 0; i < mObservers.Length(); i++) {
mObservers.ElementAt(i)->onLoadStateChanged(mCurrentState);
}
@ -162,6 +177,7 @@ LoadManagerSingleton::AddObserver(webrtc::CPULoadStateObserver * aObserver)
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
mLoadMonitor->Init(mLoadMonitor);
mLoadMonitor->SetLoadChangeCallback(this);
mLastStateChange = TimeStamp::Now();
}
}
}
@ -176,6 +192,35 @@ LoadManagerSingleton::RemoveObserver(webrtc::CPULoadStateObserver * aObserver)
}
if (mObservers.Length() == 0) {
if (mLoadMonitor) {
// Record how long we spent in the final state for later Telemetry or display
TimeStamp now = TimeStamp::Now();
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
float total = 0;
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mTimeInState); i++) {
total += mTimeInState[i];
}
// Don't include short calls; we don't have reasonable load data, and
// such short calls rarely reach a stable state. Keep relatively
// short calls separate from longer ones
bool log = total > 5*PR_MSEC_PER_SEC;
bool small = log && total < 30*PR_MSEC_PER_SEC;
if (log) {
// Note: We don't care about rounding here; thus total may be < 100
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_RELAXED_SHORT :
Telemetry::WEBRTC_LOAD_STATE_RELAXED,
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadRelaxed]/total * 100));
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_NORMAL_SHORT :
Telemetry::WEBRTC_LOAD_STATE_NORMAL,
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadNormal]/total * 100));
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_STRESSED_SHORT :
Telemetry::WEBRTC_LOAD_STATE_STRESSED,
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadStressed]/total * 100));
}
for (auto &in_state : mTimeInState) {
in_state = 0;
}
// Dance to avoid deadlock on mLock!
nsRefPtr<LoadMonitor> loadMonitor = mLoadMonitor.forget();
MutexAutoUnlock unlock(mLock);

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

@ -50,7 +50,7 @@ private:
float aLowLoadThreshold);
~LoadManagerSingleton();
void LoadHasChanged();
void LoadHasChanged(webrtc::CPULoadState aNewState);
nsRefPtr<LoadMonitor> mLoadMonitor;
@ -59,6 +59,9 @@ private:
Mutex mLock;
nsTArray<webrtc::CPULoadStateObserver*> mObservers;
webrtc::CPULoadState mCurrentState;
TimeStamp mLastStateChange;
float mTimeInState[static_cast<int>(webrtc::kLoadLast)];
// Set when overuse was signaled to us, and hasn't been un-signaled yet.
bool mOveruseActive;
float mLoadSum;

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

@ -4,41 +4,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/PresentationBinding.h"
#include "mozilla/dom/Promise.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationDeviceManager.h"
#include "nsIPresentationService.h"
#include "nsIUUIDGenerator.h"
#include "nsServiceManagerUtils.h"
#include "Presentation.h"
#include "PresentationCallbacks.h"
#include "PresentationSession.h"
#include "PresentationReceiver.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(Presentation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Presentation, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDefaultRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingGetSessionPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Presentation, DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDefaultRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessions)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingGetSessionPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_INHERITED(Presentation, DOMEventTargetHelper,
mDefaultRequest, mReceiver)
NS_IMPL_ADDREF_INHERITED(Presentation, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(Presentation, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Presentation)
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
/* static */ already_AddRefed<Presentation>
@ -55,7 +38,6 @@ Presentation::Presentation(nsPIDOMWindow* aWindow)
Presentation::~Presentation()
{
Shutdown();
}
bool
@ -70,56 +52,25 @@ Presentation::Init()
if (NS_WARN_IF(!GetOwner())) {
return false;
}
mWindowId = GetOwner()->WindowID();
// Check if a session instance is required now. A session may already be
// connecting before the web content gets loaded in a presenting browsing
// context (receiver).
// Check if a receiver instance is required now. A session may already be
// connecting before the web content gets loaded in a receiving browsing
// context.
nsAutoString sessionId;
nsresult rv = service->GetExistentSessionIdAtLaunch(mWindowId, sessionId);
nsresult rv = service->GetExistentSessionIdAtLaunch(GetOwner()->WindowID(), sessionId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
if (!sessionId.IsEmpty()) {
rv = NotifySessionConnect(mWindowId, sessionId);
if (NS_WARN_IF(NS_FAILED(rv))) {
mReceiver = PresentationReceiver::Create(GetOwner(), sessionId);
if (NS_WARN_IF(!mReceiver)) {
return false;
}
}
// Register listener for incoming sessions.
rv = service->RegisterRespondingListener(mWindowId, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return true;
}
void Presentation::Shutdown()
{
mDefaultRequest = nullptr;
mSessions.Clear();
mPendingGetSessionPromises.Clear();
// Unregister listener for incoming sessions.
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return;
}
nsresult rv = service->UnregisterRespondingListener(mWindowId);
NS_WARN_IF(NS_FAILED(rv));
}
/* virtual */ void
Presentation::DisconnectFromOwner()
{
Shutdown();
DOMEventTargetHelper::DisconnectFromOwner();
}
/* virtual */ JSObject*
Presentation::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
@ -140,81 +91,9 @@ Presentation::GetDefaultRequest() const
return request.forget();
}
already_AddRefed<Promise>
Presentation::GetSession(ErrorResult& aRv)
already_AddRefed<PresentationReceiver>
Presentation::GetReceiver() const
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// If there's no existing session, leave the promise pending until a
// connecting request arrives from the controlling browsing context (sender).
// http://w3c.github.io/presentation-api/#dom-presentation-getsession
if (!mSessions.IsEmpty()) {
promise->MaybeResolve(mSessions[0]);
} else {
mPendingGetSessionPromises.AppendElement(promise);
}
return promise.forget();
}
already_AddRefed<Promise>
Presentation::GetSessions(ErrorResult& aRv) const
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
promise->MaybeResolve(mSessions);
return promise.forget();
}
NS_IMETHODIMP
Presentation::NotifySessionConnect(uint64_t aWindowId,
const nsAString& aSessionId)
{
if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
return NS_ERROR_INVALID_ARG;
}
nsRefPtr<PresentationSession> session =
PresentationSession::Create(GetOwner(), aSessionId,
PresentationSessionState::Disconnected);
if (NS_WARN_IF(!session)) {
return NS_ERROR_NOT_AVAILABLE;
}
mSessions.AppendElement(session);
// Resolve pending |GetSession| promises if any.
if (!mPendingGetSessionPromises.IsEmpty()) {
for(uint32_t i = 0; i < mPendingGetSessionPromises.Length(); i++) {
mPendingGetSessionPromises[i]->MaybeResolve(session);
}
mPendingGetSessionPromises.Clear();
}
return DispatchSessionAvailableEvent();
}
nsresult
Presentation::DispatchSessionAvailableEvent()
{
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("sessionavailable"), false);
return asyncDispatcher->PostDOMEvent();
nsRefPtr<PresentationReceiver> receiver = mReceiver;
return receiver.forget();
}

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

@ -8,28 +8,23 @@
#define mozilla_dom_Presentation_h
#include "mozilla/DOMEventTargetHelper.h"
#include "nsIPresentationListener.h"
namespace mozilla {
namespace dom {
class Promise;
class PresentationReceiver;
class PresentationRequest;
class PresentationSession;
class Presentation final : public DOMEventTargetHelper
, public nsIPresentationRespondingListener
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Presentation,
DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
static already_AddRefed<Presentation> Create(nsPIDOMWindow* aWindow);
virtual void DisconnectFromOwner() override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@ -38,11 +33,7 @@ public:
already_AddRefed<PresentationRequest> GetDefaultRequest() const;
already_AddRefed<Promise> GetSession(ErrorResult& aRv);
already_AddRefed<Promise> GetSessions(ErrorResult& aRv) const;
IMPL_EVENT_HANDLER(sessionavailable);
already_AddRefed<PresentationReceiver> GetReceiver() const;
private:
explicit Presentation(nsPIDOMWindow* aWindow);
@ -51,17 +42,8 @@ private:
bool Init();
void Shutdown();
nsresult DispatchSessionAvailableEvent();
// Store the inner window ID for |UnregisterRespondingListener| call in
// |Shutdown| since the inner window may not exist at that moment.
uint64_t mWindowId;
nsRefPtr<PresentationRequest> mDefaultRequest;
nsTArray<nsRefPtr<PresentationSession>> mSessions;
nsTArray<nsRefPtr<Promise>> mPendingGetSessionPromises;
nsRefPtr<PresentationReceiver> mReceiver;
};
} // namespace dom

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

@ -0,0 +1,194 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/PresentationReceiverBinding.h"
#include "mozilla/dom/Promise.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationService.h"
#include "nsServiceManagerUtils.h"
#include "PresentationReceiver.h"
#include "PresentationSession.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationReceiver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingGetSessionPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessions)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingGetSessionPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(PresentationReceiver, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationReceiver, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationReceiver)
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
/* static */ already_AddRefed<PresentationReceiver>
PresentationReceiver::Create(nsPIDOMWindow* aWindow,
const nsAString& aSessionId)
{
nsRefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow);
return NS_WARN_IF(!receiver->Init(aSessionId)) ? nullptr : receiver.forget();
}
PresentationReceiver::PresentationReceiver(nsPIDOMWindow* aWindow)
: DOMEventTargetHelper(aWindow)
{
}
PresentationReceiver::~PresentationReceiver()
{
Shutdown();
}
bool
PresentationReceiver::Init(const nsAString& aSessionId)
{
if (NS_WARN_IF(!GetOwner())) {
return false;
}
mWindowId = GetOwner()->WindowID();
if (!aSessionId.IsEmpty()) {
nsresult rv = NotifySessionConnect(mWindowId, aSessionId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
}
// Register listener for incoming sessions.
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return false;
}
nsresult rv = service->RegisterRespondingListener(mWindowId, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return true;
}
void PresentationReceiver::Shutdown()
{
mSessions.Clear();
mPendingGetSessionPromises.Clear();
// Unregister listener for incoming sessions.
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return;
}
nsresult rv = service->UnregisterRespondingListener(mWindowId);
NS_WARN_IF(NS_FAILED(rv));
}
/* virtual */ void
PresentationReceiver::DisconnectFromOwner()
{
Shutdown();
DOMEventTargetHelper::DisconnectFromOwner();
}
/* virtual */ JSObject*
PresentationReceiver::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
PresentationReceiver::GetSession(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// If there's no existing session, leave the promise pending until a
// connecting request arrives from the controlling browsing context (sender).
// http://w3c.github.io/presentation-api/#dom-presentation-getsession
if (!mSessions.IsEmpty()) {
promise->MaybeResolve(mSessions[0]);
} else {
mPendingGetSessionPromises.AppendElement(promise);
}
return promise.forget();
}
already_AddRefed<Promise>
PresentationReceiver::GetSessions(ErrorResult& aRv) const
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
promise->MaybeResolve(mSessions);
return promise.forget();
}
NS_IMETHODIMP
PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
const nsAString& aSessionId)
{
if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
return NS_ERROR_INVALID_ARG;
}
nsRefPtr<PresentationSession> session =
PresentationSession::Create(GetOwner(), aSessionId,
PresentationSessionState::Disconnected);
if (NS_WARN_IF(!session)) {
return NS_ERROR_NOT_AVAILABLE;
}
mSessions.AppendElement(session);
// Resolve pending |GetSession| promises if any.
if (!mPendingGetSessionPromises.IsEmpty()) {
for(uint32_t i = 0; i < mPendingGetSessionPromises.Length(); i++) {
mPendingGetSessionPromises[i]->MaybeResolve(session);
}
mPendingGetSessionPromises.Clear();
}
return DispatchSessionAvailableEvent();
}
nsresult
PresentationReceiver::DispatchSessionAvailableEvent()
{
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("sessionavailable"), false);
return asyncDispatcher->PostDOMEvent();
}

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

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PresentationReceiver_h
#define mozilla_dom_PresentationReceiver_h
#include "mozilla/DOMEventTargetHelper.h"
#include "nsIPresentationListener.h"
namespace mozilla {
namespace dom {
class Promise;
class PresentationSession;
class PresentationReceiver final : public DOMEventTargetHelper
, public nsIPresentationRespondingListener
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationReceiver,
DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindow* aWindow,
const nsAString& aSessionId);
virtual void DisconnectFromOwner() override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// WebIDL (public APIs)
already_AddRefed<Promise> GetSession(ErrorResult& aRv);
already_AddRefed<Promise> GetSessions(ErrorResult& aRv) const;
IMPL_EVENT_HANDLER(sessionavailable);
private:
explicit PresentationReceiver(nsPIDOMWindow* aWindow);
~PresentationReceiver();
bool Init(const nsAString& aSessionId);
void Shutdown();
nsresult DispatchSessionAvailableEvent();
// Store the inner window ID for |UnregisterRespondingListener| call in
// |Shutdown| since the inner window may not exist at that moment.
uint64_t mWindowId;
nsTArray<nsRefPtr<PresentationSession>> mSessions;
nsTArray<nsRefPtr<Promise>> mPendingGetSessionPromises;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationReceiver_h

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

@ -50,6 +50,11 @@ PresentationParent::ActorDestroy(ActorDestroyReason aWhy)
}
mSessionIds.Clear();
for (uint32_t i = 0; i < mWindowIds.Length(); i++) {
NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(mWindowIds[i])));
}
mWindowIds.Clear();
mService->UnregisterAvailabilityListener(this);
mService = nullptr;
}
@ -149,6 +154,8 @@ PresentationParent::RecvUnregisterSessionHandler(const nsString& aSessionId)
PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId)
{
MOZ_ASSERT(mService);
mWindowIds.AppendElement(aWindowId);
NS_WARN_IF(NS_FAILED(mService->RegisterRespondingListener(aWindowId, this)));
return true;
}
@ -157,6 +164,7 @@ PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId)
PresentationParent::RecvUnregisterRespondingHandler(const uint64_t& aWindowId)
{
MOZ_ASSERT(mService);
mWindowIds.RemoveElement(aWindowId);
NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(aWindowId)));
return true;
}

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

@ -64,6 +64,7 @@ private:
bool mActorDestroyed;
nsCOMPtr<nsIPresentationService> mService;
nsTArray<nsString> mSessionIds;
nsTArray<uint64_t> mWindowIds;
};
class PresentationRequestParent final : public PPresentationRequestParent

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

@ -17,6 +17,7 @@ EXPORTS.mozilla.dom += [
'PresentationAvailability.h',
'PresentationCallbacks.h',
'PresentationDeviceManager.h',
'PresentationReceiver.h',
'PresentationRequest.h',
'PresentationService.h',
'PresentationSession.h',
@ -32,6 +33,7 @@ UNIFIED_SOURCES += [
'PresentationAvailability.cpp',
'PresentationCallbacks.cpp',
'PresentationDeviceManager.cpp',
'PresentationReceiver.cpp',
'PresentationRequest.cpp',
'PresentationService.cpp',
'PresentationSession.cpp',

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

@ -29,18 +29,8 @@ function finish() {
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available in OOP pages.");
navigator.presentation.getSessions().then(
function(aSessions) {
is(aSessions.length, 0, "Non-receiving OOP pages shouldn't get a predefined presentation session instance.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when getting sessions: " + aError);
teardown();
aReject();
}
);
ok(!navigator.presentation.receiver, "Non-receiving OOP pages shouldn't get a presentation receiver instance.");
aResolve();
});
}

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

@ -35,8 +35,9 @@ var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
navigator.presentation.getSession().then(
navigator.presentation.receiver.getSession().then(
function(aSession) {
session = aSession;

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

@ -35,8 +35,9 @@ var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
navigator.presentation.getSession().then(
navigator.presentation.receiver.getSession().then(
function(aSession) {
session = aSession;

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

@ -35,8 +35,9 @@ var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
navigator.presentation.getSession().then(
navigator.presentation.receiver.getSession().then(
function(aSession) {
session = aSession;

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

@ -93,18 +93,8 @@ function testIncomingSessionRequest() {
info("Trying to launch receiver page.");
ok(navigator.presentation, "navigator.presentation should be available in in-process pages.");
navigator.presentation.getSessions().then(
function(aSessions) {
is(aSessions.length, 0, "Non-receiving in-process pages shouldn't get a predefined presentation session instance.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when getting sessions: " + aError);
teardown();
aReject();
}
);
ok(!navigator.presentation.receiver, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);

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

@ -81,6 +81,8 @@ function testStartSession() {
gScript.sendAsyncMessage('trigger-incoming-answer');
});
ok(!navigator.presentation.receiver, "Sender shouldn't get a presentation receiver instance.");
navigator.presentation.defaultRequest.onsessionconnect = function(aEvent) {
navigator.presentation.defaultRequest.onsessionconnect = null;
session = aEvent.session;

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

@ -7,5 +7,6 @@ support-files =
[test_app_uninstall.html]
[test_clear_browser_data.html]
[test_localStorageBasePrivateBrowsing_perwindowpb.html]
skip-if = true # bug 1156725
[test_localStorageFromChrome.xhtml]
[test_localStorageQuotaPrivateBrowsing_perwindowpb.html]

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

@ -18,26 +18,9 @@ interface Presentation : EventTarget {
attribute PresentationRequest? defaultRequest;
/*
* Get the first connected presentation session in a presenting browsing
* context.
*
* Only used by presenting browsing context (receivers).
* This should be available on the receiving browsing context in order to
* access the controlling browsing context and communicate with them.
*/
[Throws]
Promise<PresentationSession> getSession();
/*
* Get all connected presentation sessions in a presenting browsing context.
*
* Only used by presenting browsing context (receivers).
*/
[Throws]
Promise<sequence<PresentationSession>> getSessions();
/*
* It is called when an incoming session is connecting.
*
* Only used by presenting browsing context (receivers).
*/
attribute EventHandler onsessionavailable;
[SameObject]
readonly attribute PresentationReceiver? receiver;
};

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

@ -0,0 +1,27 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
interface PresentationReceiver : EventTarget {
/*
* Get the first connected presentation session in a receiving browsing
* context.
*/
[Throws]
Promise<PresentationSession> getSession();
/*
* Get all connected presentation sessions in a receiving browsing context.
*/
[Throws]
Promise<sequence<PresentationSession>> getSessions();
/*
* It is called when an incoming session is connecting.
*/
attribute EventHandler onsessionavailable;
};

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

@ -4,8 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Pref="dom.workers.sharedWorkers.enabled",
Constructor(DOMString scriptURL, optional DOMString name)]
[Constructor(DOMString scriptURL, optional DOMString name)]
interface SharedWorker : EventTarget {
readonly attribute MessagePort port;
};

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

@ -373,6 +373,7 @@ WEBIDL_FILES = [
'Presentation.webidl',
'PresentationAvailability.webidl',
'PresentationDeviceInfoManager.webidl',
'PresentationReceiver.webidl',
'PresentationRequest.webidl',
'PresentationSession.webidl',
'ProcessingInstruction.webidl',

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

@ -3376,7 +3376,6 @@ ServiceWorkerManager::FindScopeForPath(const nsACString& aScopeKey,
return false;
}
#ifdef DEBUG
/* static */ bool
ServiceWorkerManager::HasScope(nsIPrincipal* aPrincipal,
const nsACString& aScope)
@ -3397,7 +3396,6 @@ ServiceWorkerManager::HasScope(nsIPrincipal* aPrincipal,
return data->mOrderedScopes.Contains(aScope);
}
#endif
/* static */ void
ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration)
@ -4636,7 +4634,8 @@ ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRe
{
MOZ_ASSERT(aRegistration);
nsRefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
if (!newest) {
if (!newest && HasScope(aRegistration->mPrincipal, aRegistration->mScope)) {
aRegistration->Clear();
RemoveRegistration(aRegistration);
}
}

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

@ -520,10 +520,8 @@ private:
const nsACString& aPath,
RegistrationDataPerPrincipal** aData, nsACString& aMatch);
#ifdef DEBUG
static bool
HasScope(nsIPrincipal* aPrincipal, const nsACString& aScope);
#endif
static void
RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration);

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

@ -16,23 +16,21 @@
// This test is full of dummy debug messages. This is because I need to follow
// an hard-to-reproduce timeout failure.
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
info("test started");
var sw = new SharedWorker('bug1132395_sharedWorker.js');
sw.port.onmessage = function(event) {
info("sw.onmessage received");
ok(true, "We didn't crash.");
SimpleTest.finish();
}
info("test started");
var sw = new SharedWorker('bug1132395_sharedWorker.js');
sw.port.onmessage = function(event) {
info("sw.onmessage received");
ok(true, "We didn't crash.");
SimpleTest.finish();
}
sw.onerror = function(event) {
ok(false, "Failed to create a ServiceWorker");
SimpleTest.finish();
}
sw.onerror = function(event) {
ok(false, "Failed to create a ServiceWorker");
SimpleTest.finish();
}
info("sw.postmessage called");
sw.port.postMessage('go');
});
info("sw.postmessage called");
sw.port.postMessage('go');
SimpleTest.waitForExplicitFinish();

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

@ -15,15 +15,10 @@
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
new SharedWorker('sharedWorker_sharedWorker.js');
new SharedWorker('sharedWorker_sharedWorker.js', ':');
new SharedWorker('sharedWorker_sharedWorker.js', '|||');
ok(true, "3 SharedWorkers created!");
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
new SharedWorker('sharedWorker_sharedWorker.js');
new SharedWorker('sharedWorker_sharedWorker.js', ':');
new SharedWorker('sharedWorker_sharedWorker.js', '|||');
ok(true, "3 SharedWorkers created!");
</script>
</pre>

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

@ -47,10 +47,7 @@
}
var cl = new consoleListener();
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
new SharedWorker('sharedWorker_console.js');
});
new SharedWorker('sharedWorker_console.js');
SimpleTest.waitForExplicitFinish();

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

@ -11,8 +11,6 @@
<script class="testbody" type="text/javascript;version=1.7">
"use strict";
const swPref = "dom.workers.sharedWorkers.enabled";
const basePath =
location.pathname.substring(0,
location.pathname.lastIndexOf("/") + 1);
@ -30,13 +28,6 @@
let testGenerator = (function() {
SimpleTest.waitForExplicitFinish();
if (!SpecialPowers.getBoolPref(swPref)) {
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
}
SpecialPowers.pushPrefEnv({ set: [[swPref, true]] }, sendToGenerator);
yield undefined;
window.addEventListener("message", function(event) {
if (typeof(event.data) == "string") {
info(event.data);

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

@ -11,7 +11,6 @@
<script class="testbody" type="text/javascript;version=1.7">
"use strict";
const swPref = "dom.workers.sharedWorkers.enabled";
const scrollbarPref = "layout.testing.overlay-scrollbars.always-visible";
const bfCacheEnabledPref = "browser.sessionhistory.cache_subframes";
const bfCacheDepthPref = "browser.sessionhistory.max_total_viewers";
@ -23,16 +22,11 @@
let testGenerator = (function() {
SimpleTest.waitForExplicitFinish();
if (!SpecialPowers.getBoolPref(swPref)) {
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
}
// Enable SharedWorkers and force scrollbar to always be shown. The
// scrollbar setting is necessary to avoid the fade-in/fade-out from
// evicting our document from the BF cache below. If bug 1049277
// is fixed, then we can stop setting the scrollbar pref here.
SpecialPowers.pushPrefEnv({ set: [[swPref, true],
[scrollbarPref, true]] },
// Force scrollbar to always be shown. The scrollbar setting is
// necessary to avoid the fade-in/fade-out from evicting our document
// from the BF cache below. If bug 1049277 is fixed, then we can
// stop setting the scrollbar pref here.
SpecialPowers.pushPrefEnv({ set: [[scrollbarPref, true]] },
sendToGenerator);
yield undefined;

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

@ -17,8 +17,6 @@
<script class="testbody">
"use strict";
const swPref = "dom.workers.sharedWorkers.enabled";
const href = window.location.href;
const filename = "sharedWorker_sharedWorker.js";
const sentMessage = "ping";
@ -27,49 +25,43 @@
const errorLine = 86;
const errorColumn = 0;
if (!SpecialPowers.getBoolPref(swPref)) {
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
}
var worker = new SharedWorker(filename);
SpecialPowers.pushPrefEnv({ set: [[swPref, true]] }, function() {
var worker = new SharedWorker(filename);
ok(worker instanceof SharedWorker, "Got SharedWorker instance");
ok(!("postMessage" in worker), "SharedWorker has no 'postMessage'");
ok(worker.port instanceof MessagePort,
"Shared worker has MessagePort");
ok(worker instanceof SharedWorker, "Got SharedWorker instance");
ok(!("postMessage" in worker), "SharedWorker has no 'postMessage'");
ok(worker.port instanceof MessagePort,
"Shared worker has MessagePort");
var receivedMessage;
var receivedError;
var receivedMessage;
var receivedError;
worker.port.onmessage = function(event) {
ok(event instanceof MessageEvent, "Got a MessageEvent");
ok(event.target === worker.port,
"MessageEvent has correct 'target' property");
is(event.data, sentMessage, "Got correct message");
ok(receivedMessage === undefined, "Haven't gotten message yet");
receivedMessage = event.data;
if (receivedError) {
SimpleTest.finish();
}
};
worker.port.onmessage = function(event) {
ok(event instanceof MessageEvent, "Got a MessageEvent");
ok(event.target === worker.port,
"MessageEvent has correct 'target' property");
is(event.data, sentMessage, "Got correct message");
ok(receivedMessage === undefined, "Haven't gotten message yet");
receivedMessage = event.data;
if (receivedError) {
SimpleTest.finish();
}
};
worker.onerror = function(event) {
ok(event instanceof ErrorEvent, "Got an ErrorEvent");
is(event.message, "Error: " + sentMessage, "Got correct error");
is(event.filename, errorFilename, "Got correct filename");
is(event.lineno, errorLine, "Got correct lineno");
is(event.colno, errorColumn, "Got correct column");
ok(receivedError === undefined, "Haven't gotten error yet");
receivedError = event.message;
event.preventDefault();
if (receivedMessage) {
SimpleTest.finish();
}
};
worker.onerror = function(event) {
ok(event instanceof ErrorEvent, "Got an ErrorEvent");
is(event.message, "Error: " + sentMessage, "Got correct error");
is(event.filename, errorFilename, "Got correct filename");
is(event.lineno, errorLine, "Got correct lineno");
is(event.colno, errorColumn, "Got correct column");
ok(receivedError === undefined, "Haven't gotten error yet");
receivedError = event.message;
event.preventDefault();
if (receivedMessage) {
SimpleTest.finish();
}
};
worker.port.postMessage(sentMessage);
});
worker.port.postMessage(sentMessage);
SimpleTest.waitForExplicitFinish();

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

@ -13,18 +13,16 @@
<script class="testbody" type="text/javascript">
var gced = false;
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
function() {
var sw = new SharedWorker('sharedWorker_lifetime.js');
sw.port.onmessage = function(event) {
ok(gced, "The SW is still alive also after GC");
SimpleTest.finish();
}
sw = null;
SpecialPowers.forceGC();
gced = true;
});
var sw = new SharedWorker('sharedWorker_lifetime.js');
sw.port.onmessage = function(event) {
ok(gced, "The SW is still alive also after GC");
SimpleTest.finish();
}
sw = null;
SpecialPowers.forceGC();
gced = true;
SimpleTest.waitForExplicitFinish();
</script>

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

@ -12,17 +12,14 @@
<body>
<script class="testbody" type="text/javascript">
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
function() {
var sw = new SharedWorker('sharedworker_performance_user_timing.js');
sw.port.onmessage = function(event) {
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
var sw = new SharedWorker('sharedworker_performance_user_timing.js');
sw.port.onmessage = function(event) {
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
});
}
SimpleTest.waitForExplicitFinish();
</script>

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

@ -12,28 +12,25 @@
<body>
<script class="testbody" type="text/javascript">
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
function() {
var sw1 = new SharedWorker('sharedWorker_ports.js');
sw1.port.onmessage = function(event) {
if (event.data.type == "connected") {
ok(true, "The SharedWorker is alive.");
var sw1 = new SharedWorker('sharedWorker_ports.js');
sw1.port.onmessage = function(event) {
if (event.data.type == "connected") {
ok(true, "The SharedWorker is alive.");
var sw2 = new SharedWorker('sharedWorker_ports.js');
sw1.port.postMessage("Port from the main-thread!", [sw2.port]);
return;
}
if (event.data.type == "status") {
ok(event.data.test, event.data.msg);
return;
}
if (event.data.type == "finish") {
SimpleTest.finish();
}
var sw2 = new SharedWorker('sharedWorker_ports.js');
sw1.port.postMessage("Port from the main-thread!", [sw2.port]);
return;
}
});
if (event.data.type == "status") {
ok(event.data.test, event.data.msg);
return;
}
if (event.data.type == "finish") {
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
</script>

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

@ -92,7 +92,6 @@ function runTest() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.workers.sharedWorkers.enabled", true],
["browser.startup.page", 0],
["browser.startup.homepage_override.mstone", "ignore"],
]}, runTest);

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

@ -13,17 +13,14 @@
<script class="testbody" type="text/javascript">
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
function() {
var sw = new SharedWorker('webSocket_sharedWorker.js');
sw.port.onmessage = function(event) {
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
var sw = new SharedWorker('webSocket_sharedWorker.js');
sw.port.onmessage = function(event) {
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
});
}
SimpleTest.waitForExplicitFinish();

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

@ -18,6 +18,7 @@
#include "nsXBLProtoImplMethod.h"
#include "nsXBLPrototypeHandler.h"
#include "nsXBLPrototypeResources.h"
#include "mozilla/WeakPtr.h"
class nsIAtom;
class nsIContent;
@ -36,9 +37,12 @@ class CSSStyleSheet;
// Instances of this class are owned by the nsXBLDocumentInfo object returned
// by XBLDocumentInfo(). Consumers who want to refcount things should refcount
// that.
class nsXBLPrototypeBinding final
class nsXBLPrototypeBinding final :
public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
{
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsXBLPrototypeBinding)
nsIContent* GetBindingElement() const { return mBinding; }
void SetBindingElement(nsIContent* aElement);
@ -290,7 +294,8 @@ protected:
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
// the constructor, and the destructor).
nsXBLPrototypeBinding* mBaseBinding; // Weak. The docinfo will own our base binding.
// Weak. The docinfo will own our base binding.
mozilla::WeakPtr<nsXBLPrototypeBinding> mBaseBinding;
bool mInheritStyle;
bool mCheckedBaseProto;
bool mKeyHandlersRegistered;

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

@ -730,7 +730,8 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
if (!docInfo)
return NS_ERROR_FAILURE;
nsXBLPrototypeBinding* protoBinding = docInfo->GetPrototypeBinding(ref);
WeakPtr<nsXBLPrototypeBinding> protoBinding =
docInfo->GetPrototypeBinding(ref);
if (!protoBinding) {
#ifdef DEBUG
@ -781,7 +782,7 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> baseBindingURI;
nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
WeakPtr<nsXBLPrototypeBinding> baseProto = protoBinding->GetBasePrototype();
if (baseProto) {
baseBindingURI = baseProto->BindingURI();
}
@ -826,7 +827,6 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
if (!aPeekOnly) {
// Make a new binding
protoBinding = docInfo->GetPrototypeBinding(ref);
NS_ENSURE_STATE(protoBinding);
nsXBLBinding *newBinding = new nsXBLBinding(protoBinding);

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

@ -918,6 +918,23 @@ XULDocument::AttributeWillChange(nsIDocument* aDocument,
}
}
static bool
ShouldPersistAttribute(nsIDocument* aDocument, Element* aElement)
{
if (aElement->IsXULElement(nsGkAtoms::window)) {
if (nsCOMPtr<nsPIDOMWindow> window = aDocument->GetWindow()) {
bool isFullscreen;
window->GetFullScreen(&isFullscreen);
if (isFullscreen) {
// Don't persist attributes if it is window element and
// we are in fullscreen state.
return false;
}
}
}
return true;
}
void
XULDocument::AttributeChanged(nsIDocument* aDocument,
Element* aElement, int32_t aNameSpaceID,
@ -992,18 +1009,19 @@ XULDocument::AttributeChanged(nsIDocument* aDocument,
bool listener, resolved;
CheckBroadcasterHookup(aElement, &listener, &resolved);
// See if there is anything we need to persist in the localstore.
//
// XXX Namespace handling broken :-(
nsAutoString persist;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
if (!persist.IsEmpty()) {
// XXXldb This should check that it's a token, not just a substring.
if (persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
if (ShouldPersistAttribute(aDocument, aElement)) {
// See if there is anything we need to persist in the localstore.
//
// XXX Namespace handling broken :-(
nsString persist;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
if (!persist.IsEmpty() &&
// XXXldb This should check that it's a token, not just a substring.
persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
nsContentUtils::AddScriptRunner(NS_NewRunnableMethodWithArgs
<nsIContent*, int32_t, nsIAtom*>
(this, &XULDocument::DoPersist, aElement, kNameSpaceID_None,
aAttribute));
<nsIContent*, int32_t, nsIAtom*>
(this, &XULDocument::DoPersist, aElement,
kNameSpaceID_None, aAttribute));
}
}
}

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

@ -106,7 +106,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
mSize.width = skiaTexGlue.fWidth = aSize.width;
mSize.height = skiaTexGlue.fHeight = aSize.height;
skiaTexGlue.fFlags = kNone_GrBackendTextureFlag;
skiaTexGlue.fOrigin = kBottomLeft_GrSurfaceOrigin;
skiaTexGlue.fOrigin = kTopLeft_GrSurfaceOrigin;
skiaTexGlue.fConfig = GfxFormatToGrConfig(aFormat);
skiaTexGlue.fSampleCnt = 0;
skiaTexGlue.fTextureHandle = aTexture;

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

@ -78,7 +78,8 @@ WheelScrollAnimation::InitPreferences(TimeStamp aTime)
mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
mIntervalRatio = (gfxPrefs::SmoothScrollDurationToIntervalRatio() * 100) / 100.0;
// The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
mIntervalRatio = std::max(1.0, mIntervalRatio);
InitializeHistory(aTime);

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

@ -169,12 +169,17 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
AddUniforms(result);
vs << "#ifdef GL_ES" << endl;
vs << "#define EDGE_PRECISION mediump" << endl;
vs << "#else" << endl;
vs << "#define EDGE_PRECISION" << endl;
vs << "#endif" << endl;
vs << "uniform mat4 uMatrixProj;" << endl;
vs << "uniform vec4 uLayerRects[4];" << endl;
vs << "uniform mat4 uLayerTransform;" << endl;
if (aConfig.mFeatures & ENABLE_DEAA) {
vs << "uniform mat4 uLayerTransformInverse;" << endl;
vs << "uniform vec3 uSSEdges[4];" << endl;
vs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
vs << "uniform vec2 uVisibleCenter;" << endl;
vs << "uniform vec2 uViewportSize;" << endl;
}
@ -282,8 +287,10 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
fs << "#ifdef GL_ES" << endl;
fs << "precision mediump float;" << endl;
fs << "#define COLOR_PRECISION lowp" << endl;
fs << "#define EDGE_PRECISION mediump" << endl;
fs << "#else" << endl;
fs << "#define COLOR_PRECISION" << endl;
fs << "#define EDGE_PRECISION" << endl;
fs << "#endif" << endl;
if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl;
@ -344,7 +351,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
}
if (aConfig.mFeatures & ENABLE_DEAA) {
fs << "uniform vec3 uSSEdges[4];" << endl;
fs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
}
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {

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

@ -66,7 +66,7 @@ private:
case NS_STYLE_TEXT_ORIENTATION_UPRIGHT:
flags |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
break;
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_RIGHT:
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS:
flags |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
break;
}

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

@ -4,12 +4,6 @@
-->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="100%" height="100%">
<!-- There is a bug with MultiTiledContentClient that causes improper painting;
bug 1204076 is on file for this issue. As a temporary workaround, we set
user-scalable=no here so that WantAsyncZoom() returns false and we don't
use a MultiTiledContentClient. Once bug 1204076 is fixed, we can remove this. -->
<meta xmlns="http://www.w3.org/1999/xhtml" name="viewport" content="user-scalable=no"/>
<title>Testcase for small circles</title>
<!--From https://bugzilla.mozilla.org/show_bug.cgi?id=1143303 -->

До

Ширина:  |  Высота:  |  Размер: 1.2 KiB

После

Ширина:  |  Высота:  |  Размер: 769 B

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

@ -4,36 +4,8 @@
# 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/.
os_win = 0
os_posix = 0
os_macosx = 0
os_dragonfly = 0
os_freebsd = 0
os_netbsd = 0
os_openbsd = 0
os_bsd = 0
os_linux = 0
if CONFIG['OS_ARCH'] == 'WINNT':
os_win = 1
else:
os_posix = 1
if CONFIG['OS_ARCH'] == 'Darwin':
os_macosx = 1
elif CONFIG['OS_ARCH'] == 'DragonFly':
os_dragonfly = 1
os_bsd = 1
elif CONFIG['OS_ARCH'] in ['FreeBSD', 'GNU_kFreeBSD']:
os_freebsd = 1
os_bsd = 1
elif CONFIG['OS_ARCH'] == 'NetBSD':
os_netbsd = 1
os_bsd = 1
elif CONFIG['OS_ARCH'] == 'OpenBSD':
os_openbsd = 1
os_bsd = 1
else:
os_linux = 1
libevent_path_prefix = 'src/third_party'
include(libevent_path_prefix + '/libeventcommon.mozbuild')
UNIFIED_SOURCES += [
'src/base/at_exit.cc',
@ -102,36 +74,7 @@ if os_win:
'src/chrome/common/transport_dib_win.cc',
]
elif not CONFIG['MOZ_NATIVE_LIBEVENT']:
UNIFIED_SOURCES += [
'src/third_party/libevent/buffer.c',
'src/third_party/libevent/bufferevent.c',
'src/third_party/libevent/bufferevent_ratelim.c',
'src/third_party/libevent/bufferevent_sock.c',
'src/third_party/libevent/event.c',
'src/third_party/libevent/event_tagging.c',
'src/third_party/libevent/evmap.c',
'src/third_party/libevent/evrpc.c',
'src/third_party/libevent/evthread.c',
'src/third_party/libevent/evthread_pthread.c',
'src/third_party/libevent/evutil.c',
'src/third_party/libevent/evutil_rand.c',
'src/third_party/libevent/http.c',
'src/third_party/libevent/listener.c',
'src/third_party/libevent/log.c',
'src/third_party/libevent/poll.c',
'src/third_party/libevent/select.c',
'src/third_party/libevent/signal.c',
'src/third_party/libevent/strlcpy.c',
]
SOURCES += [
# This file cannot be built in unified mode because of strtotimeval symbol clash.
'src/third_party/libevent/evdns.c',
]
DEFINES['HAVE_CONFIG_H'] = True
LOCAL_INCLUDES += [
'src/third_party/libevent',
'src/third_party/libevent/include',
]
DIRS += ['src/third_party']
if os_posix:
UNIFIED_SOURCES += [
@ -156,12 +99,6 @@ if os_posix:
'src/chrome/common/ipc_channel_posix.cc',
'src/chrome/common/process_watcher_posix_sigchld.cc',
]
if CONFIG['OS_TARGET'] == 'Android':
UNIFIED_SOURCES += [
'src/base/message_pump_android.cc',
]
DEFINES['ANDROID'] = True
DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
if os_macosx:
UNIFIED_SOURCES += [
@ -180,43 +117,10 @@ if os_macosx:
'src/chrome/common/transport_dib_mac.cc',
]
SOURCES += [
# This file cannot be built in unified mode because of the redefinition of NoOp.
# This file cannot be built in unified mode because of the redefinition
# of NoOp.
'src/base/platform_thread_mac.mm',
]
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
UNIFIED_SOURCES += [
'src/third_party/libevent/kqueue.c',
]
LOCAL_INCLUDES += ['src/third_party/libevent/mac']
if os_linux:
SOURCES += [
'src/base/atomicops_internals_x86_gcc.cc',
'src/base/idle_timer_none.cc',
'src/base/process_util_linux.cc',
'src/base/time_posix.cc',
]
if CONFIG['MOZ_WIDGET_GTK']:
SOURCES += [
'src/base/message_pump_glib.cc',
]
if CONFIG['MOZ_ENABLE_QT']:
SOURCES += [
'!moc_message_pump_qt.cc',
'src/base/message_pump_qt.cc',
]
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
if CONFIG['OS_TARGET'] != 'Android':
SOURCES += [
'src/third_party/libevent/epoll_sub.c',
]
SOURCES += [
'src/third_party/libevent/epoll.c',
]
if CONFIG['OS_TARGET'] == 'Android':
LOCAL_INCLUDES += ['src/third_party/libevent/android']
else:
LOCAL_INCLUDES += ['src/third_party/libevent/linux']
if os_bsd:
SOURCES += [
@ -231,6 +135,22 @@ if os_bsd:
SOURCES += [
'src/base/process_util_bsd.cc'
]
if os_linux:
SOURCES += [
'src/base/atomicops_internals_x86_gcc.cc',
'src/base/idle_timer_none.cc',
'src/base/process_util_linux.cc',
'src/base/time_posix.cc',
]
if CONFIG['OS_TARGET'] == 'Android':
UNIFIED_SOURCES += [
'src/base/message_pump_android.cc',
]
DEFINES['ANDROID'] = True
DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
if os_bsd or os_linux:
if CONFIG['MOZ_WIDGET_GTK']:
SOURCES += [
'src/base/message_pump_glib.cc',
@ -240,11 +160,6 @@ if os_bsd:
'!moc_message_pump_qt.cc',
'src/base/message_pump_qt.cc',
]
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
SOURCES += [
'src/third_party/libevent/kqueue.c',
]
LOCAL_INCLUDES += ['src/third_party/libevent/bsd']
ost = CONFIG['OS_TEST']
if '86' not in ost and 'arm' not in ost and 'mips' not in ost:

37
ipc/chromium/src/third_party/libeventcommon.mozbuild поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
os_win = 0
os_posix = 0
os_macosx = 0
os_bsd = 0
os_linux = 0
if CONFIG['OS_ARCH'] == 'WINNT':
os_win = 1
else:
os_posix = 1
if CONFIG['OS_ARCH'] == 'Darwin':
os_macosx = 1
libevent_include_suffix = 'mac'
elif CONFIG['OS_ARCH'] in ['DragonFly', 'FreeBSD', 'GNU_kFreeBSD',
'NetBSD', 'OpenBSD']:
os_bsd = 1
libevent_include_suffix = 'bsd'
else:
os_linux = 1
if CONFIG['OS_TARGET'] == 'Android':
libevent_include_suffix = 'android'
else:
libevent_include_suffix = 'linux'
if os_posix and not CONFIG['MOZ_NATIVE_LIBEVENT']:
DEFINES['HAVE_CONFIG_H'] = True
LOCAL_INCLUDES += sorted([
libevent_path_prefix + '/libevent',
libevent_path_prefix + '/libevent/include',
libevent_path_prefix + '/libevent/' + libevent_include_suffix,
])

59
ipc/chromium/src/third_party/moz.build поставляемый Normal file
Просмотреть файл

@ -0,0 +1,59 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
libevent_path_prefix = '.'
include(libevent_path_prefix + '/libeventcommon.mozbuild')
if os_win:
error('should not reach here on Windows')
if CONFIG['MOZ_NATIVE_LIBEVENT']:
error('should not reach here if we are using a native libevent')
UNIFIED_SOURCES += [
'libevent/buffer.c',
'libevent/bufferevent.c',
'libevent/bufferevent_ratelim.c',
'libevent/bufferevent_sock.c',
'libevent/event.c',
'libevent/event_tagging.c',
'libevent/evmap.c',
'libevent/evrpc.c',
'libevent/evthread.c',
'libevent/evthread_pthread.c',
'libevent/evutil.c',
'libevent/evutil_rand.c',
'libevent/http.c',
'libevent/listener.c',
'libevent/log.c',
'libevent/poll.c',
'libevent/select.c',
'libevent/signal.c',
'libevent/strlcpy.c',
]
SOURCES += [
# This file cannot be built in unified mode because of strtotimeval
# symbol clash.
'libevent/evdns.c',
]
if os_macosx or os_bsd:
UNIFIED_SOURCES += [
'libevent/kqueue.c',
]
if os_linux:
SOURCES += [
'libevent/epoll.c',
]
if CONFIG['OS_TARGET'] != 'Android':
SOURCES += [
'libevent/epoll_sub.c',
]
ALLOW_COMPILER_WARNINGS = True
FINAL_LIBRARY = 'xul'

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

@ -9,7 +9,7 @@
#include "base/process.h"
#include "mozilla/Mutex.h"
#if defined(OS_LINUX) || defined(OS_MACOSX)
#if defined(OS_LINUX) || defined(XP_DARWIN)
#include <pthread.h>
#include "SharedMemoryBasic.h"
#include "mozilla/Atomics.h"

1
ipc/glue/Makefile.in Normal file
Просмотреть файл

@ -0,0 +1 @@
%/SharedMemoryBasic_mach.cpp: ;

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

@ -10,7 +10,7 @@
#ifdef ANDROID
# include "mozilla/ipc/SharedMemoryBasic_android.h"
#elif defined(XP_MACOSX)
#elif defined(XP_DARWIN)
# include "mozilla/ipc/SharedMemoryBasic_mach.h"
#else
# include "mozilla/ipc/SharedMemoryBasic_chromium.h"

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

@ -9,7 +9,18 @@
#include <mach/vm_map.h>
#include <mach/mach_port.h>
#if defined(XP_IOS)
#include <mach/vm_map.h>
#define mach_vm_address_t vm_address_t
#define mach_vm_allocate vm_allocate
#define mach_vm_deallocate vm_deallocate
#define mach_vm_map vm_map
#define mach_vm_read vm_read
#define mach_vm_region_recurse vm_region_recurse_64
#define mach_vm_size_t vm_size_t
#else
#include <mach/mach_vm.h>
#endif
#include <pthread.h>
#include <unistd.h>
#include "SharedMemoryBasic.h"

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

@ -80,7 +80,7 @@ if CONFIG['OS_TARGET'] == 'Android':
elif CONFIG['OS_ARCH'] == 'Darwin':
EXPORTS.mozilla.ipc += ['SharedMemoryBasic_mach.h']
SOURCES += [
'SharedMemoryBasic_mach.cpp',
'SharedMemoryBasic_mach.mm',
]
else:
EXPORTS.mozilla.ipc += ['SharedMemoryBasic_chromium.h']

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

@ -703,7 +703,8 @@ struct JSClass {
// the beginning of every global object's slots for use by the
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 32)
#define JSCLASS_GLOBAL_SLOT_COUNT \
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 33)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \

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

@ -569,7 +569,7 @@ class Base {
//
// If wantNames is true, compute names for edges. Doing so can be expensive
// in time and memory.
virtual UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
virtual UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
// Return the Zone to which this node's referent belongs, or nullptr if the
// referent is not of a type allocated in SpiderMonkey Zones.
@ -756,8 +756,8 @@ class Node {
return base()->size(mallocSizeof);
}
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
return base()->edges(cx, wantNames);
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
return base()->edges(rt, wantNames);
}
bool hasAllocationStack() const { return base()->hasAllocationStack(); }
@ -868,7 +868,7 @@ class EdgeRange {
};
typedef mozilla::Vector<Edge, 8, js::TempAllocPolicy> EdgeVector;
typedef mozilla::Vector<Edge, 8, js::SystemAllocPolicy> EdgeVector;
// An EdgeRange concrete class that holds a pre-existing vector of
// Edges. A PreComputedEdgeRange does not take ownership of its
@ -883,7 +883,7 @@ class PreComputedEdgeRange : public EdgeRange {
}
public:
explicit PreComputedEdgeRange(JSContext* cx, EdgeVector& edges)
explicit PreComputedEdgeRange(EdgeVector& edges)
: edges(edges),
i(0)
{
@ -916,7 +916,7 @@ class PreComputedEdgeRange : public EdgeRange {
//
// {
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
// JS::ubi::RootList rootList(cx, maybeNoGC);
// JS::ubi::RootList rootList(rt, maybeNoGC);
// if (!rootList.init())
// return false;
//
@ -929,13 +929,13 @@ class PreComputedEdgeRange : public EdgeRange {
// }
class MOZ_STACK_CLASS RootList {
Maybe<AutoCheckCannotGC>& noGC;
JSContext* cx;
public:
JSRuntime* rt;
EdgeVector edges;
bool wantNames;
RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
// Find all GC roots.
bool init();
@ -959,7 +959,7 @@ class MOZ_STACK_CLASS RootList {
template<>
struct Concrete<RootList> : public Base {
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
const char16_t* typeName() const override { return concreteTypeName; }
protected:
@ -976,7 +976,7 @@ struct Concrete<RootList> : public Base {
template<typename Referent>
class TracerConcrete : public Base {
const char16_t* typeName() const override { return concreteTypeName; }
UniquePtr<EdgeRange> edges(JSContext*, bool wantNames) const override;
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
JS::Zone* zone() const override;
protected:
@ -1069,7 +1069,7 @@ template<>
class Concrete<void> : public Base {
const char16_t* typeName() const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
JS::Zone* zone() const override;
JSCompartment* compartment() const override;
CoarseType coarseType() const final;

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

@ -78,13 +78,13 @@ template<typename Handler>
struct BreadthFirst {
// Construct a breadth-first traversal object that reports the nodes it
// reaches to |handler|. The traversal object reports OOM on |cx|, and
// asserts that no GC happens in |cx|'s runtime during its lifetime.
// reaches to |handler|. The traversal asserts that no GC happens in its
// runtime during its lifetime.
//
// We do nothing with noGC, other than require it to exist, with a lifetime
// that encloses our own.
BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
: wantNames(true), cx(cx), visited(cx), handler(handler), pending(cx),
BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
: wantNames(true), rt(rt), visited(), handler(handler), pending(),
traversalBegun(false), stopRequested(false), abandonRequested(false)
{ }
@ -126,7 +126,7 @@ struct BreadthFirst {
pending.popFront();
// Get a range containing all origin's outgoing edges.
auto range = origin.edges(cx, wantNames);
auto range = origin.edges(rt, wantNames);
if (!range)
return false;
@ -181,13 +181,14 @@ struct BreadthFirst {
// Other edges *to* that referent will still be traversed.
void abandonReferent() { abandonRequested = true; }
// The context with which we were constructed.
JSContext* cx;
// The runtime with which we were constructed.
JSRuntime* rt;
// A map associating each node N that we have reached with a
// Handler::NodeData, for |handler|'s use. This is public, so that
// |handler| can access it to see the traversal thus far.
typedef js::HashMap<Node, typename Handler::NodeData> NodeMap;
using NodeMap = js::HashMap<Node, typename Handler::NodeData, js::DefaultHasher<Node>,
js::SystemAllocPolicy>;
NodeMap visited;
private:
@ -199,10 +200,10 @@ struct BreadthFirst {
// current population.
template <typename T>
class Queue {
js::Vector<T, 0> head, tail;
js::Vector<T, 0, js::SystemAllocPolicy> head, tail;
size_t frontIndex;
public:
explicit Queue(JSContext* cx) : head(cx), tail(cx), frontIndex(0) { }
Queue() : head(), tail(), frontIndex(0) { }
bool empty() { return frontIndex >= head.length(); }
T& front() {
MOZ_ASSERT(!empty());

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

@ -291,6 +291,7 @@ selfhosting_srcs := \
$(srcdir)/builtin/IntlData.js \
$(srcdir)/builtin/Iterator.js \
$(srcdir)/builtin/Map.js \
$(srcdir)/builtin/Module.js \
$(srcdir)/builtin/Number.js \
$(srcdir)/builtin/Object.js \
$(srcdir)/builtin/Reflect.js \

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

@ -201,6 +201,7 @@ class AutoSetHandlingSignal
#elif defined(XP_DARWIN)
# define EIP_sig(p) ((p)->uc_mcontext->__ss.__eip)
# define RIP_sig(p) ((p)->uc_mcontext->__ss.__rip)
# define R15_sig(p) ((p)->uc_mcontext->__ss.__pc)
#else
# error "Don't know how to read/write to the thread state via the mcontext_t."
#endif
@ -320,12 +321,20 @@ struct macos_x64_context {
x86_float_state64_t float_;
};
# define EMULATOR_CONTEXT macos_x64_context
# else
# elif defined(JS_CODEGEN_X86)
struct macos_x86_context {
x86_thread_state_t thread;
x86_float_state_t float_;
};
# define EMULATOR_CONTEXT macos_x86_context
# elif defined(JS_CODEGEN_ARM)
struct macos_arm_context {
arm_thread_state_t thread;
arm_neon_state_t float_;
};
# define EMULATOR_CONTEXT macos_arm_context
# else
# error Unsupported architecture
# endif
#else
# define EMULATOR_CONTEXT CONTEXT
@ -803,10 +812,16 @@ ContextToPC(EMULATOR_CONTEXT* context)
static_assert(sizeof(context->thread.__rip) == sizeof(void*),
"stored IP should be compile-time pointer-sized");
return reinterpret_cast<uint8_t**>(&context->thread.__rip);
# else
# elif defined(JS_CPU_X86)
static_assert(sizeof(context->thread.uts.ts32.__eip) == sizeof(void*),
"stored IP should be compile-time pointer-sized");
return reinterpret_cast<uint8_t**>(&context->thread.uts.ts32.__eip);
# elif defined(JS_CPU_ARM)
static_assert(sizeof(context->thread.__pc) == sizeof(void*),
"stored IP should be compile-time pointer-sized");
return reinterpret_cast<uint8_t**>(&context->thread.__pc);
# else
# error Unsupported architecture
# endif
}
@ -852,11 +867,18 @@ HandleMachException(JSRuntime* rt, const ExceptionRequest& request)
unsigned int float_state_count = x86_FLOAT_STATE64_COUNT;
int thread_state = x86_THREAD_STATE64;
int float_state = x86_FLOAT_STATE64;
# else
# elif defined(JS_CODEGEN_X86)
unsigned int thread_state_count = x86_THREAD_STATE_COUNT;
unsigned int float_state_count = x86_FLOAT_STATE_COUNT;
int thread_state = x86_THREAD_STATE;
int float_state = x86_FLOAT_STATE;
# elif defined(JS_CODEGEN_ARM)
unsigned int thread_state_count = ARM_THREAD_STATE_COUNT;
unsigned int float_state_count = ARM_NEON_STATE_COUNT;
int thread_state = ARM_THREAD_STATE;
int float_state = ARM_NEON_STATE;
# else
# error Unsupported architecture
# endif
kern_return_t kret;
kret = thread_get_state(rtThread, thread_state,

171
js/src/builtin/Module.js Normal file
Просмотреть файл

@ -0,0 +1,171 @@
/* 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/. */
function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = [])
{
// 15.2.1.16.3 ResolveExport(exportName, resolveSet, exportStarSet)
if (!IsObject(this) || !IsModule(this)) {
return callFunction(CallModuleMethodIfWrapped, this, exportName, resolveSet,
exportStarSet, "ModuleResolveExport");
}
// Step 1
let module = this;
// Step 2
for (let i = 0; i < resolveSet.length; i++) {
let r = resolveSet[i];
if (r.module === module && r.exportName === exportName)
return null;
}
// Step 3
resolveSet.push({module: module, exportName: exportName});
// Step 4
let localExportEntries = module.localExportEntries;
for (let i = 0; i < localExportEntries.length; i++) {
let e = localExportEntries[i];
if (exportName === e.exportName)
return {module: module, bindingName: e.localName};
}
// Step 5
let indirectExportEntries = module.indirectExportEntries;
for (let i = 0; i < indirectExportEntries.length; i++) {
let e = indirectExportEntries[i];
if (exportName === e.exportName) {
let importedModule = HostResolveImportedModule(module, e.moduleRequest);
let indirectResolution = importedModule.resolveExport(e.importName,
resolveSet,
exportStarSet);
if (indirectResolution !== null)
return indirectResolution;
}
}
// Step 6
if (exportName === "default") {
// A default export cannot be provided by an export *.
ThrowSyntaxError(JSMSG_BAD_DEFAULT_EXPORT);
}
// Step 7
if (module in exportStarSet)
return null;
// Step 8
exportStarSet.push(module);
// Step 9
let starResolution = null;
// Step 10
let starExportEntries = module.starExportEntries;
for (let i = 0; i < starExportEntries.length; i++) {
let e = starExportEntries[i];
let importedModule = HostResolveImportedModule(module, e.moduleRequest);
let resolution = importedModule.resolveExport(exportName, resolveSet, exportStarSet);
if (resolution === "ambiguous")
return resolution;
if (resolution !== null) {
if (starResolution === null) {
starResolution = resolution;
} else {
if (resolution.module !== starResolution.module ||
resolution.exportName !== starResolution.exportName)
{
return "ambiguous";
}
}
}
}
return starResolution;
}
// 15.2.1.16.4 ModuleDeclarationInstantiation()
function ModuleDeclarationInstantiation()
{
if (!IsObject(this) || !IsModule(this))
return callFunction(CallModuleMethodIfWrapped, this, "ModuleDeclarationInstantiation");
// Step 1
let module = this;
// Step 5
if (module.environment !== undefined)
return;
// Step 7
CreateModuleEnvironment(module);
let env = module.environment;
// Step 8
let requestedModules = module.requestedModules;
for (let i = 0; i < requestedModules.length; i++) {
let required = requestedModules[i];
let requiredModule = HostResolveImportedModule(module, required);
requiredModule.declarationInstantiation();
}
// Step 9
let indirectExportEntries = module.indirectExportEntries;
for (let i = 0; i < indirectExportEntries.length; i++) {
let e = indirectExportEntries[i];
let resolution = module.resolveExport(e.exportName);
if (resolution === null)
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT);
if (resolution === "ambiguous")
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT);
}
// Step 12
let importEntries = module.importEntries;
for (let i = 0; i < importEntries.length; i++) {
let imp = importEntries[i];
let importedModule = HostResolveImportedModule(module, imp.moduleRequest);
if (imp.importName === "*") {
// TODO
// let namespace = GetModuleNamespace(importedModule);
// CreateNamespaceBinding(module.environment, imp.localName, namespace);
} else {
let resolution = importedModule.resolveExport(imp.importName);
if (resolution === null)
ThrowSyntaxError(JSMSG_MISSING_IMPORT);
if (resolution === "ambiguous")
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT);
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
}
}
}
// 15.2.1.16.5 ModuleEvaluation()
function ModuleEvaluation()
{
if (!IsObject(this) || !IsModule(this))
return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluation");
// Step 1
let module = this;
// Step 4
if (module.evaluated)
return undefined;
// Step 5
SetModuleEvaluated(this);
// Step 6
let requestedModules = module.requestedModules;
for (let i = 0; i < requestedModules.length; i++) {
let required = requestedModules[i];
let requiredModule = HostResolveImportedModule(module, required);
requiredModule.evaluation();
}
return EvaluateModule(module);
}

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

@ -211,6 +211,13 @@ ExportEntryObject::create(JSContext* cx,
return self;
}
///////////////////////////////////////////////////////////////////////////
// IndirectBinding
IndirectBinding::IndirectBinding(Handle<ModuleEnvironmentObject*> environment, HandleId localName)
: environment(environment), localName(localName)
{}
///////////////////////////////////////////////////////////////////////////
// ModuleObject
@ -228,7 +235,7 @@ ModuleObject::class_ = {
nullptr, /* resolve */
nullptr, /* mayResolve */
nullptr, /* convert */
nullptr, /* finalize */
ModuleObject::finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
@ -257,7 +264,39 @@ ModuleObject::isInstance(HandleValue value)
/* static */ ModuleObject*
ModuleObject::create(ExclusiveContext* cx)
{
return NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject);
Rooted<ModuleObject*> self(cx, NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject));
IndirectBindingMap* bindings = cx->new_<IndirectBindingMap>();
if (!bindings || !bindings->init()) {
ReportOutOfMemory(cx);
return nullptr;
}
self->setReservedSlot(ImportBindingsSlot, PrivateValue(bindings));
return self;
}
/* static */ void
ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
{
fop->delete_(&obj->as<ModuleObject>().importBindings());
}
ModuleEnvironmentObject*
ModuleObject::environment() const
{
Value value = getReservedSlot(EnvironmentSlot);
if (value.isUndefined())
return nullptr;
return &value.toObject().as<ModuleEnvironmentObject>();
}
IndirectBindingMap&
ModuleObject::importBindings()
{
return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
}
void
@ -265,6 +304,7 @@ ModuleObject::init(HandleScript script)
{
MOZ_ASSERT(!script->enclosingStaticScope());
initReservedSlot(ScriptSlot, PrivateValue(script));
initReservedSlot(EvaluatedSlot, BooleanValue(false));
}
void
@ -301,6 +341,12 @@ ModuleObject::script() const
return static_cast<JSScript*>(getReservedSlot(ScriptSlot).toPrivate());
}
bool
ModuleObject::evaluated() const
{
return getReservedSlot(EvaluatedSlot).toBoolean();
}
ModuleEnvironmentObject&
ModuleObject::initialEnvironment() const
{
@ -325,9 +371,45 @@ ModuleObject::trace(JSTracer* trc, JSObject* obj)
TraceManuallyBarrieredEdge(trc, &script, "Module script");
module.setReservedSlot(ScriptSlot, PrivateValue(script));
}
IndirectBindingMap& bindings = module.importBindings();
for (IndirectBindingMap::Enum e(bindings); !e.empty(); e.popFront()) {
IndirectBinding& b = e.front().value();
TraceEdge(trc, &b.environment, "module import environment");
TraceEdge(trc, &b.localName, "module import local name");
jsid bindingName = e.front().key();
TraceManuallyBarrieredEdge(trc, &bindingName, "module import binding name");
MOZ_ASSERT(bindingName == e.front().key());
}
}
void
ModuleObject::createEnvironment()
{
// The environment has already been created, we just neet to set it in the
// right slot.
MOZ_ASSERT(!getReservedSlot(InitialEnvironmentSlot).isUndefined());
MOZ_ASSERT(getReservedSlot(EnvironmentSlot).isUndefined());
setReservedSlot(EnvironmentSlot, getReservedSlot(InitialEnvironmentSlot));
}
void
ModuleObject::setEvaluated()
{
MOZ_ASSERT(!evaluated());
setReservedSlot(EvaluatedSlot, TrueHandleValue);
}
bool
ModuleObject::evaluate(JSContext* cx, MutableHandleValue rval)
{
RootedScript script(cx, this->script());
return JS_ExecuteScript(cx, script, rval);
}
DEFINE_GETTER_FUNCTIONS(ModuleObject, initialEnvironment, InitialEnvironmentSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, environment, EnvironmentSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluated, EvaluatedSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
@ -339,6 +421,8 @@ js::InitModuleClass(JSContext* cx, HandleObject obj)
{
static const JSPropertySpec protoAccessors[] = {
JS_PSG("initialEnvironment", ModuleObject_initialEnvironmentGetter, 0),
JS_PSG("environment", ModuleObject_environmentGetter, 0),
JS_PSG("evaluated", ModuleObject_evaluatedGetter, 0),
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
@ -347,13 +431,20 @@ js::InitModuleClass(JSContext* cx, HandleObject obj)
JS_PS_END
};
static const JSFunctionSpec protoFunctions[] = {
JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 3, 0),
JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0),
JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0),
JS_FS_END
};
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
if (!proto)
return nullptr;
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, protoFunctions))
return nullptr;
global->setPrototype(JSProto_Module, ObjectValue(*proto));

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

@ -8,6 +8,7 @@
#define builtin_ModuleObject_h
#include "jsapi.h"
#include "jsatom.h"
#include "js/TraceableVector.h"
@ -70,6 +71,15 @@ class ExportEntryObject : public NativeObject
JSAtom* localName();
};
struct IndirectBinding
{
IndirectBinding(Handle<ModuleEnvironmentObject*> environment, HandleId localName);
RelocatablePtr<ModuleEnvironmentObject*> environment;
RelocatableId localName;
};
typedef HashMap<jsid, IndirectBinding, JsidHasher, SystemAllocPolicy> IndirectBindingMap;
class ModuleObject : public NativeObject
{
public:
@ -77,11 +87,14 @@ class ModuleObject : public NativeObject
{
ScriptSlot = 0,
InitialEnvironmentSlot,
EnvironmentSlot,
EvaluatedSlot,
RequestedModulesSlot,
ImportEntriesSlot,
LocalExportEntriesSlot,
IndirectExportEntriesSlot,
StarExportEntriesSlot,
ImportBindingsSlot,
SlotCount
};
@ -100,15 +113,24 @@ class ModuleObject : public NativeObject
JSScript* script() const;
ModuleEnvironmentObject& initialEnvironment() const;
ModuleEnvironmentObject* environment() const;
bool evaluated() const;
ArrayObject& requestedModules() const;
ArrayObject& importEntries() const;
ArrayObject& localExportEntries() const;
ArrayObject& indirectExportEntries() const;
ArrayObject& starExportEntries() const;
JSObject* enclosingStaticScope() const;
IndirectBindingMap& importBindings();
void createEnvironment();
void setEvaluated();
bool evaluate(JSContext*cx, MutableHandleValue rval);
private:
static void trace(JSTracer* trc, JSObject* obj);
static void finalize(js::FreeOp* fop, JSObject* obj);
bool hasScript() const;
};
@ -135,6 +157,7 @@ class MOZ_STACK_CLASS ModuleBuilder
JSContext* cx_;
RootedAtomVector requestedModules_;
RootedAtomVector importedBoundNames_;
RootedImportEntryVector importEntries_;
RootedExportEntryVector exportEntries_;

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

@ -2127,9 +2127,9 @@ struct FindPathHandler {
typedef BackEdge NodeData;
typedef JS::ubi::BreadthFirst<FindPathHandler> Traversal;
FindPathHandler(JS::ubi::Node start, JS::ubi::Node target,
FindPathHandler(JSContext*cx, JS::ubi::Node start, JS::ubi::Node target,
AutoValueVector& nodes, Vector<EdgeName>& edges)
: start(start), target(target), foundPath(false),
: cx(cx), start(start), target(target), foundPath(false),
nodes(nodes), edges(edges) { }
bool
@ -2143,7 +2143,7 @@ struct FindPathHandler {
// Record how we reached this node. This is the last edge on a
// shortest path to this node.
EdgeName edgeName = DuplicateString(traversal.cx, edge.name);
EdgeName edgeName = DuplicateString(cx, edge.name);
if (!edgeName)
return false;
*backEdge = mozilla::Move(BackEdge(origin, Move(edgeName)));
@ -2180,6 +2180,8 @@ struct FindPathHandler {
return true;
}
JSContext* cx;
// The node we're starting from.
JS::ubi::Node start;
@ -2238,8 +2240,8 @@ FindPath(JSContext* cx, unsigned argc, Value* vp)
JS::ubi::Node start(args[0]), target(args[1]);
heaptools::FindPathHandler handler(start, target, nodes, edges);
heaptools::FindPathHandler::Traversal traversal(cx, handler, autoCannotGC);
heaptools::FindPathHandler handler(cx, start, target, nodes, edges);
heaptools::FindPathHandler::Traversal traversal(cx->runtime(), handler, autoCannotGC);
if (!traversal.init() || !traversal.addStart(start))
return false;

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

@ -673,7 +673,7 @@ class GCRuntime
bool onBackgroundThread() { return helperState.onBackgroundThread(); }
bool currentThreadOwnsGCLock() {
return lockOwner == PR_GetCurrentThread();
return lockOwner.value == PR_GetCurrentThread();
}
#endif // DEBUG
@ -684,15 +684,17 @@ class GCRuntime
void lockGC() {
PR_Lock(lock);
MOZ_ASSERT(!lockOwner);
#ifdef DEBUG
lockOwner = PR_GetCurrentThread();
MOZ_ASSERT(!lockOwner.value);
lockOwner.value = PR_GetCurrentThread();
#endif
}
void unlockGC() {
MOZ_ASSERT(lockOwner == PR_GetCurrentThread());
lockOwner = nullptr;
#ifdef DEBUG
MOZ_ASSERT(lockOwner.value == PR_GetCurrentThread());
lockOwner.value = nullptr;
#endif
PR_Unlock(lock);
}
@ -1298,7 +1300,7 @@ class GCRuntime
/* Synchronize GC heap access between main thread and GCHelperState. */
PRLock* lock;
mozilla::DebugOnly<PRThread*> lockOwner;
mozilla::DebugOnly<mozilla::Atomic<PRThread*>> lockOwner;
BackgroundAllocTask allocTask;
GCHelperState helperState;

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

@ -370,7 +370,8 @@ AssertRootMarkingPhase(JSTracer* trc)
D(GlobalObject*) \
D(JSObject*) \
D(JSFunction*) \
D(ModuleObject*) \
D(ModuleObject*) \
D(ModuleEnvironmentObject*) \
D(NestedScopeObject*) \
D(PlainObject*) \
D(SavedFrame*) \

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

@ -133,6 +133,14 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
pushedNonVolatileRegisters++;
}
#if defined(XP_IOS) && defined(JS_CODEGEN_ARM)
// The stack is 4-byte aligned on iOS, force 8-byte alignment.
masm.movePtr(StackPointer, temp0);
masm.andPtr(Imm32(~7), StackPointer);
masm.push(temp0);
masm.push(temp0);
#endif
#ifndef JS_CODEGEN_X86
// The InputOutputData* is stored as an argument, save it on the stack
// above the frame.
@ -369,6 +377,11 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
masm.freeStack(frameSize);
#endif
#if defined(XP_IOS) && defined(JS_CODEGEN_ARM)
masm.pop(temp0);
masm.movePtr(temp0, StackPointer);
#endif
// Restore non-volatile registers which were saved on entry.
for (GeneralRegisterBackwardIterator iter(savedNonVolatileRegisters); iter.more(); ++iter)
masm.Pop(*iter);

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