merge mozilla-inbound to mozilla-central a=merge

--HG--
rename : browser/locales/en-US/chrome/browser/devtools/memory.properties => devtools/client/locales/en-US/memory.properties
This commit is contained in:
Carsten "Tomcat" Book 2015-11-05 11:58:55 +01:00
commit bb068eacd7
290 changed files with 4515 additions and 1594 deletions

View File

@ -119,7 +119,7 @@
accesskey="&bookmarkAllTabs.accesskey;"
command="Browser:BookmarkAllTabs"/>
<menuitem id="context_closeTabsToTheEnd" label="&closeTabsToTheEnd.label;" accesskey="&closeTabsToTheEnd.accesskey;"
oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab);"/>
oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
<menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
<menuseparator/>

View File

@ -2049,12 +2049,13 @@
<method name="removeTabsToTheEndFrom">
<parameter name="aTab"/>
<parameter name="aParams"/>
<body>
<![CDATA[
if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) {
let tabs = this.getTabsToTheEndFrom(aTab);
for (let i = tabs.length - 1; i >= 0; --i) {
this.removeTab(tabs[i], {animate: true});
this.removeTab(tabs[i], aParams);
}
}
]]>

View File

@ -70,12 +70,8 @@ function loadTabInWindow(win, callback) {
info("Loading tab");
let url = "http://user:pass@example.com/";
let tab = win.gBrowser.selectedTab = win.gBrowser.addTab(url);
tab.linkedBrowser.addEventListener("load", function listener() {
BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url).then(() => {
info("Tab loaded");
if (tab.linkedBrowser.currentURI.spec != url)
return;
tab.linkedBrowser.removeEventListener("load", listener, true);
is(win.gURLBar.textValue, "example.com", "URL bar had user/pass stripped initially");
callback(tab);
}, true);

View File

@ -2,9 +2,7 @@ function test () {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
let doc = gBrowser.contentDocument;
let tooltip = document.getElementById("aHTMLTooltip");
@ -35,9 +33,10 @@ function test () {
gBrowser.removeCurrentTab();
finish();
}, true);
});
content.location =
"http://mochi.test:8888/browser/browser/base/content/test/general/title_test.svg";
gBrowser.loadURI(
"http://mochi.test:8888/browser/browser/base/content/test/general/title_test.svg"
);
}

View File

@ -4,9 +4,7 @@
function test () {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
let doc = gBrowser.contentDocument;
let tooltip = document.getElementById("aHTMLTooltip");
@ -15,9 +13,10 @@ function test () {
gBrowser.removeCurrentTab();
finish();
}, true);
});
content.location =
"http://mochi.test:8888/browser/browser/base/content/test/general/xul_tooltiptext.xhtml";
gBrowser.loadURI(
"http://mochi.test:8888/browser/browser/base/content/test/general/xul_tooltiptext.xhtml"
);
}

View File

@ -22,7 +22,7 @@ function test() {
function addTab(aURI, aIndex) {
var tab = gBrowser.addTab(aURI);
if (aIndex == 0)
gBrowser.removeTab(gBrowser.tabs[0]);
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
tab.linkedBrowser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
@ -41,14 +41,14 @@ function doTabsTest() {
var scheme = closedTab.linkedBrowser.currentURI.scheme;
Array.slice(gBrowser.tabs).forEach(function (aTab) {
if (aTab != closedTab && aTab.linkedBrowser.currentURI.scheme == scheme)
gBrowser.removeTab(aTab);
gBrowser.removeTab(aTab, {skipPermitUnload: true});
});
}, true);
gBrowser.removeTab(gBrowser.tabs[0]);
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
is(gBrowser.tabs.length, 1, "Related tabs are not closed unexpectedly");
gBrowser.addTab("about:blank");
gBrowser.removeTab(gBrowser.tabs[0]);
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
finish();
}

View File

@ -1,42 +1,63 @@
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
// Navigate to a site with a broken cert
window.addEventListener("DOMContentLoaded", testBrokenCert, true);
content.location = "https://nocert.example.com/";
function remote(task) {
return ContentTask.spawn(gBrowser.selectedBrowser, null, task);
}
function testBrokenCert() {
if (gBrowser.contentDocument.documentURI === "about:blank")
return;
window.removeEventListener("DOMContentLoaded", testBrokenCert, true);
add_task(function* () {
gBrowser.selectedTab = gBrowser.addTab();
let promise = remote(function () {
return ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", true, event => {
return content.document.documentURI != "about:blank";
}).then(() => 0); // don't want to send the event to the chrome process
});
gBrowser.loadURI("https://nocert.example.com/");
yield promise;
let uri = yield remote(() => {
return content.document.documentURI;
});
// Confirm that we are displaying the contributed error page, not the default
ok(gBrowser.contentDocument.documentURI.startsWith("about:certerror"), "Broken page should go to about:certerror, not about:neterror");
ok(uri.startsWith("about:certerror"), "Broken page should go to about:certerror, not about:neterror");
let advancedDiv, advancedDivVisibility, technicalDivCollapsed;
[advancedDiv, advancedDivVisibility] = yield remote(() => {
let div = content.document.getElementById("advancedPanel");
if (div) {
return [true, div.ownerDocument.defaultView.getComputedStyle(div, "").visibility];
} else {
return [null, null];
}
});
// Confirm that the expert section is collapsed
var advancedDiv = gBrowser.contentDocument.getElementById("advancedPanel");
ok(advancedDiv, "Advanced content div should exist");
is_element_hidden(advancedDiv, "Advanced content should not be visible by default");
is(advancedDivVisibility, "hidden", "Advanced content should not be visible by default");
// Tweak the expert mode pref
gPrefService.setBoolPref("browser.xul.error_pages.expert_bad_cert", true);
window.addEventListener("DOMContentLoaded", testExpertPref, true);
promise = remote(function () {
return ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", true);
});
gBrowser.reload();
}
yield promise;
[advancedDiv, advancedDivVisibility] = yield remote(() => {
let div = content.document.getElementById("advancedPanel");
if (div) {
return [true, div.ownerDocument.defaultView.getComputedStyle(div, "").visibility];
} else {
return [null, null];
}
});
function testExpertPref() {
window.removeEventListener("DOMContentLoaded", testExpertPref, true);
var advancedDiv = gBrowser.contentDocument.getElementById("advancedPanel");
ok(advancedDiv, "Advanced content div should exist");
is_element_visible(advancedDiv, "Advanced content should be visible by default");
is(advancedDivVisibility, "visible", "Advanced content should be visible by default");
// Clean up
gBrowser.removeCurrentTab();
if (gPrefService.prefHasUserValue("browser.xul.error_pages.expert_bad_cert"))
gPrefService.clearUserPref("browser.xul.error_pages.expert_bad_cert");
finish();
}
});

View File

@ -99,7 +99,7 @@ function checkBookmarksPanel(invoker, phase)
if (currentInvoker < invokers.length) {
checkBookmarksPanel(invokers[currentInvoker], 1);
} else {
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
PlacesUtils.bookmarks.removeItem(bookmarkId);
executeSoon(finish);
}

View File

@ -2,15 +2,16 @@ function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
is(document.getElementById("identity-box").className,
"unknownIdentity mixedDisplayContent",
"identity box has class name for mixed content");
gBrowser.removeCurrentTab();
finish();
}, true);
});
content.location = "https://example.com/browser/browser/base/content/test/general/test_bug435035.html";
gBrowser.loadURI(
"https://example.com/browser/browser/base/content/test/general/test_bug435035.html"
);
}

View File

@ -30,16 +30,16 @@ function test() {
// Start the sub-document load.
let deferred = Promise.defer();
executeSoon(function () {
testBrowser.addEventListener("load", function (e) {
testBrowser.removeEventListener("load", arguments.callee, true);
is(e.target.defaultView.location, TEST_IFRAME_URL, "got the load event for the iframe");
BrowserTestUtils.browserLoaded(testBrowser, true).then(url => {
is(url, TEST_IFRAME_URL, "got the load event for the iframe");
is(ZoomManager.zoom, zoomLevel, "zoom is retained after sub-document load");
FullZoomHelper.removeTabAndWaitForLocationChange().
then(() => deferred.resolve());
}, true);
content.document.querySelector("iframe").src = TEST_IFRAME_URL;
});
ContentTask.spawn(testBrowser, TEST_IFRAME_URL, url => {
content.document.querySelector("iframe").src = url;
});
});
yield deferred.promise;
}).then(finish, FullZoomHelper.failAndContinue(finish));

View File

@ -1,4 +1,4 @@
function test() {
add_task(function*() {
is(gBrowser.tabs.length, 1, "one tab is open");
gBrowser.selectedBrowser.focus();
@ -6,11 +6,15 @@ function test() {
var tab = gBrowser.selectedTab;
gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
let tabClosedPromise = BrowserTestUtils.removeTab(tab, {dontRemove: true});
EventUtils.synthesizeKey("w", { accelKey: true });
yield tabClosedPromise;
is(tab.parentNode, null, "ctrl+w removes the tab");
is(gBrowser.tabs.length, 1, "a new tab has been opened");
is(document.activeElement, gURLBar.inputField, "location bar is focused for the new tab");
if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
}
});

View File

@ -18,10 +18,13 @@ function record(aName) {
if (actual.length == expected.length) {
is(actual.toString(), expected.toString(),
"got events and progress notifications in expected order");
gBrowser.removeTab(tab);
gBrowser.removeTabsProgressListener(progressListener);
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
finish();
executeSoon(function(tab) {
gBrowser.removeTab(tab);
gBrowser.removeTabsProgressListener(progressListener);
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
finish();
}.bind(null, tab));
}
}

View File

@ -6,14 +6,14 @@ function test() {
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
gBrowser.selectedTab = childTab1;
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
is(idx(gBrowser.selectedTab), idx(tab1),
"closing a tab next to its parent selects the parent");
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
gBrowser.selectedTab = tab2;
gBrowser.selectedTab = childTab1;
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
is(idx(gBrowser.selectedTab), idx(tab2),
"closing a tab next to its parent doesn't select the parent if another tab had been selected ad interim");
@ -21,14 +21,14 @@ function test() {
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
childTab2 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
gBrowser.selectedTab = childTab1;
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
is(idx(gBrowser.selectedTab), idx(childTab2),
"closing a tab next to its parent selects the next tab with the same parent");
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
is(idx(gBrowser.selectedTab), idx(tab2),
"closing the last tab in a set of child tabs doesn't go back to the parent");
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab2, { skipPermitUnload: true });
}
function idx(tab) {

View File

@ -803,12 +803,9 @@ function test_urlbar() {
function test_wronghost() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec != TESTROOT2 + "enabled.html")
return;
gBrowser.removeEventListener("load", arguments.callee, true);
let requestedUrl = TESTROOT2 + "enabled.html";
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, requestedUrl).then(() => {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the complete notification
@ -825,7 +822,7 @@ function test_wronghost() {
});
gBrowser.loadURI(TESTROOT + "corrupt.xpi");
}, true);
});
gBrowser.loadURI(TESTROOT2 + "enabled.html");
},
@ -848,12 +845,8 @@ function test_reload() {
PopupNotifications.panel.addEventListener("popuphiding", test_fail, false);
gBrowser.addEventListener("load", function() {
if (gBrowser.currentURI.spec != TESTROOT2 + "enabled.html")
return;
gBrowser.removeEventListener("load", arguments.callee, true);
let requestedUrl = TESTROOT2 + "enabled.html";
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, requestedUrl).then(() => {
PopupNotifications.panel.removeEventListener("popuphiding", test_fail, false);
AddonManager.getAllInstalls(function(aInstalls) {
@ -864,7 +857,7 @@ function test_reload() {
wait_for_notification_close(runNextTest);
gBrowser.removeTab(gBrowser.selectedTab);
});
}, true);
});
gBrowser.loadURI(TESTROOT2 + "enabled.html");
});

View File

@ -1,9 +1,7 @@
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
let doc = gBrowser.contentDocument;
let tooltip = document.getElementById("aHTMLTooltip");
let i = doc.getElementById("i");
@ -21,9 +19,10 @@ function test() {
gBrowser.removeCurrentTab();
finish();
}, true);
});
content.location =
"data:text/html,<!DOCTYPE html><html><body><input id='i'></body></html>";
gBrowser.loadURI(
"data:text/html,<!DOCTYPE html><html><body><input id='i'></body></html>"
);
}

View File

@ -14,13 +14,11 @@ function test() {
is(gURLBar.value, URI, "location bar value matches test URI after switching tabs");
waitForExplicitFinish();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
is(gBrowser.userTypedValue, null, "userTypedValue is null as the page has loaded");
is(gURLBar.value, URI, "location bar value matches test URI as the page has loaded");
gBrowser.removeCurrentTab();
finish();
}, true);
});
}

View File

@ -8,19 +8,18 @@ function test() {
let uriObj = Services.io.newURI(uriString, null, null)
let cp = Components.classes["@mozilla.org/cookie/permission;1"]
.getService(Components.interfaces.nsICookiePermission);
Services.prefs.setIntPref(cookieBehavior, 2);
cp.setAccess(uriObj, cp.ACCESS_ALLOW);
gBrowser.selectedTab = gBrowser.addTab(uriString);
waitForExplicitFinish();
gBrowser.selectedBrowser.addEventListener("load", onTabLoaded, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(onTabLoaded);
function onTabLoaded() {
is(gBrowser.selectedBrowser.contentWindow.navigator.cookieEnabled, true,
"navigator.cookieEnabled should be true");
// Clean up
gBrowser.selectedBrowser.removeEventListener("load", onTabLoaded, true);
gBrowser.removeTab(gBrowser.selectedTab);
Services.prefs.setIntPref(cookieBehavior, 0);
cp.setAccess(uriObj, cp.ACCESS_DEFAULT);

View File

@ -5,8 +5,8 @@
function test() {
let newTab = gBrowser.addTab();
waitForExplicitFinish();
newTab.linkedBrowser.addEventListener("load", mainPart, true);
BrowserTestUtils.browserLoaded(newTab.linkedBrowser).then(mainPart);
function mainPart() {
gBrowser.pinTab(newTab);
gBrowser.selectedTab = newTab;
@ -20,7 +20,6 @@ function test() {
openUILinkIn("http://example.org/", "current");
is(gBrowser.tabs.length, 3, "Should open in new tab");
newTab.removeEventListener("load", mainPart, true);
gBrowser.removeTab(newTab);
gBrowser.removeTab(gBrowser.tabs[1]); // example.org tab
finish();

View File

@ -17,12 +17,10 @@ function test() {
var tab = gBrowser.addTab("http://mochi.test:8888/");
var browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(browser).then(() => {
BrowserTestUtils.removeTab(tab).then(() => {
ok(isUndoCloseEnabled(), "Undo Close Tab should be enabled.");
finish();
});
}, true);
});
}

View File

@ -58,9 +58,7 @@ function todo_check(aElementName, aBarred) {
function test () {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
let testData = [
/* element name, barred */
[ 'input', false, null],
@ -87,9 +85,10 @@ function test () {
gBrowser.removeCurrentTab();
finish();
}, true);
});
content.location =
"data:text/html,<!DOCTYPE html><html><body><form id='content'></form></body></html>";
gBrowser.loadURI(
"data:text/html,<!DOCTYPE html><html><body><form id='content'></form></body></html>"
);
}

View File

@ -14,6 +14,13 @@ function testAttrib(elem, attrib, attribValue, msg) {
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
is(gBrowser.tabs.length, 1, "one tab is open initially");
// Add several new tabs in sequence, hiding some, to ensure that the

View File

@ -5,11 +5,9 @@
function test() {
let newTab = gBrowser.addTab("http://example.com");
waitForExplicitFinish();
newTab.linkedBrowser.addEventListener("load", mainPart, true);
BrowserTestUtils.browserLoaded(newTab.linkedBrowser).then(mainPart);
function mainPart() {
newTab.linkedBrowser.removeEventListener("load", mainPart, true);
gBrowser.pinTab(newTab);
gBrowser.selectedTab = newTab;

View File

@ -5,6 +5,12 @@
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
// establish initial state
is(gBrowser.tabs.length, 1, "we start with one tab");

View File

@ -17,15 +17,13 @@ function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab();
tab.linkedBrowser.addEventListener("load", (function(event) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
if (BookmarkingUI.status == BookmarkingUI.STATUS_UPDATING) {
waitForCondition(() => BookmarkingUI.status != BookmarkingUI.STATUS_UPDATING, finishTest, "BookmarkingUI was updating for too long");
} else {
finishTest();
}
}), true);
});
tab.linkedBrowser.loadURI("http://example.com/browser/browser/base/content/test/general/dummy_page.html");
}

View File

@ -4,17 +4,12 @@
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedTab = gBrowser.addTab("data:text/html,<iframe width='700' height='700' src='about:certerror'></iframe>");
// Open a html page with about:certerror in an iframe
gBrowser.selectedBrowser.addEventListener("load", testIframeCert, true);
content.location = "data:text/html,<iframe width='700' height='700' src='about:certerror'></iframe>";
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(testIframeCert);
}
function testIframeCert(e) {
if (e.target.location.href == "about:blank") {
return;
}
gBrowser.selectedBrowser.removeEventListener("load", testIframeCert, true);
// Confirm that the expert section is hidden
var doc = gBrowser.contentDocument.getElementsByTagName('iframe')[0].contentDocument;
var aP = doc.getElementById("advancedPanel");

View File

@ -1,16 +1,10 @@
function test () {
requestLongerTimeout(2);
waitForExplicitFinish();
var isHTTPS = false;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
if (isHTTPS) {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
}
let doc = gBrowser.contentDocument;
function loadListener() {
function testLocation(link, url, next) {
var tabOpenListener = new TabOpenListener(url, function () {
gBrowser.removeTab(this.tab);
@ -18,18 +12,26 @@ function test () {
next();
});
doc.getElementById(link).click();
ContentTask.spawn(gBrowser.selectedBrowser, link, link => {
content.document.getElementById(link).click();
});
}
function testLink(link, name, next) {
addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function (win) {
is(doc.getElementById("unload-flag").textContent, "Okay", "beforeunload shouldn't have fired");
is(win.document.getElementById("location").value, name, "file name should match");
win.close();
next();
addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function (win) {
ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
return content.document.getElementById("unload-flag").textContent;
}).then(unloadFlag => {
is(unloadFlag, "Okay", "beforeunload shouldn't have fired");
is(win.document.getElementById("location").value, name, "file name should match");
win.close();
next();
});
});
doc.getElementById(link).click();
ContentTask.spawn(gBrowser.selectedBrowser, link, link => {
content.document.getElementById(link).click();
});
}
testLink("link1", "test.txt",
@ -41,18 +43,22 @@ function test () {
testLocation.bind(null, "link7", "http://example.com/",
function () {
if (isHTTPS) {
gBrowser.removeCurrentTab();
finish();
} else {
// same test again with https:
isHTTPS = true;
content.location = "https://example.com:443/browser/browser/base/content/test/general/download_page.html";
gBrowser.loadURI("https://example.com:443/browser/browser/base/content/test/general/download_page.html");
}
})))))));
}, true);
}
content.location = "http://mochi.test:8888/browser/browser/base/content/test/general/download_page.html";
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
loadListener();
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(loadListener);
});
gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/general/download_page.html");
}
@ -97,15 +103,12 @@ TabOpenListener.prototype = {
gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
this.tab = event.originalTarget;
this.browser = this.tab.linkedBrowser;
gBrowser.addEventListener("pageshow", this, false);
} else if (event.type == "pageshow") {
if (event.target.location.href != this.url)
return;
gBrowser.removeEventListener("pageshow", this, false);
this.tab.addEventListener("TabClose", this, false);
var url = this.browser.contentDocument.location.href;
is(url, this.url, "Should have opened the correct tab");
this.opencallback(this.tab, this.browser.contentWindow);
BrowserTestUtils.browserLoaded(this.browser, false, this.url).then(() => {
this.tab.addEventListener("TabClose", this, false);
var url = this.browser.currentURI.spec;
is(url, this.url, "Should have opened the correct tab");
this.opencallback();
});
} else if (event.type == "TabClose") {
if (event.originalTarget != this.tab)
return;

View File

@ -45,10 +45,7 @@ function cleanUpAfterTests() {
//------------------------ Test 1 ------------------------------
function test1A() {
// Removing EventListener because we have to register a new
// one once the page is loaded with mixed content blocker disabled
gTestBrowser.removeEventListener("load", test1A, true);
gTestBrowser.addEventListener("load", test1B, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test1B);
assertMixedContentBlockingState(gTestBrowser, {activeLoaded: false, activeBlocked: true, passiveLoaded: false});
@ -65,21 +62,18 @@ function test1B() {
}
function test1C() {
gTestBrowser.removeEventListener("load", test1B, true);
var actual = content.document.getElementById('mctestdiv').innerHTML;
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 1C");
// The Script loaded after we disabled the page, now we are going to reload the
// page and see if our decision is persistent
gTestBrowser.addEventListener("load", test1D, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test1D);
var url = gHttpTestRoot1 + "file_bug902156_2.html";
gTestBrowser.contentWindow.location = url;
gTestBrowser.loadURI(url);
}
function test1D() {
gTestBrowser.removeEventListener("load", test1D, true);
// The Control Center button should appear but isMixedContentBlocked should be NOT true,
// because our decision of disabling the mixed content blocker is persistent.
assertMixedContentBlockingState(gTestBrowser, {activeLoaded: true, activeBlocked: false, passiveLoaded: false});
@ -94,16 +88,13 @@ function test1D() {
//------------------------ Test 2 ------------------------------
function test2() {
gTestBrowser.addEventListener("load", test2A, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test2A);
var url = gHttpTestRoot2 + "file_bug902156_2.html";
gTestBrowser.contentWindow.location = url;
gTestBrowser.loadURI(url);
}
function test2A() {
// Removing EventListener because we have to register a new
// one once the page is loaded with mixed content blocker disabled
gTestBrowser.removeEventListener("load", test2A, true);
gTestBrowser.addEventListener("load", test2B, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test2B);
assertMixedContentBlockingState(gTestBrowser, {activeLoaded: false, activeBlocked: true, passiveLoaded: false});
@ -120,13 +111,12 @@ function test2B() {
}
function test2C() {
gTestBrowser.removeEventListener("load", test2B, true);
var actual = content.document.getElementById('mctestdiv').innerHTML;
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 2C");
// The Script loaded after we disabled the page, now we are going to reload the
// page and see if our decision is persistent
gTestBrowser.addEventListener("load", test2D, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test2D);
// reload the page using the provided link in the html file
var mctestlink = content.document.getElementById("mctestlink");
@ -134,8 +124,6 @@ function test2C() {
}
function test2D() {
gTestBrowser.removeEventListener("load", test2D, true);
// The Control Center button should appear but isMixedContentBlocked should be NOT true,
// because our decision of disabling the mixed content blocker is persistent.
assertMixedContentBlockingState(gTestBrowser, {activeLoaded: true, activeBlocked: false, passiveLoaded: false});
@ -150,16 +138,12 @@ function test2D() {
//------------------------ Test 3 ------------------------------
function test3() {
gTestBrowser.addEventListener("load", test3A, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test3A);
var url = gHttpTestRoot1 + "file_bug902156_3.html";
gTestBrowser.contentWindow.location = url;
gTestBrowser.loadURI(url);
}
function test3A() {
// Removing EventListener because we have to register a new
// one once the page is loaded with mixed content blocker disabled
gTestBrowser.removeEventListener("load", test3A, true);
assertMixedContentBlockingState(gTestBrowser, {activeLoaded: false, activeBlocked: true, passiveLoaded: false});
// We are done with tests, clean up
@ -184,7 +168,7 @@ function test() {
newTab.linkedBrowser.stop()
// Starting Test Number 1:
gTestBrowser.addEventListener("load", test1A, true);
BrowserTestUtils.browserLoaded(gTestBrowser).then(test1A);
var url = gHttpTestRoot1 + "file_bug902156_1.html";
gTestBrowser.contentWindow.location = url;
gTestBrowser.loadURI(url);
}

View File

@ -3,32 +3,27 @@
// Tests find bar auto-close behavior
var newTab, iframe;
var newTab;
function test() {
add_task(function* findbar_test() {
waitForExplicitFinish();
newTab = gBrowser.addTab("about:blank");
newTab.linkedBrowser.addEventListener("DOMContentLoaded",
prepareTestFindBarStaysOpenOnSubdocumentLocationChange, false);
newTab.linkedBrowser.contentWindow.location = "http://example.com/browser/" +
"browser/base/content/test/general/test_bug628179.html";
}
function prepareTestFindBarStaysOpenOnSubdocumentLocationChange() {
newTab.linkedBrowser.removeEventListener("DOMContentLoaded",
prepareTestFindBarStaysOpenOnSubdocumentLocationChange, false);
let promise = ContentTask.spawn(newTab.linkedBrowser, null, function* () {
yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", false);
});
newTab.linkedBrowser.loadURI("http://example.com/browser/" +
"browser/base/content/test/general/test_bug628179.html");
yield promise;
gFindBar.open();
iframe = newTab.linkedBrowser.contentDocument.getElementById("iframe");
iframe.addEventListener("load",
testFindBarStaysOpenOnSubdocumentLocationChange, false);
iframe.src = "http://example.org/";
}
function testFindBarStaysOpenOnSubdocumentLocationChange() {
iframe.removeEventListener("load",
testFindBarStaysOpenOnSubdocumentLocationChange, false);
yield new ContentTask.spawn(newTab.linkedBrowser, null, function* () {
let iframe = content.document.getElementById("iframe");
let promise = ContentTaskUtils.waitForEvent(iframe, "load", false);
iframe.src = "http://example.org/";
yield promise;
});
ok(!gFindBar.hidden, "the Find bar isn't hidden after the location of a " +
"subdocument changes");
@ -36,5 +31,5 @@ function testFindBarStaysOpenOnSubdocumentLocationChange() {
gFindBar.close();
gBrowser.removeTab(newTab);
finish();
}
});

View File

@ -7,6 +7,12 @@
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
// Add a tab that will get removed and hidden
let testTab = gBrowser.addTab("about:blank", {skipAnimation: true});
is(gBrowser.visibleTabs.length, 2, "just added a tab, so 2 tabs");

View File

@ -3,17 +3,16 @@ function test() {
gPrefService.setBoolPref("dom.disable_open_during_load", false);
var browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function () {
browser.removeEventListener("load", arguments.callee, true);
BrowserTestUtils.browserLoaded(browser).then(() => {
if (gPrefService.prefHasUserValue("dom.disable_open_during_load"))
gPrefService.clearUserPref("dom.disable_open_during_load");
findPopup();
}, true);
});
content.location =
"data:text/html,<html><script>popup=open('about:blank','','width=300,height=200')</script>";
browser.loadURI(
"data:text/html,<html><script>popup=open('about:blank','','width=300,height=200')</script>"
);
}
function findPopup() {

View File

@ -2,7 +2,7 @@
* 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 test() {
add_task(function*() {
is(gBrowser.tabs.length, 1, "one tab is open initially");
// Add several new tabs in sequence, interrupted by selecting a
@ -10,26 +10,29 @@ function test() {
// returning a list of opened tabs for verifying the expected order.
// The new tab behaviour is documented in bug 465673
let tabs = [];
let promises = [];
function addTab(aURL, aReferrer) {
tabs.push(gBrowser.addTab(aURL, {referrerURI: aReferrer}));
let tab = gBrowser.addTab(aURL, {referrerURI: aReferrer});
tabs.push(tab);
return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
}
addTab("http://mochi.test:8888/#0");
yield addTab("http://mochi.test:8888/#0");
gBrowser.selectedTab = tabs[0];
addTab("http://mochi.test:8888/#1");
addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
addTab("http://mochi.test:8888/#3", gBrowser.currentURI);
yield addTab("http://mochi.test:8888/#1");
yield addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
yield addTab("http://mochi.test:8888/#3", gBrowser.currentURI);
gBrowser.selectedTab = tabs[tabs.length - 1];
gBrowser.selectedTab = tabs[0];
addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
yield addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
gBrowser.selectedTab = tabs[3];
addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
yield addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
gBrowser.removeTab(tabs.pop());
addTab("about:blank", gBrowser.currentURI);
yield addTab("about:blank", gBrowser.currentURI);
gBrowser.moveTabTo(gBrowser.selectedTab, 1);
addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
addTab();
addTab("http://mochi.test:8888/#7");
yield addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
yield addTab();
yield addTab("http://mochi.test:8888/#7");
function testPosition(tabNum, expectedPosition, msg) {
is(Array.indexOf(gBrowser.tabs, tabs[tabNum]), expectedPosition, msg);
@ -46,4 +49,4 @@ function test() {
testPosition(8, 9, "tab without referrer opens at the end");
tabs.forEach(gBrowser.removeTab, gBrowser);
}
});

View File

@ -18,5 +18,5 @@ function test() {
"gBrowser.selectTabAtIndex(-3) selects expected tab");
for (let i = 0; i < 9; i++)
gBrowser.removeCurrentTab();
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
}

View File

@ -41,22 +41,20 @@ function test_getBoolPref() {
function test_openNewTabWith() {
openNewTabWith("http://example.com/");
let tab = gBrowser.selectedTab = gBrowser.tabs[1];
tab.linkedBrowser.addEventListener("load", function onLoad(event) {
tab.linkedBrowser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
is(tab.linkedBrowser.currentURI.spec, "http://example.com/", "example.com loaded");
gBrowser.removeCurrentTab();
runNextTest();
}, true);
});
}
function test_openUILink() {
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
tab.linkedBrowser.addEventListener("load", function onLoad(event) {
tab.linkedBrowser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
is(tab.linkedBrowser.currentURI.spec, "http://example.org/", "example.org loaded");
gBrowser.removeCurrentTab();
runNextTest();
}, true);
});
openUILink("http://example.org/"); // defaults to "current"
}

View File

@ -2,7 +2,11 @@
* 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 test() {
add_task(function* () {
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
yield new Promise(resolve => TabView._initFrame(resolve));
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
@ -100,4 +104,5 @@ function test() {
if (tabViewWindow)
tabViewWindow.GroupItems.groupItems[0].close();
}
});

View File

@ -5,6 +5,12 @@
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
let tabOne = gBrowser.addTab("about:blank");
let tabTwo = gBrowser.addTab("http://mochi.test:8888/");
gBrowser.selectedTab = tabTwo;

View File

@ -5,6 +5,12 @@
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
is(gBrowser.visibleTabs.length, 1, "1 tab should be open");

View File

@ -2,7 +2,11 @@
* 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 test() {
add_task(function* test() {
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
yield new Promise(resolve => TabView._initFrame(resolve));
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
@ -51,4 +55,5 @@ function test() {
gBrowser.removeTab(testTab);
gBrowser.removeTab(pinned);
}
});

View File

@ -2,7 +2,11 @@
* 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 test() {
add_task(function* test() {
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
yield new Promise(resolve => TabView._initFrame(resolve));
gPrefService.setBoolPref("browser.ctrlTab.previews", true);
let [origTab] = gBrowser.visibleTabs;
@ -30,7 +34,7 @@ function test() {
if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
gPrefService.clearUserPref("browser.ctrlTab.previews");
}
});
function pressCtrlTab(aShiftKey) {
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });

View File

@ -416,7 +416,7 @@ function loadIntoTab(tab, url, callback) {
function ensureBrowserTabClosed(tab) {
let promise = ensureEventFired(gBrowser.tabContainer, "TabClose");
gBrowser.removeTab(tab);
gBrowser.removeTab(tab, {skipPermitUnload: true});
return promise;
}

View File

@ -6,7 +6,7 @@ function test() {
/** Test for Bug 522545 **/
waitForExplicitFinish();
requestLongerTimeout(2);
requestLongerTimeout(3);
// This tests the following use case:
// User opens a new tab which gets focus. The user types something into the
@ -159,12 +159,10 @@ function test() {
ok(hasUTV, "At least one tab has a userTypedValue with userTypedClear with no loaded URL");
gBrowser.addEventListener("load", firstLoad, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(firstLoad);
}
function firstLoad() {
gBrowser.removeEventListener("load", firstLoad, true);
let state = JSON.parse(ss.getBrowserState());
let hasSH = state.windows[0].tabs.some(function(aTab) {
return !("userTypedValue" in aTab) && aTab.entries[0].url;

View File

@ -6,6 +6,10 @@ add_task(function* () {
/** Bug 607016 - If a tab is never restored, attributes (eg. hidden) aren't updated correctly **/
ignoreAllUncaughtExceptions();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
yield new Promise(resolve => TabView._initFrame(resolve));
// Set the pref to true so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);

View File

@ -7,6 +7,12 @@
function test() {
waitForExplicitFinish();
// Ensure TabView has been initialized already. Otherwise it could
// activate at an unexpected time and show/hide tabs.
TabView._initFrame(runTest);
}
function runTest() {
// We speed up the interval between session saves to ensure that the test
// runs quickly.
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);

View File

@ -39,11 +39,18 @@ var RemotePrompt = {
let tabPrompt = window.gBrowser.getTabModalPromptBox(browser)
let callbackInvoked = false;
let newPrompt;
let needRemove = false;
let promptId = args._remoteId;
function onPromptClose(forceCleanup) {
// It's possible that we removed the prompt during the
// appendPrompt call below. In that case, newPrompt will be
// undefined. We set the needRemove flag to remember to remove
// it right after we've finished adding it.
if (newPrompt)
tabPrompt.removePrompt(newPrompt);
else
needRemove = true;
PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser);
browser.messageManager.sendAsyncMessage("Prompt:Close", args);
@ -74,6 +81,10 @@ var RemotePrompt = {
newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
if (needRemove) {
tabPrompt.removePrompt(newPrompt);
}
// TODO since we don't actually open a window, need to check if
// there's other stuff in nsWindowWatcher::OpenWindowInternal
// that we might need to do here as well.

View File

@ -9,12 +9,10 @@ function test()
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(onLoad);
}
function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
function onLoad() {
target = TargetFactory.forTab(gBrowser.selectedTab);
is(target.tab, gBrowser.selectedTab, "Target linked to the right tab.");

View File

@ -61,6 +61,11 @@ viewsourceindebugger=View source in Debugger → %S
# that represents a row broken down by allocation stack when no stack was available.
tree-item.nostack=(no stack available)
# LOCALIZATION NOTE (tree-item.nofilename): The label describing the row in the
# heap tree that represents a row broken down by filename when no filename was
# available.
tree-item.nofilename=(no filename available)
# LOCALIZATION NOTE (tree-item.root): The label describing the row in the heap tree
# that represents the root of the tree when inverted.
tree-item.root=(root)

View File

@ -59,9 +59,22 @@ const TreeItem = module.exports = createClass({
},
toLabel(name, toolbox) {
return isSavedFrame(name) ? FrameView({ frame: name, toolbox }) :
name === "noStack" ? L10N.getStr("tree-item.nostack") :
name === null ? L10N.getStr("tree-item.root") :
String(name);
if (isSavedFrame(name)) {
return FrameView({ frame: name, toolbox });
}
if (name === null) {
return L10N.getStr("tree-item.root");
}
if (name === "noStack") {
return L10N.getStr("tree-item.nostack");
}
if (name === "noFilename") {
return L10N.getStr("tree-item.nofilename");
}
return String(name);
},
});

View File

@ -56,7 +56,11 @@ const breakdowns = exports.breakdowns = {
by: "coarseType",
objects: OBJECT_CLASS,
strings: COUNT,
scripts: INTERNAL_TYPE,
scripts: {
by: "filename",
then: INTERNAL_TYPE,
noFilename: INTERNAL_TYPE
},
other: INTERNAL_TYPE,
}
},

View File

@ -107,7 +107,8 @@ function removeTab(aTab, aWindow) {
let targetWindow = aWindow || window;
let targetBrowser = targetWindow.gBrowser;
targetBrowser.removeTab(aTab);
// browser_net_pane-toggle.js relies on synchronous removeTab behavior.
targetBrowser.removeTab(aTab, {skipPermitUnload: true});
}
function waitForNavigation(aTarget) {

View File

@ -131,26 +131,22 @@ function* testTheBasics(widget) {
*/
function checkLinkClick(link) {
function loadListener(e) {
let tab = e.target;
function loadListener(tab) {
var browser = getBrowser().getBrowserForTab(tab);
var uri = browser.currentURI.spec;
// this is horrible, and it's because when we open a new tab
// "about:blank: is first loaded into it, before the actual
// document we want to load.
if (uri != "about:blank") {
info("New browser tab has loaded");
tab.removeEventListener("load", loadListener);
gBrowser.removeTab(tab);
info("Resolve promise with new tab URI");
deferred.resolve(uri);
}
info("New browser tab has loaded");
gBrowser.removeTab(tab);
info("Resolve promise with new tab URI");
deferred.resolve(uri);
}
function newTabListener(e) {
gBrowser.tabContainer.removeEventListener("TabOpen", newTabListener);
var tab = e.target;
tab.addEventListener("load", loadListener, false);
BrowserTestUtils.browserLoaded(tab.linkedBrowser, false,
url => { return url != "about:blank"; })
.then(url => loadListener(tab));
}
let deferred = promise.defer();

View File

@ -27,17 +27,16 @@ function addTab(aURL, aCallback)
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = aURL;
let tab = gBrowser.selectedTab;
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
aCallback(browser, tab, browser.contentDocument);
}
let url = encodeURI(aURL);
browser.addEventListener("load", onTabLoad, true);
BrowserTestUtils.browserLoaded(browser, false, url).then(() => {
aCallback(browser, tab, browser.contentDocument);
});
browser.loadURI(url);
}
function promiseTab(aURL) {

View File

@ -123,12 +123,11 @@ var doc = null;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
doc = content.document;
runTests();
}, true);
content.location = TEST_URI;
});
gBrowser.loadURI(TEST_URI);
}
function runTests() {

View File

@ -58,13 +58,11 @@ const TEST_URI = "data:text/html;charset=UTF-8," + encodeURIComponent(
var doc = null;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
gBrowser.selectedTab = gBrowser.addTab(TEST_URI);
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
doc = content.document;
runTests();
}, true);
content.location = TEST_URI;
});
}
function runTests() {

View File

@ -28,8 +28,8 @@ function runCodeMirrorTest(browser) {
'function check() { ' +
' var doc = content.document; var out = doc.getElementById("status"); ' +
' if (!out || !out.classList.contains("done")) { return setTimeout(check, 100); }' +
' sendSyncMessage("done", { failed: content.wrappedJSObject.failed });' +
' sendAsyncMessage("done", { failed: content.wrappedJSObject.failed });' +
'}' +
'check();'
, true);
}
}

View File

@ -97,11 +97,19 @@ EDGES.allocationStack = function (breakdown, report) {
edge: key,
referent: value,
breakdown: key === "noStack" ? breakdown.noStack : breakdown.then
})
});
});
return edges;
};
EDGES.filename = function (breakdown, report) {
return Object.keys(report).map(key => ({
edge: key,
referent: report[key],
breakdown: key === "noFilename" ? breakdown.noFilename : breakdown.then
}));
};
/**
* Get the set of outgoing edges from `report` as specified by the given
* breakdown.

View File

@ -49,6 +49,8 @@ struct NodeOneofInstance {
::google::protobuf::uint64 typenameref_;
const ::std::string* jsobjectclassname_;
::google::protobuf::uint64 jsobjectclassnameref_;
const ::std::string* scriptfilename_;
::google::protobuf::uint64 scriptfilenameref_;
}* Node_default_oneof_instance_ = NULL;
const ::google::protobuf::Descriptor* Edge_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
@ -130,7 +132,7 @@ void protobuf_AssignDesc_CoreDump_2eproto() {
::google::protobuf::MessageFactory::generated_factory(),
sizeof(StackFrame_Data));
Node_descriptor_ = file->message_type(2);
static const int Node_offsets_[11] = {
static const int Node_offsets_[14] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Node, id_),
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, typename__),
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, typenameref_),
@ -140,8 +142,11 @@ void protobuf_AssignDesc_CoreDump_2eproto() {
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, jsobjectclassname_),
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, jsobjectclassnameref_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Node, coarsetype_),
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, scriptfilename_),
PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Node_default_oneof_instance_, scriptfilenameref_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Node, TypeNameOrRef_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Node, JSObjectClassNameOrRef_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Node, ScriptFilenameOrRef_),
};
Node_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
@ -237,17 +242,19 @@ void protobuf_AddDesc_CoreDump_2eproto() {
"nDisplayName\030\007 \001(\014H\001\022 \n\026functionDisplayN"
"ameRef\030\010 \001(\004H\001\022\020\n\010isSystem\030\t \001(\010\022\024\n\014isSe"
"lfHosted\030\n \001(\010B\r\n\013SourceOrRefB\032\n\030Functio"
"nDisplayNameOrRefB\020\n\016StackFrameType\"\272\002\n\004"
"nDisplayNameOrRefB\020\n\016StackFrameType\"\210\003\n\004"
"Node\022\n\n\002id\030\001 \001(\004\022\022\n\010typeName\030\002 \001(\014H\000\022\025\n\013"
"typeNameRef\030\003 \001(\004H\000\022\014\n\004size\030\004 \001(\004\022.\n\005edg"
"es\030\005 \003(\0132\037.mozilla.devtools.protobuf.Edg"
"e\022>\n\017allocationStack\030\006 \001(\0132%.mozilla.dev"
"tools.protobuf.StackFrame\022\033\n\021jsObjectCla"
"ssName\030\007 \001(\014H\001\022\036\n\024jsObjectClassNameRef\030\010"
" \001(\004H\001\022\025\n\ncoarseType\030\t \001(\r:\0010B\017\n\rTypeNam"
"eOrRefB\030\n\026JSObjectClassNameOrRef\"L\n\004Edge"
"\022\020\n\010referent\030\001 \001(\004\022\016\n\004name\030\002 \001(\014H\000\022\021\n\007na"
"meRef\030\003 \001(\004H\000B\017\n\rEdgeNameOrRef", 870);
" \001(\004H\001\022\025\n\ncoarseType\030\t \001(\r:\0010\022\030\n\016scriptF"
"ilename\030\n \001(\014H\002\022\033\n\021scriptFilenameRef\030\013 \001"
"(\004H\002B\017\n\rTypeNameOrRefB\030\n\026JSObjectClassNa"
"meOrRefB\025\n\023ScriptFilenameOrRef\"L\n\004Edge\022\020"
"\n\010referent\030\001 \001(\004\022\016\n\004name\030\002 \001(\014H\000\022\021\n\007name"
"Ref\030\003 \001(\004H\000B\017\n\rEdgeNameOrRef", 948);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"CoreDump.proto", &protobuf_RegisterTypes);
Metadata::default_instance_ = new Metadata();
@ -1462,6 +1469,8 @@ const int Node::kAllocationStackFieldNumber;
const int Node::kJsObjectClassNameFieldNumber;
const int Node::kJsObjectClassNameRefFieldNumber;
const int Node::kCoarseTypeFieldNumber;
const int Node::kScriptFilenameFieldNumber;
const int Node::kScriptFilenameRefFieldNumber;
#endif // !_MSC_VER
Node::Node()
@ -1476,6 +1485,8 @@ void Node::InitAsDefaultInstance() {
allocationstack_ = const_cast< ::mozilla::devtools::protobuf::StackFrame*>(&::mozilla::devtools::protobuf::StackFrame::default_instance());
Node_default_oneof_instance_->jsobjectclassname_ = &::google::protobuf::internal::GetEmptyStringAlreadyInited();
Node_default_oneof_instance_->jsobjectclassnameref_ = GOOGLE_ULONGLONG(0);
Node_default_oneof_instance_->scriptfilename_ = &::google::protobuf::internal::GetEmptyStringAlreadyInited();
Node_default_oneof_instance_->scriptfilenameref_ = GOOGLE_ULONGLONG(0);
}
Node::Node(const Node& from)
@ -1495,6 +1506,7 @@ void Node::SharedCtor() {
::memset(_has_bits_, 0, sizeof(_has_bits_));
clear_has_TypeNameOrRef();
clear_has_JSObjectClassNameOrRef();
clear_has_ScriptFilenameOrRef();
}
Node::~Node() {
@ -1509,6 +1521,9 @@ void Node::SharedDtor() {
if (has_JSObjectClassNameOrRef()) {
clear_JSObjectClassNameOrRef();
}
if (has_ScriptFilenameOrRef()) {
clear_ScriptFilenameOrRef();
}
if (this != default_instance_) {
delete allocationstack_;
}
@ -1569,6 +1584,23 @@ void Node::clear_JSObjectClassNameOrRef() {
_oneof_case_[1] = JSOBJECTCLASSNAMEORREF_NOT_SET;
}
void Node::clear_ScriptFilenameOrRef() {
switch(ScriptFilenameOrRef_case()) {
case kScriptFilename: {
delete ScriptFilenameOrRef_.scriptfilename_;
break;
}
case kScriptFilenameRef: {
// No need to clear
break;
}
case SCRIPTFILENAMEORREF_NOT_SET: {
break;
}
}
_oneof_case_[2] = SCRIPTFILENAMEORREF_NOT_SET;
}
void Node::Clear() {
#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
@ -1595,6 +1627,7 @@ void Node::Clear() {
edges_.Clear();
clear_TypeNameOrRef();
clear_JSObjectClassNameOrRef();
clear_ScriptFilenameOrRef();
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
}
@ -1734,6 +1767,35 @@ bool Node::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(82)) goto parse_scriptFilename;
break;
}
// optional bytes scriptFilename = 10;
case 10: {
if (tag == 82) {
parse_scriptFilename:
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
input, this->mutable_scriptfilename()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(88)) goto parse_scriptFilenameRef;
break;
}
// optional uint64 scriptFilenameRef = 11;
case 11: {
if (tag == 88) {
parse_scriptFilenameRef:
clear_ScriptFilenameOrRef();
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
input, &ScriptFilenameOrRef_.scriptfilenameref_)));
set_has_scriptfilenameref();
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -1812,6 +1874,17 @@ void Node::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteUInt32(9, this->coarsetype(), output);
}
// optional bytes scriptFilename = 10;
if (has_scriptfilename()) {
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
10, this->scriptfilename(), output);
}
// optional uint64 scriptFilenameRef = 11;
if (has_scriptfilenameref()) {
::google::protobuf::internal::WireFormatLite::WriteUInt64(11, this->scriptfilenameref(), output);
}
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@ -1875,6 +1948,18 @@ void Node::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(9, this->coarsetype(), target);
}
// optional bytes scriptFilename = 10;
if (has_scriptfilename()) {
target =
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
10, this->scriptfilename(), target);
}
// optional uint64 scriptFilenameRef = 11;
if (has_scriptfilenameref()) {
target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(11, this->scriptfilenameref(), target);
}
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@ -1964,6 +2049,25 @@ int Node::ByteSize() const {
break;
}
}
switch (ScriptFilenameOrRef_case()) {
// optional bytes scriptFilename = 10;
case kScriptFilename: {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::BytesSize(
this->scriptfilename());
break;
}
// optional uint64 scriptFilenameRef = 11;
case kScriptFilenameRef: {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::UInt64Size(
this->scriptfilenameref());
break;
}
case SCRIPTFILENAMEORREF_NOT_SET: {
break;
}
}
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@ -2016,6 +2120,19 @@ void Node::MergeFrom(const Node& from) {
break;
}
}
switch (from.ScriptFilenameOrRef_case()) {
case kScriptFilename: {
set_scriptfilename(from.scriptfilename());
break;
}
case kScriptFilenameRef: {
set_scriptfilenameref(from.scriptfilenameref());
break;
}
case SCRIPTFILENAMEORREF_NOT_SET: {
break;
}
}
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_id()) {
set_id(from.id());
@ -2063,6 +2180,8 @@ void Node::Swap(Node* other) {
std::swap(_oneof_case_[0], other->_oneof_case_[0]);
std::swap(JSObjectClassNameOrRef_, other->JSObjectClassNameOrRef_);
std::swap(_oneof_case_[1], other->_oneof_case_[1]);
std::swap(ScriptFilenameOrRef_, other->ScriptFilenameOrRef_);
std::swap(_oneof_case_[2], other->_oneof_case_[2]);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);

View File

@ -468,6 +468,12 @@ class Node : public ::google::protobuf::Message {
JSOBJECTCLASSNAMEORREF_NOT_SET = 0,
};
enum ScriptFilenameOrRefCase {
kScriptFilename = 10,
kScriptFilenameRef = 11,
SCRIPTFILENAMEORREF_NOT_SET = 0,
};
void Swap(Node* other);
// implements Message ----------------------------------------------
@ -578,8 +584,28 @@ class Node : public ::google::protobuf::Message {
inline ::google::protobuf::uint32 coarsetype() const;
inline void set_coarsetype(::google::protobuf::uint32 value);
// optional bytes scriptFilename = 10;
inline bool has_scriptfilename() const;
inline void clear_scriptfilename();
static const int kScriptFilenameFieldNumber = 10;
inline const ::std::string& scriptfilename() const;
inline void set_scriptfilename(const ::std::string& value);
inline void set_scriptfilename(const char* value);
inline void set_scriptfilename(const void* value, size_t size);
inline ::std::string* mutable_scriptfilename();
inline ::std::string* release_scriptfilename();
inline void set_allocated_scriptfilename(::std::string* scriptfilename);
// optional uint64 scriptFilenameRef = 11;
inline bool has_scriptfilenameref() const;
inline void clear_scriptfilenameref();
static const int kScriptFilenameRefFieldNumber = 11;
inline ::google::protobuf::uint64 scriptfilenameref() const;
inline void set_scriptfilenameref(::google::protobuf::uint64 value);
inline TypeNameOrRefCase TypeNameOrRef_case() const;
inline JSObjectClassNameOrRefCase JSObjectClassNameOrRef_case() const;
inline ScriptFilenameOrRefCase ScriptFilenameOrRef_case() const;
// @@protoc_insertion_point(class_scope:mozilla.devtools.protobuf.Node)
private:
inline void set_has_id();
@ -594,6 +620,8 @@ class Node : public ::google::protobuf::Message {
inline void set_has_jsobjectclassnameref();
inline void set_has_coarsetype();
inline void clear_has_coarsetype();
inline void set_has_scriptfilename();
inline void set_has_scriptfilenameref();
inline bool has_TypeNameOrRef();
void clear_TypeNameOrRef();
@ -603,6 +631,10 @@ class Node : public ::google::protobuf::Message {
void clear_JSObjectClassNameOrRef();
inline void clear_has_JSObjectClassNameOrRef();
inline bool has_ScriptFilenameOrRef();
void clear_ScriptFilenameOrRef();
inline void clear_has_ScriptFilenameOrRef();
::google::protobuf::UnknownFieldSet _unknown_fields_;
::google::protobuf::uint32 _has_bits_[1];
@ -620,7 +652,11 @@ class Node : public ::google::protobuf::Message {
::std::string* jsobjectclassname_;
::google::protobuf::uint64 jsobjectclassnameref_;
} JSObjectClassNameOrRef_;
::google::protobuf::uint32 _oneof_case_[2];
union ScriptFilenameOrRefUnion {
::std::string* scriptfilename_;
::google::protobuf::uint64 scriptfilenameref_;
} ScriptFilenameOrRef_;
::google::protobuf::uint32 _oneof_case_[3];
friend void protobuf_AddDesc_CoreDump_2eproto();
friend void protobuf_AssignDesc_CoreDump_2eproto();
@ -1578,6 +1614,103 @@ inline void Node::set_coarsetype(::google::protobuf::uint32 value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.coarseType)
}
// optional bytes scriptFilename = 10;
inline bool Node::has_scriptfilename() const {
return ScriptFilenameOrRef_case() == kScriptFilename;
}
inline void Node::set_has_scriptfilename() {
_oneof_case_[2] = kScriptFilename;
}
inline void Node::clear_scriptfilename() {
if (has_scriptfilename()) {
delete ScriptFilenameOrRef_.scriptfilename_;
clear_has_ScriptFilenameOrRef();
}
}
inline const ::std::string& Node::scriptfilename() const {
if (has_scriptfilename()) {
return *ScriptFilenameOrRef_.scriptfilename_;
}
return ::google::protobuf::internal::GetEmptyStringAlreadyInited();
}
inline void Node::set_scriptfilename(const ::std::string& value) {
if (!has_scriptfilename()) {
clear_ScriptFilenameOrRef();
set_has_scriptfilename();
ScriptFilenameOrRef_.scriptfilename_ = new ::std::string;
}
ScriptFilenameOrRef_.scriptfilename_->assign(value);
}
inline void Node::set_scriptfilename(const char* value) {
if (!has_scriptfilename()) {
clear_ScriptFilenameOrRef();
set_has_scriptfilename();
ScriptFilenameOrRef_.scriptfilename_ = new ::std::string;
}
ScriptFilenameOrRef_.scriptfilename_->assign(value);
}
inline void Node::set_scriptfilename(const void* value, size_t size) {
if (!has_scriptfilename()) {
clear_ScriptFilenameOrRef();
set_has_scriptfilename();
ScriptFilenameOrRef_.scriptfilename_ = new ::std::string;
}
ScriptFilenameOrRef_.scriptfilename_->assign(
reinterpret_cast<const char*>(value), size);
}
inline ::std::string* Node::mutable_scriptfilename() {
if (!has_scriptfilename()) {
clear_ScriptFilenameOrRef();
set_has_scriptfilename();
ScriptFilenameOrRef_.scriptfilename_ = new ::std::string;
}
return ScriptFilenameOrRef_.scriptfilename_;
}
inline ::std::string* Node::release_scriptfilename() {
if (has_scriptfilename()) {
clear_has_ScriptFilenameOrRef();
::std::string* temp = ScriptFilenameOrRef_.scriptfilename_;
ScriptFilenameOrRef_.scriptfilename_ = NULL;
return temp;
} else {
return NULL;
}
}
inline void Node::set_allocated_scriptfilename(::std::string* scriptfilename) {
clear_ScriptFilenameOrRef();
if (scriptfilename) {
set_has_scriptfilename();
ScriptFilenameOrRef_.scriptfilename_ = scriptfilename;
}
}
// optional uint64 scriptFilenameRef = 11;
inline bool Node::has_scriptfilenameref() const {
return ScriptFilenameOrRef_case() == kScriptFilenameRef;
}
inline void Node::set_has_scriptfilenameref() {
_oneof_case_[2] = kScriptFilenameRef;
}
inline void Node::clear_scriptfilenameref() {
if (has_scriptfilenameref()) {
ScriptFilenameOrRef_.scriptfilenameref_ = GOOGLE_ULONGLONG(0);
clear_has_ScriptFilenameOrRef();
}
}
inline ::google::protobuf::uint64 Node::scriptfilenameref() const {
if (has_scriptfilenameref()) {
return ScriptFilenameOrRef_.scriptfilenameref_;
}
return GOOGLE_ULONGLONG(0);
}
inline void Node::set_scriptfilenameref(::google::protobuf::uint64 value) {
if (!has_scriptfilenameref()) {
clear_ScriptFilenameOrRef();
set_has_scriptfilenameref();
}
ScriptFilenameOrRef_.scriptfilenameref_ = value;
}
inline bool Node::has_TypeNameOrRef() {
return TypeNameOrRef_case() != TYPENAMEORREF_NOT_SET;
}
@ -1590,12 +1723,21 @@ inline bool Node::has_JSObjectClassNameOrRef() {
inline void Node::clear_has_JSObjectClassNameOrRef() {
_oneof_case_[1] = JSOBJECTCLASSNAMEORREF_NOT_SET;
}
inline bool Node::has_ScriptFilenameOrRef() {
return ScriptFilenameOrRef_case() != SCRIPTFILENAMEORREF_NOT_SET;
}
inline void Node::clear_has_ScriptFilenameOrRef() {
_oneof_case_[2] = SCRIPTFILENAMEORREF_NOT_SET;
}
inline Node::TypeNameOrRefCase Node::TypeNameOrRef_case() const {
return Node::TypeNameOrRefCase(_oneof_case_[0]);
}
inline Node::JSObjectClassNameOrRefCase Node::JSObjectClassNameOrRef_case() const {
return Node::JSObjectClassNameOrRefCase(_oneof_case_[1]);
}
inline Node::ScriptFilenameOrRefCase Node::ScriptFilenameOrRef_case() const {
return Node::ScriptFilenameOrRefCase(_oneof_case_[2]);
}
// -------------------------------------------------------------------
// Edge

View File

@ -123,6 +123,12 @@ message Node {
// JS::ubi::CoarseType. Defaults to Other.
optional uint32 coarseType = 9 [default = 0];
// De-duplicated one-byte string.
oneof ScriptFilenameOrRef {
bytes scriptFilename = 10;
uint64 scriptFilenameRef = 11;
}
}
// A serialized edge from the heap graph.

View File

@ -67,6 +67,8 @@ struct DeserializedNode {
Maybe<StackFrameId> allocationStack;
// A borrowed reference to a string owned by this node's owning HeapSnapshot.
const char* jsObjectClassName;
// A borrowed reference to a string owned by this node's owning HeapSnapshot.
const char* scriptFilename;
// A weak pointer to this node's owning `HeapSnapshot`. Safe without
// AddRef'ing because this node's lifetime is equal to that of its owner.
HeapSnapshot* owner;
@ -78,6 +80,7 @@ struct DeserializedNode {
EdgeVector&& edges,
Maybe<StackFrameId> allocationStack,
const char* className,
const char* filename,
HeapSnapshot& owner)
: id(id)
, coarseType(coarseType)
@ -86,6 +89,7 @@ struct DeserializedNode {
, edges(Move(edges))
, allocationStack(allocationStack)
, jsObjectClassName(className)
, scriptFilename(filename)
, owner(&owner)
{ }
virtual ~DeserializedNode() { }
@ -98,6 +102,7 @@ struct DeserializedNode {
, edges(Move(rhs.edges))
, allocationStack(rhs.allocationStack)
, jsObjectClassName(rhs.jsObjectClassName)
, scriptFilename(rhs.scriptFilename)
, owner(rhs.owner)
{ }
@ -125,6 +130,7 @@ protected:
, edges()
, allocationStack(Nothing())
, jsObjectClassName(nullptr)
, scriptFilename(nullptr)
, owner(nullptr)
{ }
@ -260,6 +266,7 @@ public:
const char16_t* typeName() const override;
Node::Size size(mozilla::MallocSizeOf mallocSizeof) const override;
const char* jsObjectClassName() const override { return get().jsObjectClassName; }
const char* scriptFilename() const final { return get().scriptFilename; }
bool hasAllocationStack() const override { return get().allocationStack.isSome(); }
StackFrame allocationStack() const override;

View File

@ -276,10 +276,19 @@ HeapSnapshot::saveNode(const protobuf::Node& node)
return false;
}
const char* scriptFilename = nullptr;
if (node.ScriptFilenameOrRef_case() != protobuf::Node::SCRIPTFILENAMEORREF_NOT_SET) {
Maybe<StringOrRef> scriptFilenameOrRef = GET_STRING_OR_REF(node, scriptfilename);
scriptFilename = getOrInternString<char>(internedOneByteStrings, scriptFilenameOrRef);
if (NS_WARN_IF(!scriptFilename))
return false;
}
if (NS_WARN_IF(!nodes.putNew(id, DeserializedNode(id, coarseType, typeName,
size, Move(edges),
allocationStack,
jsObjectClassName, *this))))
jsObjectClassName,
scriptFilename, *this))))
{
return false;
};
@ -1079,6 +1088,15 @@ public:
}
}
if (auto scriptFilename = ubiNode.scriptFilename()) {
if (NS_WARN_IF(!attachOneByteString(scriptFilename,
[&] (std::string* name) { protobufNode.set_allocated_scriptfilename(name); },
[&] (uint64_t ref) { protobufNode.set_scriptfilenameref(ref); })))
{
return false;
}
}
return writeMessage(protobufNode);
}
};

View File

@ -39,12 +39,14 @@ size_t fakeMallocSizeOf(const void*) {
DEF_TEST(DeserializedNodeUbiNodes, {
const char16_t* typeName = MOZ_UTF16("TestTypeName");
const char* className = "MyObjectClassName";
const char* filename = "my-cool-filename.js";
NodeId id = uint64_t(1) << 33;
uint64_t size = uint64_t(1) << 60;
MockDeserializedNode mocked(id, typeName, size);
mocked.coarseType = JS::ubi::CoarseType::Script;
mocked.jsObjectClassName = className;
mocked.scriptFilename = filename;
DeserializedNode& deserialized = mocked;
JS::ubi::Node ubi(&deserialized);
@ -57,6 +59,7 @@ DEF_TEST(DeserializedNodeUbiNodes, {
EXPECT_EQ(id, ubi.identifier());
EXPECT_FALSE(ubi.isLive());
EXPECT_EQ(ubi.jsObjectClassName(), className);
EXPECT_EQ(ubi.scriptFilename(), filename);
// Test the ubi::Node's edges.

View File

@ -0,0 +1,133 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test inverting CensusTreeNode with a non-allocation stack breakdown.
*/
function run_test() {
const BREAKDOWN = {
by: "filename",
then: {
by: "internalType",
then: { by: "count", count: true, bytes: true }
},
noFilename: {
by: "internalType",
then: { by: "count", count: true, bytes: true }
},
};
const REPORT = {
"http://example.com/app.js": {
JSScript: { count: 10, bytes: 100 }
},
"http://example.com/ads.js": {
"js::LazyScript": { count: 20, bytes: 200 }
},
"http://example.com/trackers.js": {
JSScript: { count: 30, bytes: 300 }
},
noFilename: {
"js::jit::JitCode": { count: 40, bytes: 400 }
}
};
const EXPECTED = {
name: null,
bytes: 0,
totalBytes: 1000,
count: 0,
totalCount: 100,
children: [
{
name: "noFilename",
bytes: 0,
totalBytes: 400,
count: 0,
totalCount: 40,
children: [
{
name: "js::jit::JitCode",
bytes: 400,
totalBytes: 400,
count: 40,
totalCount: 40,
children: undefined,
id: 9,
parent: 8
}
],
id: 8,
parent: 1
},
{
name: "http://example.com/trackers.js",
bytes: 0,
totalBytes: 300,
count: 0,
totalCount: 30,
children: [
{
name: "JSScript",
bytes: 300,
totalBytes: 300,
count: 30,
totalCount: 30,
children: undefined,
id: 7,
parent: 6
}
],
id: 6,
parent: 1
},
{
name: "http://example.com/ads.js",
bytes: 0,
totalBytes: 200,
count: 0,
totalCount: 20,
children: [
{
name: "js::LazyScript",
bytes: 200,
totalBytes: 200,
count: 20,
totalCount: 20,
children: undefined,
id: 5,
parent: 4
}
],
id: 4,
parent: 1
},
{
name: "http://example.com/app.js",
bytes: 0,
totalBytes: 100,
count: 0,
totalCount: 10,
children: [
{
name: "JSScript",
bytes: 100,
totalBytes: 100,
count: 10,
totalCount: 10,
children: undefined,
id: 3,
parent: 2
}
],
id: 2,
parent: 1
}
],
id: 1,
parent: undefined,
};
compareCensusViewData(BREAKDOWN, REPORT, EXPECTED);
}

View File

@ -26,6 +26,7 @@ support-files =
[test_census-tree-node-05.js]
[test_census-tree-node-06.js]
[test_census-tree-node-07.js]
[test_census-tree-node-08.js]
[test_HeapAnalyses_getCreationTime_01.js]
[test_HeapAnalyses_readHeapSnapshot_01.js]
[test_HeapAnalyses_takeCensusDiff_01.js]

View File

@ -1,31 +1,37 @@
/* Make sure that netError won't allow HTML injection through badcert parameters. See bug 441169. */
var newBrowser
// An edited version of the standard neterror url which attempts to
// insert a <span id="test_span"> tag into the text. We will navigate to this page
// and ensure that the span tag is not parsed as HTML.
var chromeURL = "about:neterror?e=nssBadCert&u=https%3A//test.kuix.de/&c=UTF-8&d=This%20sentence%20should%20not%20be%20parsed%20to%20include%20a%20%3Cspan%20id=%22test_span%22%3Enamed%3C/span%3E%20span%20tag.%0A%0AThe%20certificate%20is%20only%20valid%20for%20%3Ca%20id=%22cert_domain_link%22%20title=%22kuix.de%22%3Ekuix.de%3C/a%3E%0A%0A(Error%20code%3A%20ssl_error_bad_cert_domain)";
function task() {
let resolve;
let promise = new Promise(r => { resolve = r; });
addEventListener("DOMContentLoaded", checkPage, false);
function checkPage(event) {
if (event.target != content.document) {
return;
}
removeEventListener("DOMContentLoaded", checkPage, false);
is(content.document.getElementById("test_span"), null, "Error message should not be parsed as HTML, and hence shouldn't include the 'test_span' element.");
resolve();
}
var chromeURL = "about:neterror?e=nssBadCert&u=https%3A//test.kuix.de/&c=UTF-8&d=This%20sentence%20should%20not%20be%20parsed%20to%20include%20a%20%3Cspan%20id=%22test_span%22%3Enamed%3C/span%3E%20span%20tag.%0A%0AThe%20certificate%20is%20only%20valid%20for%20%3Ca%20id=%22cert_domain_link%22%20title=%22kuix.de%22%3Ekuix.de%3C/a%3E%0A%0A(Error%20code%3A%20ssl_error_bad_cert_domain)";
content.location = chromeURL;
return promise;
}
function test() {
waitForExplicitFinish();
var newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
newBrowser = gBrowser.getBrowserForTab(newTab);
window.addEventListener("DOMContentLoaded", checkPage, false);
newBrowser.contentWindow.location = chromeURL;
}
function checkPage(event) {
if (event.target != gBrowser.selectedBrowser.contentDocument) {
return;
}
window.removeEventListener("DOMContentLoaded", checkPage, false);
is(newBrowser.contentDocument.getElementById("test_span"), null, "Error message should not be parsed as HTML, and hence shouldn't include the 'test_span' element.");
gBrowser.removeCurrentTab();
finish();
ContentTask.spawn(newBrowser, null, task).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}

View File

@ -14,9 +14,7 @@ function test() {
let tab = gBrowser.addTab('http://example.com');
let tabBrowser = tab.linkedBrowser;
tabBrowser.addEventListener('load', function(aEvent) {
tabBrowser.removeEventListener('load', arguments.callee, true);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
let cw = tabBrowser.contentWindow;
let oldTitle = cw.document.title;
ok(oldTitle, 'Content window should initially have a title.');
@ -31,5 +29,5 @@ function test() {
gBrowser.removeTab(tab);
finish();
}, true);
});
}

View File

@ -10,6 +10,7 @@ SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunlo
var loadExpected = TEST_PAGE;
var testTab;
var testsLength;
var loadStarted = false;
var tabStateListener = {
@ -40,6 +41,10 @@ function onTabLoaded(event) {
return;
}
if (!testsLength) {
testsLength = testTab.linkedBrowser.contentWindow.wrappedJSObject.testFns.length;
}
is(loadedPage, loadExpected, "Loaded the expected page");
if (contentWindow) {
is(contentWindow.document, event.target, "Same doc");
@ -102,47 +107,9 @@ function onTabModalDialogLoaded(node) {
// Listen for the dialog being created
Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
var testFns = [
function(e) {
e.target.location.href = 'otherpage-href-set.html';
return "stop";
},
function(e) {
e.target.location.reload();
return "stop";
},
function(e) {
e.target.location.replace('otherpage-location-replaced.html');
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = "otherpage.html";
e.target.body.appendChild(link);
link.click();
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = "otherpage.html";
link.setAttribute("target", "_blank");
e.target.body.appendChild(link);
link.click();
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = e.target.location.href;
e.target.body.appendChild(link);
link.setAttribute("target", "somearbitrarywindow");
link.click();
return "stop";
},
];
function runNextTest() {
currentTest++;
if (currentTest >= testFns.length) {
if (currentTest >= testsLength) {
if (!stayingOnPage) {
finish();
return;
@ -171,10 +138,10 @@ function runCurrentTest() {
contentWindow.dialogWasInvoked = false;
originalLocation = contentWindow.location.href;
// And run this test:
info("Running test with onbeforeunload " + testFns[currentTest].toSource());
contentWindow.onbeforeunload = testFns[currentTest];
info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
loadStarted = false;
contentWindow.location.href = TARGETED_PAGE;
testTab.linkedBrowser.loadURI(TARGETED_PAGE);
}
var onAfterPageLoad = runNextTest;

View File

@ -7,4 +7,44 @@
<body>
Waiting for onbeforeunload to hit...
</body>
<script>
var testFns = [
function(e) {
e.target.location.href = 'otherpage-href-set.html';
return "stop";
},
function(e) {
e.target.location.reload();
return "stop";
},
function(e) {
e.target.location.replace('otherpage-location-replaced.html');
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = "otherpage.html";
e.target.body.appendChild(link);
link.click();
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = "otherpage.html";
link.setAttribute("target", "_blank");
e.target.body.appendChild(link);
link.click();
return "stop";
},
function(e) {
var link = e.target.createElement('a');
link.href = e.target.location.href;
e.target.body.appendChild(link);
link.setAttribute("target", "somearbitrarywindow");
link.click();
return "stop";
},
];
</script>
</html>

View File

@ -31,8 +31,8 @@ function makeTimelineTest(frameScriptName, url) {
info(message.data.message);
});
mm.addMessageListener("browser:test:finish", function(ignore) {
finish();
gBrowser.removeCurrentTab();
finish();
});
});
}

View File

@ -186,7 +186,8 @@ function runNextTest()
gCurrentTest = gTests[gNextTest++];
gNumPokes = 0;
SpecialPowers.pushPrefEnv({"set": [["network.jar.open-unsafe-types", gCurrentTest['pref']]]}, function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false],
["network.jar.open-unsafe-types", gCurrentTest['pref']]]}, function() {
// Create a new frame each time, so our restictions on loads in a
// jar:-loaded iframe don't interfere with the test.

View File

@ -0,0 +1,99 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ComputedTimingFunction.h"
#include "nsStyleUtil.h"
namespace mozilla {
void
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
{
mType = aFunction.mType;
if (nsTimingFunction::IsSplineType(mType)) {
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
} else {
mSteps = aFunction.mSteps;
mStepSyntax = aFunction.mStepSyntax;
}
}
static inline double
StepEnd(uint32_t aSteps, double aPortion)
{
MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
uint32_t step = uint32_t(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
double
ComputedTimingFunction::GetValue(double aPortion) const
{
if (HasSpline()) {
return mTimingFunction.GetSplineValue(aPortion);
}
if (mType == nsTimingFunction::Type::StepStart) {
// There are diagrams in the spec that seem to suggest this check
// and the bounds point should not be symmetric with StepEnd, but
// should actually step up at rather than immediately after the
// fraction points. However, we rely on rounding negative values
// up to zero, so we can't do that. And it's not clear the spec
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
}
MOZ_ASSERT(mType == nsTimingFunction::Type::StepEnd, "bad type");
return StepEnd(mSteps, aPortion);
}
int32_t
ComputedTimingFunction::Compare(const ComputedTimingFunction& aRhs) const
{
if (mType != aRhs.mType) {
return int32_t(mType) - int32_t(aRhs.mType);
}
if (mType == nsTimingFunction::Type::CubicBezier) {
int32_t order = mTimingFunction.Compare(aRhs.mTimingFunction);
if (order != 0) {
return order;
}
} else if (mType == nsTimingFunction::Type::StepStart ||
mType == nsTimingFunction::Type::StepEnd) {
if (mSteps != aRhs.mSteps) {
return int32_t(mSteps) - int32_t(aRhs.mSteps);
}
if (mStepSyntax != aRhs.mStepSyntax) {
return int32_t(mStepSyntax) - int32_t(aRhs.mStepSyntax);
}
}
return 0;
}
void
ComputedTimingFunction::AppendToString(nsAString& aResult) const
{
switch (mType) {
case nsTimingFunction::Type::CubicBezier:
nsStyleUtil::AppendCubicBezierTimingFunction(mTimingFunction.X1(),
mTimingFunction.Y1(),
mTimingFunction.X2(),
mTimingFunction.Y2(),
aResult);
break;
case nsTimingFunction::Type::StepStart:
case nsTimingFunction::Type::StepEnd:
nsStyleUtil::AppendStepsTimingFunction(mType, mSteps, mStepSyntax,
aResult);
break;
default:
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(mType, aResult);
break;
}
}
} // namespace mozilla

View File

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ComputedTimingFunction_h
#define mozilla_ComputedTimingFunction_h
#include "nsSMILKeySpline.h" // nsSMILKeySpline
#include "nsStyleStruct.h" // nsTimingFunction
namespace mozilla {
class ComputedTimingFunction
{
public:
void Init(const nsTimingFunction &aFunction);
double GetValue(double aPortion) const;
const nsSMILKeySpline* GetFunction() const
{
NS_ASSERTION(HasSpline(), "Type mismatch");
return &mTimingFunction;
}
nsTimingFunction::Type GetType() const { return mType; }
bool HasSpline() const { return nsTimingFunction::IsSplineType(mType); }
uint32_t GetSteps() const { return mSteps; }
nsTimingFunction::StepSyntax GetStepSyntax() const { return mStepSyntax; }
bool operator==(const ComputedTimingFunction& aOther) const
{
return mType == aOther.mType &&
(HasSpline() ?
mTimingFunction == aOther.mTimingFunction :
(mSteps == aOther.mSteps &&
mStepSyntax == aOther.mStepSyntax));
}
bool operator!=(const ComputedTimingFunction& aOther) const
{
return !(*this == aOther);
}
int32_t Compare(const ComputedTimingFunction& aRhs) const;
void AppendToString(nsAString& aResult) const;
private:
nsTimingFunction::Type mType;
nsSMILKeySpline mTimingFunction;
uint32_t mSteps;
nsTimingFunction::StepSyntax mStepSyntax;
};
} // namespace mozilla
#endif // mozilla_dom_AnimationEffectReadOnly_h

View File

@ -86,94 +86,6 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
}
}
void
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
{
mType = aFunction.mType;
if (nsTimingFunction::IsSplineType(mType)) {
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
} else {
mSteps = aFunction.mSteps;
mStepSyntax = aFunction.mStepSyntax;
}
}
static inline double
StepEnd(uint32_t aSteps, double aPortion)
{
MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
uint32_t step = uint32_t(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
double
ComputedTimingFunction::GetValue(double aPortion) const
{
if (HasSpline()) {
return mTimingFunction.GetSplineValue(aPortion);
}
if (mType == nsTimingFunction::Type::StepStart) {
// There are diagrams in the spec that seem to suggest this check
// and the bounds point should not be symmetric with StepEnd, but
// should actually step up at rather than immediately after the
// fraction points. However, we rely on rounding negative values
// up to zero, so we can't do that. And it's not clear the spec
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
}
MOZ_ASSERT(mType == nsTimingFunction::Type::StepEnd, "bad type");
return StepEnd(mSteps, aPortion);
}
int32_t
ComputedTimingFunction::Compare(const ComputedTimingFunction& aRhs) const
{
if (mType != aRhs.mType) {
return int32_t(mType) - int32_t(aRhs.mType);
}
if (mType == nsTimingFunction::Type::CubicBezier) {
int32_t order = mTimingFunction.Compare(aRhs.mTimingFunction);
if (order != 0) {
return order;
}
} else if (mType == nsTimingFunction::Type::StepStart ||
mType == nsTimingFunction::Type::StepEnd) {
if (mSteps != aRhs.mSteps) {
return int32_t(mSteps) - int32_t(aRhs.mSteps);
}
if (mStepSyntax != aRhs.mStepSyntax) {
return int32_t(mStepSyntax) - int32_t(aRhs.mStepSyntax);
}
}
return 0;
}
void
ComputedTimingFunction::AppendToString(nsAString& aResult) const
{
switch (mType) {
case nsTimingFunction::Type::CubicBezier:
nsStyleUtil::AppendCubicBezierTimingFunction(mTimingFunction.X1(),
mTimingFunction.Y1(),
mTimingFunction.X2(),
mTimingFunction.Y2(),
aResult);
break;
case nsTimingFunction::Type::StepStart:
case nsTimingFunction::Type::StepEnd:
nsStyleUtil::AppendStepsTimingFunction(mType, mSteps, mStepSyntax,
aResult);
break;
default:
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(mType, aResult);
break;
}
}
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadOnly,

View File

@ -13,7 +13,8 @@
#include "nsIDocument.h"
#include "nsWrapperCache.h"
#include "mozilla/Attributes.h"
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
#include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
#include "mozilla/StickyTimeDuration.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/TimeStamp.h"
@ -21,8 +22,6 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeBinding.h"
#include "mozilla/dom/Nullable.h"
#include "nsSMILKeySpline.h"
#include "nsStyleStruct.h" // for nsTimingFunction
struct JSContext;
class nsCSSPropertySet;
@ -97,41 +96,6 @@ struct ComputedTiming
AnimationPhase mPhase = AnimationPhase::Null;
};
class ComputedTimingFunction
{
public:
typedef nsTimingFunction::Type Type;
typedef nsTimingFunction::StepSyntax StepSyntax;
void Init(const nsTimingFunction &aFunction);
double GetValue(double aPortion) const;
const nsSMILKeySpline* GetFunction() const {
NS_ASSERTION(HasSpline(), "Type mismatch");
return &mTimingFunction;
}
Type GetType() const { return mType; }
bool HasSpline() const { return nsTimingFunction::IsSplineType(mType); }
uint32_t GetSteps() const { return mSteps; }
StepSyntax GetStepSyntax() const { return mStepSyntax; }
bool operator==(const ComputedTimingFunction& aOther) const {
return mType == aOther.mType &&
(HasSpline() ?
mTimingFunction == aOther.mTimingFunction :
(mSteps == aOther.mSteps &&
mStepSyntax == aOther.mStepSyntax));
}
bool operator!=(const ComputedTimingFunction& aOther) const {
return !(*this == aOther);
}
int32_t Compare(const ComputedTimingFunction& aRhs) const;
void AppendToString(nsAString& aResult) const;
private:
Type mType;
nsSMILKeySpline mTimingFunction;
uint32_t mSteps;
StepSyntax mStepSyntax;
};
struct AnimationPropertySegment
{
float mFromKey, mToKey;

View File

@ -18,6 +18,7 @@ EXPORTS.mozilla.dom += [
EXPORTS.mozilla += [
'AnimationComparator.h',
'AnimationUtils.h',
'ComputedTimingFunction.h',
'PendingAnimationTracker.h',
]
@ -25,6 +26,7 @@ UNIFIED_SOURCES += [
'Animation.cpp',
'AnimationEffectReadOnly.cpp',
'AnimationTimeline.cpp',
'ComputedTimingFunction.cpp',
'DocumentTimeline.cpp',
'KeyframeEffect.cpp',
'PendingAnimationTracker.cpp',

View File

@ -106,7 +106,6 @@ class nsIWindowProvider;
struct JSPropertyDescriptor;
struct JSRuntime;
struct nsIntMargin;
template<class E> class nsCOMArray;
template<class K, class V> class nsDataHashtable;

View File

@ -8894,16 +8894,6 @@ nsDocument::Destroy()
mRegistry = nullptr;
using mozilla::dom::workers::ServiceWorkerManager;
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (swm) {
ErrorResult error;
if (swm->IsControlled(this, error)) {
nsContentUtils::GetImgLoaderForDocument(this)->ClearCacheForControlledDocument(this);
}
swm->MaybeStopControlling(this);
}
// XXX We really should let cycle collection do this, but that currently still
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
ReleaseWrapper(static_cast<nsINode*>(this));
@ -8915,6 +8905,19 @@ nsDocument::RemovedFromDocShell()
if (mRemovedFromDocShell)
return;
using mozilla::dom::workers::ServiceWorkerManager;
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (swm) {
ErrorResult error;
if (swm->IsControlled(this, error)) {
imgLoader* loader = nsContentUtils::GetImgLoaderForDocument(this);
if (loader) {
loader->ClearCacheForControlledDocument(this);
}
}
swm->MaybeStopControlling(this);
}
mRemovedFromDocShell = true;
EnumerateActivityObservers(NotifyActivityChanged, nullptr);

View File

@ -64,7 +64,9 @@ function runTests() {
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTests);
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTests);
});
});
</script>
</pre>

View File

@ -502,8 +502,7 @@ BluetoothMapSmsManager::ReplyToConnect()
req[3] = 0x10; // version=1.0
req[4] = 0x00; // flag=0x00
req[5] = BluetoothMapSmsManager::MAX_PACKET_LENGTH >> 8;
req[6] = (uint8_t)BluetoothMapSmsManager::MAX_PACKET_LENGTH;
BigEndian::writeUint16(&req[5], BluetoothMapSmsManager::MAX_PACKET_LENGTH);
// Section 6.4 "Establishing an OBEX Session", MapSms 1.2
// Headers: [Who:16][Connection ID]

View File

@ -866,8 +866,7 @@ BluetoothOppManager::ComposePacket(uint8_t aOpCode, UnixSocketBuffer* aMessage)
// [opcode:1][length:2][Headers:var]
frameHeaderLength = 3;
mPacketLength = ((static_cast<int>(data[1]) << 8) | data[2]) -
frameHeaderLength;
mPacketLength = BigEndian::readUint16(&data[1]) - frameHeaderLength;
/**
* A PUT request from remote devices may be divided into multiple parts.
@ -1119,7 +1118,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
// Keep remote information
mRemoteObexVersion = data[3];
mRemoteConnectionFlags = data[4];
mRemoteMaxPacketLength = ((static_cast<int>(data[5]) << 8) | data[6]);
mRemoteMaxPacketLength = BigEndian::readUint16(&data[5]);
// The length of file name exceeds maximum length.
int fileNameByteLen = (mFileName.Length() + 1) * 2;

View File

@ -242,7 +242,7 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
}
// Save the max packet length from remote information
mRemoteMaxPacketLength = ((static_cast<int>(data[5]) << 8) | data[6]);
mRemoteMaxPacketLength = BigEndian::readUint16(&data[5]);
if (mRemoteMaxPacketLength < kObexLeastMaxSize) {
BT_LOGR("Remote maximum packet length %d is smaller than %d bytes",

View File

@ -842,8 +842,7 @@ BluetoothOppManager::ComposePacket(uint8_t aOpCode, UnixSocketBuffer* aMessage)
// [opcode:1][length:2][Headers:var]
frameHeaderLength = 3;
mPacketLength = ((static_cast<int>(data[1]) << 8) | data[2]) -
frameHeaderLength;
mPacketLength = BigEndian::readUint16(&data[1]) - frameHeaderLength;
/**
* A PUT request from remote devices may be divided into multiple parts.
* In other words, one request may need to be received multiple times,
@ -1094,7 +1093,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
// Keep remote information
mRemoteObexVersion = data[3];
mRemoteConnectionFlags = data[4];
mRemoteMaxPacketLength = (static_cast<int>(data[5]) << 8) | data[6];
mRemoteMaxPacketLength = BigEndian::readUint16(&data[5]);
// The length of file name exceeds maximum length.
int fileNameByteLen = (mFileName.Length() + 1) * 2;

View File

@ -9,6 +9,7 @@
#include <algorithm>
#include "mozilla/Compiler.h"
#include "mozilla/Endian.h"
#include "mozilla/Observer.h"
#include "nsAutoPtr.h"
#include "nsPrintfCString.h"
@ -496,14 +497,12 @@ struct BluetoothAddress {
uint16_t GetNAP() const
{
return (static_cast<uint16_t>(mAddr[4])) |
(static_cast<uint16_t>(mAddr[5]) << 8);
return LittleEndian::readUint16(&mAddr[4]);
}
void SetNAP(uint16_t aNAP)
{
mAddr[4] = aNAP;
mAddr[5] = aNAP >> 8;
LittleEndian::writeUint16(&mAddr[4], aNAP);
}
};
@ -635,10 +634,7 @@ struct BluetoothUuid {
void SetUuid32(uint32_t aUuid32)
{
mUuid[0] = static_cast<uint8_t>(0xff & (aUuid32 >> 24));
mUuid[1] = static_cast<uint8_t>(0xff & (aUuid32 >> 16));
mUuid[2] = static_cast<uint8_t>(0xff & (aUuid32 >> 8));
mUuid[3] = static_cast<uint8_t>(0xff & (aUuid32));
BigEndian::writeUint32(&mUuid[0], aUuid32);
mUuid[4] = 0x00;
mUuid[5] = 0x00;
mUuid[6] = 0x10;
@ -655,10 +651,7 @@ struct BluetoothUuid {
uint32_t GetUuid32() const
{
return (static_cast<uint32_t>(mUuid[0]) << 24) |
(static_cast<uint32_t>(mUuid[1]) << 16) |
(static_cast<uint32_t>(mUuid[2]) << 8) |
(static_cast<uint32_t>(mUuid[3]));
return BigEndian::readUint32(&mUuid[0]);
}
void SetUuid16(uint16_t aUuid16)
@ -668,8 +661,7 @@ struct BluetoothUuid {
uint16_t GetUuid16() const
{
return (static_cast<uint16_t>(mUuid[2]) << 8) |
(static_cast<uint16_t>(mUuid[3]));
return BigEndian::readUint16(&mUuid[2]);
}
};

View File

@ -23,8 +23,7 @@ AppendHeader(uint8_t aHeaderId, uint8_t* aRetBuf, int aBufferSize,
int writtenLength = (headerLength < aBufferSize) ? headerLength : aBufferSize;
aRetBuf[0] = aHeaderId;
aRetBuf[1] = (headerLength & 0xFF00) >> 8;
aRetBuf[2] = headerLength & 0x00FF;
BigEndian::writeUint16(&aRetBuf[1], headerLength);
memcpy(&aRetBuf[3], aData, writtenLength - 3);
return writtenLength;
@ -37,10 +36,7 @@ int
AppendHeader(uint8_t aHeaderId, uint8_t* aRetBuf, int aValue)
{
aRetBuf[0] = aHeaderId;
aRetBuf[1] = (aValue & 0xFF000000) >> 24;
aRetBuf[2] = (aValue & 0x00FF0000) >> 16;
aRetBuf[3] = (aValue & 0x0000FF00) >> 8;
aRetBuf[4] = aValue & 0x000000FF;
BigEndian::writeInt32(&aRetBuf[1], aValue);
return 5;
}
@ -135,8 +131,7 @@ void
SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength)
{
aRetBuf[0] = aOpcode;
aRetBuf[1] = (aPacketLength & 0xFF00) >> 8;
aRetBuf[2] = aPacketLength & 0x00FF;
BigEndian::writeUint16(&aRetBuf[1], aPacketLength);
}
bool
@ -150,7 +145,6 @@ ParseHeaders(const uint8_t* aHeaderStart,
ObexHeaderId headerId = (ObexHeaderId)*ptr++;
uint16_t contentLength = 0;
uint8_t highByte, lowByte;
// Defined in 2.1 OBEX Headers, IrOBEX 1.2
switch (headerId >> 6)
@ -160,9 +154,8 @@ ParseHeaders(const uint8_t* aHeaderStart,
// unsigned integer.
case 0x01:
// byte sequence, length prefixed with 2 byte unsigned integer.
highByte = *ptr++;
lowByte = *ptr++;
contentLength = (((uint16_t)highByte << 8) | lowByte) - 3;
contentLength = BigEndian::readUint16(ptr) - 3;
ptr += 2;
break;
case 0x02:

View File

@ -8,6 +8,7 @@
#define mozilla_dom_bluetooth_ObexBase_h
#include "BluetoothCommon.h"
#include "mozilla/Endian.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
@ -178,7 +179,7 @@ public:
uint8_t* ptr = mHeaders[i]->mData.get();
for (int j = 0; j < nameLength; ++j) {
char16_t c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
char16_t c = BigEndian::readUint16(&ptr[j * 2]);
aRetName += c;
}
@ -211,10 +212,7 @@ public:
for (int i = 0; i < length; ++i) {
if (mHeaders[i]->mId == ObexHeaderId::Length) {
uint8_t* ptr = mHeaders[i]->mData.get();
*aRetLength = ((uint32_t)ptr[0] << 24) |
((uint32_t)ptr[1] << 16) |
((uint32_t)ptr[2] << 8) |
((uint32_t)ptr[3]);
*aRetLength = BigEndian::readUint32(&ptr[0]);
return;
}
}

View File

@ -19,6 +19,11 @@ Cu.import("resource://gre/modules/ExtensionContent.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "acs",
"@mozilla.org/audiochannel/service;1",
"nsIAudioChannelService");
XPCOMUtils.defineLazyModuleGetter(this, "ManifestFinder",
"resource://gre/modules/ManifestFinder.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ManifestObtainer",
"resource://gre/modules/ManifestObtainer.jsm");
var kLongestReturnedString = 128;
@ -289,7 +294,8 @@ BrowserElementChild.prototype = {
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
"set-audio-channel-muted": this._recvSetAudioChannelMuted,
"get-is-audio-channel-active": this._recvIsAudioChannelActive,
"get-structured-data": this._recvGetStructuredData
"get-structured-data": this._recvGetStructuredData,
"get-web-manifest": this._recvGetWebManifest,
}
addMessageListener("browser-element-api:call", function(aMessage) {
@ -1527,7 +1533,26 @@ BrowserElementChild.prototype = {
id: data.json.id, successRv: active
});
},
_recvGetWebManifest: Task.async(function* (data) {
debug(`Received GetWebManifest message: (${data.json.id})`);
let manifest = null;
let hasManifest = ManifestFinder.contentHasManifestLink(content);
if (hasManifest) {
try {
manifest = yield ManifestObtainer.contentObtainManifest(content);
} catch (e) {
sendAsyncMsg('got-web-manifest', {
id: data.json.id,
errorMsg: `Error fetching web manifest: ${e}.`,
});
return;
}
}
sendAsyncMsg('got-web-manifest', {
id: data.json.id,
successRv: manifest
});
}),
_initFinder: function() {
if (!this._finder) {
try {

View File

@ -386,7 +386,8 @@ BrowserElementParent.prototype = {
"got-audio-channel-muted": this._gotDOMRequestResult,
"got-set-audio-channel-muted": this._gotDOMRequestResult,
"got-is-audio-channel-active": this._gotDOMRequestResult,
"got-structured-data": this._gotDOMRequestResult
"got-structured-data": this._gotDOMRequestResult,
"got-web-manifest": this._gotDOMRequestResult,
};
let mmSecuritySensitiveCalls = {
@ -1210,6 +1211,7 @@ BrowserElementParent.prototype = {
getStructuredData: defineDOMRequestMethod('get-structured-data'),
getWebManifest: defineDOMRequestMethod('get-web-manifest'),
/**
* Called when the visibility of the window which owns this iframe changes.
*/

View File

@ -0,0 +1,65 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*globals async, ok, is, SimpleTest, browserElementTestHelpers*/
// Bug 1169633 - getWebManifest tests
'use strict';
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
// request to load a manifest from a page that doesn't have a manifest.
// The expected result to be null.
var test1 = async(function* () {
var manifest = yield requestManifest('file_empty.html');
is(manifest, null, 'it should be null.');
});
// request to load a manifest from a page that has a manifest.
// The expected manifest to have a property name whose value is 'pass'.
var test2 = async(function* () {
var manifest = yield requestManifest('file_web_manifest.html');
is(manifest && manifest.name, 'pass', 'it should return a manifest with name pass.');
});
// Cause an exception by attempting to fetch a file URL,
// expect onerror to be called.
var test3 = async(function* () {
var gotError = false;
try {
yield requestManifest('file_illegal_web_manifest.html');
} catch (err) {
gotError = true;
}
ok(gotError, 'onerror was called on the DOMRequest.');
});
// Run the tests
addEventListener('testready', () => {
Promise
.all([test1(), test2(), test3()])
.then(SimpleTest.finish);
});
function requestManifest(url) {
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.src = url;
document.body.appendChild(iframe);
return new Promise((resolve, reject) => {
iframe.addEventListener('mozbrowserloadend', function loadend() {
iframe.removeEventListener('mozbrowserloadend', loadend);
SimpleTest.executeSoon(() => {
var req = iframe.getWebManifest();
req.onsuccess = () => {
document.body.removeChild(iframe);
resolve(req.result);
};
req.onerror = () => {
document.body.removeChild(iframe);
reject(new Error(req.error));
};
});
});
});
}

View File

@ -0,0 +1,6 @@
<!doctype html>
<meta charset=utf-8>
<head>
<link rel="manifest" href="file://this_is_not_allowed!">
</head>
<h1>Support Page for Web Manifest Tests</h1>

View File

@ -0,0 +1,6 @@
<!doctype html>
<meta charset=utf-8>
<head>
<link rel="manifest" href="file_web_manifest.json">
</head>
<h1>Support Page for Web Manifest Tests</h1>

View File

@ -0,0 +1 @@
{"name": "pass"}

View File

@ -119,3 +119,4 @@ disabled = bug 924771
[test_browserElement_oop_GetContentDimensions.html]
[test_browserElement_oop_AudioChannel.html]
[test_browserElement_oop_SetNFCFocus.html]
[test_browserElement_oop_getWebManifest.html]

View File

@ -39,6 +39,7 @@ support-files =
browserElement_GetScreenshot.js
browserElement_GetScreenshotDppx.js
browserElement_getStructuredData.js
browserElement_getWebManifest.js
browserElement_Iconchange.js
browserElement_LoadEvents.js
browserElement_Manifestchange.js
@ -136,10 +137,14 @@ support-files =
file_wyciwyg.html
file_audio.html
iframe_file_audio.html
file_web_manifest.html
file_web_manifest.json
file_illegal_web_manifest.html
# Note: browserElementTestHelpers.js looks at the test's filename to determine
# whether the test should be OOP. "_oop_" signals OOP, "_inproc_" signals in
# process. Default is OOP.
[test_browserElement_inproc_getWebManifest.html]
[test_browserElement_NoAttr.html]
[test_browserElement_NoPref.html]
[test_browserElement_NoPermission.html]

View File

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 1169633</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/dom/browser-element/mochitest/browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.8"
src="async.js">
</script>
<script type="application/javascript;version=1.8"
src="browserElement_getWebManifest.js">
</script>
</body>
</html>

View File

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 1169633</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/dom/browser-element/mochitest/browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.8"
src="async.js"></script>
<script type="application/javascript;version=1.8"
src="browserElement_getWebManifest.js">
</script>
</body>
</html>

View File

@ -9,7 +9,7 @@
interface nsIDOMDOMRequest;
interface nsIFrameLoader;
[scriptable, function, uuid(c0c2dd9b-41ef-42dd-a4c1-e456619c1941)]
[scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)]
interface nsIBrowserElementNextPaintListener : nsISupports
{
void recvNextPaint();
@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
* Interface to the BrowserElementParent implementation. All methods
* but setFrameLoader throw when the remote process is dead.
*/
[scriptable, uuid(9946695c-1ed3-4abb-bc60-6f8947fd5641)]
[scriptable, uuid(1e098c3a-7d65-452d-a2b2-9ffd1b6e04bb)]
interface nsIBrowserElementAPI : nsISupports
{
const long FIND_CASE_SENSITIVE = 0;
@ -101,6 +101,12 @@ interface nsIBrowserElementAPI : nsISupports
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
/**
* Returns an object that represents a Web Manifest:
* http://w3c.github.io/manifest/
*/
nsIDOMDOMRequest getWebManifest();
/**
* Returns a JSON string representing Microdata objects on the page.
* Format is described at:

View File

@ -312,22 +312,7 @@ WebGL2Context::GetUniformIndices(WebGLProgram* program,
if (!uniformNames.Length())
return;
GLuint progname = program->mGLName;
size_t count = uniformNames.Length();
nsTArray<GLuint>& arr = retval.SetValue();
MakeContextCurrent();
for (size_t n = 0; n < count; n++) {
NS_LossyConvertUTF16toASCII name(uniformNames[n]);
// const GLchar* glname = name.get();
const GLchar* glname = nullptr;
name.BeginReading(glname);
GLuint index = 0;
gl->fGetUniformIndices(progname, 1, &glname, &index);
arr.AppendElement(index);
}
program->GetUniformIndices(uniformNames, retval);
}
void

View File

@ -758,6 +758,51 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const
return locObj.forget();
}
void
WebGLProgram::GetUniformIndices(const dom::Sequence<nsString>& uniformNames,
dom::Nullable< nsTArray<GLuint> >& retval) const
{
size_t count = uniformNames.Length();
nsTArray<GLuint>& arr = retval.SetValue();
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
for (size_t i = 0; i < count; i++) {
const NS_LossyConvertUTF16toASCII userName(uniformNames[i]);
nsDependentCString baseUserName;
bool isArray;
size_t arrayIndex;
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
const WebGLActiveInfo* activeInfo;
if (!LinkInfo()->FindUniform(baseUserName, &activeInfo)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
const nsCString& baseMappedName = activeInfo->mBaseMappedName;
nsAutoCString mappedName(baseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
mappedName.AppendLiteral("]");
}
const GLchar* mappedNameBytes = mappedName.BeginReading();
GLuint index = 0;
gl->fGetUniformIndices(mGLName, 1, &mappedNameBytes, &index);
arr.AppendElement(index);
}
}
void
WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const
{

View File

@ -161,6 +161,8 @@ public:
dom::Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval,
ErrorResult& rv) const;
already_AddRefed<WebGLUniformLocation> GetUniformLocation(const nsAString& name) const;
void GetUniformIndices(const dom::Sequence<nsString>& uniformNames,
dom::Nullable< nsTArray<GLuint> >& retval) const;
void UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const;
bool LinkProgram();

View File

@ -357,8 +357,16 @@ WebGLShader::FindUniformBlockByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const
{
// TODO: Extract block information from shader validator.
return false;
if (!mValidator)
return false;
const std::string mappedNameStr(mappedName.BeginReading(), mappedName.Length());
std::string userNameStr;
if (!mValidator->FindUniformBlockByMappedName(mappedNameStr, &userNameStr))
return false;
*out_userName = userNameStr.c_str();
return true;
}
void
@ -379,9 +387,8 @@ WebGLShader::ApplyTransformFeedbackVaryings(GLuint prog,
std::string userNameStr(userName.BeginReading());
const std::string* mappedNameStr = &userNameStr;
// TODO: Are vertex->fragment shader varyings listed under attribs?
if (mValidator)
mValidator->FindAttribMappedNameByUserName(userNameStr, &mappedNameStr);
mValidator->FindVaryingMappedNameByUserName(userNameStr, &mappedNameStr);
mappedVaryings.push_back(*mappedNameStr);
}

View File

@ -361,6 +361,21 @@ ShaderValidator::FindAttribMappedNameByUserName(const std::string& userName,
return false;
}
bool
ShaderValidator::FindVaryingMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const
{
const std::vector<sh::Varying>& attribs = *ShGetVaryings(mHandle);
for (auto itr = attribs.begin(); itr != attribs.end(); ++itr) {
if (itr->name == userName) {
*out_mappedName = &(itr->mappedName);
return true;
}
}
return false;
}
// This must handle names like "foo.bar[0]".
bool
ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
@ -377,6 +392,22 @@ ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
return true;
}
return false;
}
bool
ShaderValidator::FindUniformBlockByMappedName(const std::string& mappedName,
std::string* const out_userName) const
{
const std::vector<sh::InterfaceBlock>& interfaces = *ShGetInterfaceBlocks(mHandle);
for (const auto& interface : interfaces) {
if (mappedName == interface.mappedName) {
*out_userName = interface.name;
return true;
}
}
return false;
}

View File

@ -50,9 +50,15 @@ public:
bool FindAttribMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const;
bool FindVaryingMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const;
bool FindUniformByMappedName(const std::string& mappedName,
std::string* const out_userName,
bool* const out_isArray) const;
bool FindUniformBlockByMappedName(const std::string& mappedName,
std::string* const out_userName) const;
};
} // namespace webgl

Some files were not shown because too many files have changed in this diff Show More