import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,93 @@
[DEFAULT]
support-files =
favicon_bug655270.ico
file_bug234628-1-child.html
file_bug234628-1.html
file_bug234628-10-child.xhtml
file_bug234628-10.html
file_bug234628-11-child.xhtml
file_bug234628-11-child.xhtml^headers^
file_bug234628-11.html
file_bug234628-2-child.html
file_bug234628-2.html
file_bug234628-3-child.html
file_bug234628-3.html
file_bug234628-4-child.html
file_bug234628-4.html
file_bug234628-5-child.html
file_bug234628-5.html
file_bug234628-6-child.html
file_bug234628-6-child.html^headers^
file_bug234628-6.html
file_bug234628-7-child.html
file_bug234628-7-child.html^headers^
file_bug234628-7.html
file_bug234628-8-child.html
file_bug234628-8.html
file_bug234628-9-child.html
file_bug234628-9.html
file_bug420605.html
file_bug422543_script.js
file_bug503832.html
file_bug655270.html
file_bug670318.html
file_bug852909.pdf
file_bug852909.png
file_bug1046022.html
file_bug1206879.html
file_multiple_pushState.html
print_postdata.sjs
test-form_sjis.html
timelineMarkers-04.html
browser_timelineMarkers-frame-02.js
browser_timelineMarkers-frame-03.js
browser_timelineMarkers-frame-04.js
browser_timelineMarkers-frame-05.js
head.js
frame-head.js
[browser_bug1206879.js]
[browser_bug1309900_crossProcessHistoryNavigation.js]
[browser_bug134911.js]
[browser_bug234628-1.js]
[browser_bug234628-10.js]
[browser_bug234628-11.js]
[browser_bug234628-2.js]
[browser_bug234628-3.js]
[browser_bug234628-4.js]
[browser_bug234628-5.js]
[browser_bug234628-6.js]
[browser_bug234628-7.js]
[browser_bug234628-8.js]
[browser_bug234628-9.js]
[browser_bug349769.js]
[browser_bug388121-1.js]
[browser_bug388121-2.js]
[browser_bug420605.js]
[browser_bug422543.js]
[browser_bug441169.js]
[browser_bug503832.js]
[browser_bug554155.js]
[browser_bug655270.js]
[browser_bug655273.js]
[browser_bug670318.js]
[browser_bug673467.js]
[browser_bug852909.js]
[browser_bug92473.js]
[browser_uriFixupIntegration.js]
[browser_uriFixupAlternateRedirects.js]
support-files =
redirect_to_example.sjs
[browser_loadDisallowInherit.js]
[browser_loadURI.js]
[browser_multiple_pushState.js]
[browser_onbeforeunload_navigation.js]
[browser_search_notification.js]
[browser_tab_touch_events.js]
[browser_timelineMarkers-01.js]
[browser_timelineMarkers-02.js]
skip-if = true # Bug 1220415
[browser_timelineMarkers-03.js]
[browser_timelineMarkers-04.js]
[browser_timelineMarkers-05.js]
[browser_ua_emulation.js]

View file

@ -0,0 +1,31 @@
add_task(function*() {
let url = getRootDirectory(gTestPath) + "file_bug1206879.html";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, true);
let numLocationChanges = 0;
let listener = {
onLocationChange: function(browser, wp, request, uri, flags) {
if (browser != tab.linkedBrowser) {
return;
}
info("onLocationChange: " + uri.spec);
numLocationChanges++;
this.resolve();
}
};
let locationPromise = new Promise((resolve, reject) => {
listener.resolve = resolve;
gBrowser.addTabsProgressListener(listener);
});
yield ContentTask.spawn(tab.linkedBrowser, {}, function() {
content.frames[0].history.pushState(null, null, "foo");
});
yield locationPromise;
gBrowser.removeTab(tab);
gBrowser.removeTabsProgressListener(listener);
is(numLocationChanges, 1,
"pushState with a different URI should cause a LocationChange event.");
});

View file

@ -0,0 +1,35 @@
/* -*- 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/. */
add_task(function* runTests() {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:about");
registerCleanupFunction(function* () {
gBrowser.removeTab(tab);
});
let browser = tab.linkedBrowser;
browser.loadURI("about:accounts");
let href = yield BrowserTestUtils.browserLoaded(browser);
is(href, "about:accounts", "Check about:accounts loaded");
// Using a dummy onunload listener to disable the bfcache as that can prevent
// the test browser load detection mechanism from working.
browser.loadURI("data:text/html,<body%20onunload=''><iframe></iframe></body>");
href = yield BrowserTestUtils.browserLoaded(browser);
is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
"Check data URL loaded");
browser.goBack();
href = yield BrowserTestUtils.browserLoaded(browser);
is(href, "about:accounts", "Check we've gone back to about:accounts");
browser.goForward();
href = yield BrowserTestUtils.browserLoaded(browser);
is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
"Check we've gone forward to data URL");
});

View file

@ -0,0 +1,41 @@
const TEXT = {
/* The test text decoded correctly as Shift_JIS */
rightText: "\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059",
enteredText1: "The quick brown fox jumps over the lazy dog",
enteredText2: "\u03BE\u03B5\u03C3\u03BA\u03B5\u03C0\u03AC\u03B6\u03C9\u0020\u03C4\u1F74\u03BD\u0020\u03C8\u03C5\u03C7\u03BF\u03C6\u03B8\u03CC\u03C1\u03B1\u0020\u03B2\u03B4\u03B5\u03BB\u03C5\u03B3\u03BC\u03AF\u03B1",
};
function test() {
waitForExplicitFinish();
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
}
function afterOpen() {
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
content.document.getElementById("testtextarea").value = TEXT.enteredText1;
content.document.getElementById("testinput").value = TEXT.enteredText2;
}).then(() => {
/* Force the page encoding to Shift_JIS */
BrowserSetForcedCharacterSet("Shift_JIS");
});
}
function afterChangeCharset() {
ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
is(content.document.getElementById("testpar").innerHTML, TEXT.rightText,
"encoding successfully changed");
is(content.document.getElementById("testtextarea").value, TEXT.enteredText1,
"text preserved in <textarea>");
is(content.document.getElementById("testinput").value, TEXT.enteredText2,
"text preserved in <input>");
}).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-1.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 85, "Child doc should be windows-1252 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 85, "Child doc should decode as windows-1251 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-10.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 151, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should be utf-8 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 151, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should decode as utf-8 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-11.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 193, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 193, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should decode as utf-8 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-2.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u00E2\u201A\u00AC'), 78, "Child doc should be windows-1252 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 78, "Child doc should decode as windows-1251 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-3.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 118, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 73, "Child doc should be utf-8 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 118, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 73, "Child doc should decode as windows-1251 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-4.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 132, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should be utf-8 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 132, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should decode as utf-8 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-5.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 146, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should be utf-16 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 146, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should decode as utf-16 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "UTF-16LE", "Child doc should report UTF-16LE subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-6.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 190, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should be utf-16 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 190, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should decode as utf-16 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "UTF-16BE", "Child doc should report UTF-16 subsequently");
}

View file

@ -0,0 +1,18 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-7.html", afterOpen, "windows-1251", afterChangeCharset);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 188, "Parent doc should be windows-1252 initially");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
}
function afterChangeCharset() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 188, "Parent doc should decode as windows-1251 subsequently");
is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 107, "Child doc should decode as windows-1251 subsequently");
is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
}

View file

@ -0,0 +1,11 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-8.html", afterOpen);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u0402'), 156, "Parent doc should be windows-1251");
is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 99, "Child doc should be windows-1251");
}

View file

@ -0,0 +1,11 @@
function test() {
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
runCharsetTest(rootDir + "file_bug234628-9.html", afterOpen);
}
function afterOpen() {
is(content.document.documentElement.textContent.indexOf('\u20AC'), 145, "Parent doc should be UTF-16");
is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 96, "Child doc should be windows-1252");
}

View file

@ -0,0 +1,47 @@
add_task(function* test() {
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
const uris = [undefined, "about:blank"];
function checkContentProcess(uri) {
yield ContentTask.spawn(newBrowser, uri, function* (uri) {
var prin = content.document.nodePrincipal;
Assert.notEqual(prin, null, "Loaded principal must not be null when adding " + uri);
Assert.notEqual(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
Assert.equal(secMan.isSystemPrincipal(prin), false,
"Loaded principal must not be system when loading " + uri);
});
}
for (var uri of uris) {
yield BrowserTestUtils.withNewTab({ gBrowser }, function* (newBrowser) {
yield BrowserTestUtils.loadURI(newBrowser, uri);
var prin = newBrowser.contentPrincipal;
isnot(prin, null, "Forced principal must not be null when loading " + uri);
isnot(prin, undefined,
"Forced principal must not be undefined when loading " + uri);
is(secMan.isSystemPrincipal(prin), false,
"Forced principal must not be system when loading " + uri);
// Belt-and-suspenders e10s check: make sure that the same checks hold
// true in the content process.
checkContentProcess(uri);
yield BrowserTestUtils.browserLoaded(newBrowser);
prin = newBrowser.contentPrincipal;
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
is(secMan.isSystemPrincipal(prin), false,
"Loaded principal must not be system when loading " + uri);
// Belt-and-suspenders e10s check: make sure that the same checks hold
// true in the content process.
checkContentProcess(uri);
});
}
});

View file

@ -0,0 +1,15 @@
add_task(function* test() {
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (newBrowser) {
yield ContentTask.spawn(newBrowser, null, function* () {
var prin = content.document.nodePrincipal;
Assert.notEqual(prin, null, "Loaded principal must not be null");
Assert.notEqual(prin, undefined, "Loaded principal must not be undefined");
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
Assert.equal(secMan.isSystemPrincipal(prin), false,
"Loaded principal must not be system");
});
});
});

View file

@ -0,0 +1,58 @@
function test() {
waitForExplicitFinish();
var w;
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
var iteration = 1;
const uris = ["", "about:blank"];
var uri;
var origDoc;
function testLoad() {
if (w.document == origDoc) {
// Go back to polling
setTimeout(testLoad, 10);
return;
}
var prin = w.document.nodePrincipal;
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
is(secMan.isSystemPrincipal(prin), false,
"Loaded principal must not be system when loading " + uri);
w.close();
if (iteration == uris.length) {
finish();
} else {
++iteration;
doTest();
}
}
function doTest() {
uri = uris[iteration - 1];
w = window.open(uri, "_blank", "width=10,height=10");
var prin = w.document.nodePrincipal;
if (!uri) {
uri = undefined;
}
isnot(prin, null, "Forced principal must not be null when loading " + uri);
isnot(prin, undefined,
"Forced principal must not be undefined when loading " + uri);
is(secMan.isSystemPrincipal(prin), false,
"Forced principal must not be system when loading " + uri);
if (uri == undefined) {
// No actual load here, so just move along.
w.close();
++iteration;
doTest();
} else {
origDoc = w.document;
// Need to poll, because load listeners on the content window won't
// survive the load.
setTimeout(testLoad, 10);
}
}
doTest();
}

View file

@ -0,0 +1,122 @@
/* Test for Bug 420605
* https://bugzilla.mozilla.org/show_bug.cgi?id=420605
*/
function test() {
waitForExplicitFinish();
var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html";
var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html#firefox";
var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
/* Queries nsINavHistoryService and returns a single history entry
* for a given URI */
function getNavHistoryEntry(aURI) {
var options = historyService.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
options.maxResults = 1;
var query = historyService.getNewQuery();
query.uri = aURI;
var result = historyService.executeQuery(query, options);
result.root.containerOpen = true;
if (!result.root.childCount) {
return null;
}
return result.root.getChild(0);
}
// We'll save the favicon URL of the orignal page here and check that the
// page with a hash has the same favicon.
var originalFavicon;
// Control flow in this test is a bit complicated.
//
// When the page loads, onPageLoad (the DOMContentLoaded handler) and
// historyObserver::onPageChanged are both called, in some order. Once
// they've both run, we click a fragment link in the content page
// (clickLinkIfReady), which should trigger another onPageChanged event,
// this time for the fragment's URL.
var _clickLinkTimes = 0;
function clickLinkIfReady() {
_clickLinkTimes++;
if (_clickLinkTimes == 2) {
BrowserTestUtils.synthesizeMouseAtCenter('#firefox-link', {},
gBrowser.selectedBrowser);
}
}
/* Global history observer that triggers for the two test URLs above. */
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
aTransitionType, _added) {},
onTitleChanged: function(aURI, aPageTitle) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
return;
}
aURI = aURI.spec;
switch (aURI) {
case pageurl:
ok(aValue, "Favicon value is not null for page without fragment.");
originalFavicon = aValue;
// Now that the favicon has loaded, click on fragment link.
// This should trigger the |case fragmenturl| below.
clickLinkIfReady();
return;
case fragmenturl:
// If the fragment URL's favicon isn't set, this branch won't
// be called and the test will time out.
is(aValue, originalFavicon, "New favicon should be same as original favicon.");
// Let's explicitly check that we can get the favicon
// from nsINavHistoryService now.
let info = getNavHistoryEntry(makeURI(aURI));
ok(info, "There must be a history entry for the fragment.");
ok(info.icon, "The history entry must have an associated favicon.");
historyService.removeObserver(historyObserver, false);
gBrowser.removeCurrentTab();
finish();
}
},
onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
historyService.addObserver(historyObserver, false);
function onPageLoad() {
gBrowser.selectedBrowser
.removeEventListener("DOMContentLoaded", arguments.callee, true);
clickLinkIfReady();
}
// Make sure neither of the test pages haven't been loaded before.
var info = getNavHistoryEntry(makeURI(pageurl));
ok(!info, "The test page must not have been visited already.");
info = getNavHistoryEntry(makeURI(fragmenturl));
ok(!info, "The fragment test page must not have been visited already.");
// Now open the test page in a new tab.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener(
"DOMContentLoaded", onPageLoad, true);
content.location = pageurl;
}

View file

@ -0,0 +1,116 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function* runTests() {
yield setup();
let browser = gBrowser.selectedBrowser;
// Now that we're set up, initialize our frame script.
yield checkListeners("initial", "listeners initialized");
// Check if all history listeners are always notified.
info("# part 1");
yield whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
yield checkListeners("newentry", "shistory has a new entry");
ok(browser.canGoBack, "we can go back");
yield whenPageShown(browser, () => browser.goBack());
yield checkListeners("goback", "back to the first shentry");
ok(browser.canGoForward, "we can go forward");
yield whenPageShown(browser, () => browser.goForward());
yield checkListeners("goforward", "forward to the second shentry");
yield whenPageShown(browser, () => browser.reload());
yield checkListeners("reload", "current shentry reloaded");
yield whenPageShown(browser, () => browser.gotoIndex(0));
yield checkListeners("gotoindex", "back to the first index");
// Check nsISHistoryInternal.notifyOnHistoryReload
info("# part 2");
ok((yield notifyReload()), "reloading has not been canceled");
yield checkListeners("reload", "saw the reload notification");
// Let the first listener cancel the reload action.
info("# part 3");
yield resetListeners();
yield setListenerRetval(0, false);
ok(!(yield notifyReload()), "reloading has been canceled");
yield checkListeners("reload", "saw the reload notification");
// Let both listeners cancel the reload action.
info("# part 4");
yield resetListeners();
yield setListenerRetval(1, false);
ok(!(yield notifyReload()), "reloading has been canceled");
yield checkListeners("reload", "saw the reload notification");
// Let the second listener cancel the reload action.
info("# part 5");
yield resetListeners();
yield setListenerRetval(0, true);
ok(!(yield notifyReload()), "reloading has been canceled");
yield checkListeners("reload", "saw the reload notification");
});
function listenOnce(message, arg = {}) {
return new Promise(resolve => {
let mm = gBrowser.selectedBrowser.messageManager;
mm.addMessageListener(message + ":return", function listener(msg) {
mm.removeMessageListener(message + ":return", listener);
resolve(msg.data);
});
mm.sendAsyncMessage(message, arg);
});
}
function checkListeners(aLast, aMessage) {
return listenOnce("bug422543:getListenerStatus").then((listenerStatuses) => {
is(listenerStatuses[0], aLast, aMessage);
is(listenerStatuses[1], aLast, aMessage);
});
}
function resetListeners() {
return listenOnce("bug422543:resetListeners");
}
function notifyReload() {
return listenOnce("bug422543:notifyReload").then(({ rval }) => {
return rval;
});
}
function setListenerRetval(num, val) {
return listenOnce("bug422543:setRetval", { num, val });
}
function setup() {
return BrowserTestUtils.openNewForegroundTab(gBrowser,
"http://mochi.test:8888")
.then(function (tab) {
let browser = tab.linkedBrowser;
registerCleanupFunction(function* () {
yield listenOnce("bug422543:cleanup");
gBrowser.removeTab(tab);
});
browser.messageManager
.loadFrameScript(getRootDirectory(gTestPath) + "file_bug422543_script.js", false);
});
}
function whenPageShown(aBrowser, aNavigation) {
let listener = ContentTask.spawn(aBrowser, null, function () {
return new Promise(resolve => {
addEventListener("pageshow", function onLoad() {
removeEventListener("pageshow", onLoad, true);
resolve();
}, true);
});
});
aNavigation();
return listener;
}

View file

@ -0,0 +1,37 @@
/* Make sure that netError won't allow HTML injection through badcert parameters. See bug 441169. */
var newBrowser
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);
ContentTask.spawn(newBrowser, null, task).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}

View file

@ -0,0 +1,87 @@
/* Test for Bug 503832
* https://bugzilla.mozilla.org/show_bug.cgi?id=503832
*/
add_task(function* () {
var pagetitle = "Page Title for Bug 503832";
var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html";
var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html#firefox";
var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
let fragmentPromise = new Promise(resolve => {
/* Global history observer that triggers for the two test URLs above. */
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
aTransitionType, _added) {},
onTitleChanged: function(aURI, aPageTitle) {
aURI = aURI.spec;
switch (aURI) {
case pageurl:
is(aPageTitle, pagetitle, "Correct page title for " + aURI);
return;
case fragmenturl:
is(aPageTitle, pagetitle, "Correct page title for " + aURI);
// If titles for fragment URLs aren't set, this code
// branch won't be called and the test will timeout,
// resulting in a failure
historyService.removeObserver(historyObserver, false);
resolve();
}
},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {},
onDeleteVisits: function () {},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
historyService.addObserver(historyObserver, false);
});
/* Queries nsINavHistoryService and returns a single history entry
* for a given URI */
function getNavHistoryEntry(aURI) {
var options = historyService.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
options.maxResults = 1;
var query = historyService.getNewQuery();
query.uri = aURI;
var result = historyService.executeQuery(query, options);
result.root.containerOpen = true;
if (!result.root.childCount) {
return null;
}
var node = result.root.getChild(0);
result.root.containerOpen = false;
return node;
}
// Make sure neither of the test pages haven't been loaded before.
var info = getNavHistoryEntry(makeURI(pageurl));
ok(!info, "The test page must not have been visited already.");
info = getNavHistoryEntry(makeURI(fragmenturl));
ok(!info, "The fragment test page must not have been visited already.");
// Now open the test page in a new tab
yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageurl);
// Now that the page is loaded, click on fragment link
yield BrowserTestUtils.synthesizeMouseAtCenter("#firefox-link", {},
gBrowser.selectedBrowser);
yield fragmentPromise;
gBrowser.removeCurrentTab();
});

View file

@ -0,0 +1,26 @@
add_task(function* test() {
yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" }, function* (browser) {
let numLocationChanges = 0;
let listener = {
onLocationChange: function(browser, webProgress, request, uri, flags) {
info("location change: " + (uri && uri.spec));
numLocationChanges++;
}
};
gBrowser.addTabsProgressListener(listener);
yield ContentTask.spawn(browser, null, function() {
// pushState to a new URL (http://example.com/foo"). This should trigger
// exactly one LocationChange event.
content.history.pushState(null, null, "foo");
});
yield Promise.resolve();
gBrowser.removeTabsProgressListener(listener);
is(numLocationChanges, 1,
"pushState should cause exactly one LocationChange event.");
});
});

View file

@ -0,0 +1,60 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test for Bug 655273
*
* Call pushState and then make sure that the favicon service associates our
* old favicon with the new URI.
*/
function test() {
const testDir = "http://mochi.test:8888/browser/docshell/test/browser/";
const origURL = testDir + "file_bug655270.html";
const newURL = origURL + '?new_page';
const faviconURL = testDir + "favicon_bug655270.ico";
waitForExplicitFinish();
let tab = gBrowser.addTab(origURL);
// The page at origURL has a <link rel='icon'>, so we should get a call into
// our observer below when it loads. Once we verify that we have the right
// favicon URI, we call pushState, which should trigger another onPageChange
// event, this time for the URI after pushState.
let observer = {
onPageChanged: function(aURI, aWhat, aValue) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
return;
if (aURI.spec == origURL) {
is(aValue, faviconURL, 'FaviconURL for original URI');
// Ignore the promise returned here and wait for the next
// onPageChanged notification.
ContentTask.spawn(tab.linkedBrowser, null, function() {
content.history.pushState('', '', '?new_page');
});
}
if (aURI.spec == newURL) {
is(aValue, faviconURL, 'FaviconURL for new URI');
gBrowser.removeTab(tab);
PlacesUtils.history.removeObserver(this);
finish();
}
},
onBeginUpdateBatch: function() { },
onEndUpdateBatch: function() { },
onVisit: function() { },
onTitleChanged: function() { },
onDeleteURI: function() { },
onClearHistory: function() { },
onDeleteVisits: function() { },
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
};
PlacesUtils.history.addObserver(observer, false);
}

View file

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Test for Bug 655273. Make sure that after changing the URI via
* history.pushState, the resulting SHEntry has the same title as our old
* SHEntry.
**/
add_task(function* test() {
waitForExplicitFinish();
yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
function* (browser) {
yield ContentTask.spawn(browser, null, function* () {
let cw = content;
let oldTitle = cw.document.title;
ok(oldTitle, 'Content window should initially have a title.');
cw.history.pushState('', '', 'new_page');
let shistory = cw.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.sessionHistory;
is(shistory.getEntryAtIndex(shistory.index, false).title,
oldTitle, 'SHEntry title after pushstate.');
});
});
});

View file

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test for Bug 670318
*
* When LoadEntry() is called on a browser that has multiple duplicate history
* entries, history.index can end up out of range (>= history.count).
*/
const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
add_task(function* test() {
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
function* (browser) {
yield ContentTask.spawn(browser, URL, function* (URL) {
let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
let count = 0;
let testDone = {};
testDone.promise = new Promise(resolve => { testDone.resolve = resolve; });
let listener = {
OnHistoryNewEntry: function (aNewURI) {
if (aNewURI.spec == URL && 5 == ++count) {
addEventListener("load", function onLoad() {
removeEventListener("load", onLoad, true);
Assert.ok(history.index < history.count, "history.index is valid");
testDone.resolve();
}, true);
history.removeSHistoryListener(listener);
delete content._testListener;
content.setTimeout(() => { content.location.reload(); }, 0);
}
return true;
},
OnHistoryReload: () => true,
OnHistoryGoBack: () => true,
OnHistoryGoForward: () => true,
OnHistoryGotoIndex: () => true,
OnHistoryPurge: () => true,
OnHistoryReplaceEntry: () => {
// The initial load of about:blank causes a transient entry to be
// created, so our first navigation to a real page is a replace
// instead of a new entry.
++count;
return true;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference])
};
history.addSHistoryListener(listener);
// Since listener implements nsISupportsWeakReference, we are
// responsible for keeping it alive so that the GC doesn't clear
// it before the test completes. We do this by anchoring the listener
// to the content global window, and clearing it just before the test
// completes.
content._testListener = listener;
content.location = URL;
yield testDone.promise;
});
});
});

View file

@ -0,0 +1,51 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test for bug 673467. In a new tab, load a page which inserts a new iframe
// before the load and then sets its location during the load. This should
// create just one SHEntry.
var doc = "data:text/html,<html><body onload='load()'>" +
"<script>" +
" var iframe = document.createElement('iframe');" +
" iframe.id = 'iframe';" +
" document.documentElement.appendChild(iframe);" +
" function load() {" +
" iframe.src = 'data:text/html,Hello!';" +
" }" +
"</script>" +
"</body></html>"
function test() {
waitForExplicitFinish();
let tab = gBrowser.addTab(doc);
let tabBrowser = tab.linkedBrowser;
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
return ContentTask.spawn(tab.linkedBrowser, null, () => {
return new Promise(resolve => {
// The main page has loaded. Now wait for the iframe to load.
let iframe = content.document.getElementById('iframe');
iframe.addEventListener('load', function listener(aEvent) {
// Wait for the iframe to load the new document, not about:blank.
if (!iframe.src)
return;
iframe.removeEventListener('load', listener, true);
let shistory = content
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.sessionHistory;
Assert.equal(shistory.count, 1, "shistory count should be 1.");
resolve();
}, true);
});
});
}).then(() => {
gBrowser.removeTab(tab);
finish();
});
}

View file

@ -0,0 +1,23 @@
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.png");
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(image);
}
function image(event) {
ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for images.");
gBrowser.removeCurrentTab();
gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.pdf");
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(pdf);
}
function pdf(event) {
ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for PDF.js.");
gBrowser.removeCurrentTab();
finish();
}

View file

@ -0,0 +1,54 @@
/* The test text as octets for reference
* %83%86%83%6a%83%52%81%5b%83%68%82%cd%81%41%82%b7%82%d7%82%c4%82%cc%95%b6%8e%9a%82%c9%8c%c5%97%4c%82%cc%94%d4%8d%86%82%f0%95%74%97%5e%82%b5%82%dc%82%b7
*/
function testContent(text) {
return ContentTask.spawn(gBrowser.selectedBrowser, text, text => {
Assert.equal(content.document.getElementById("testpar").innerHTML, text,
"<p> contains expected text");
Assert.equal(content.document.getElementById("testtextarea").innerHTML, text,
"<textarea> contains expected text");
Assert.equal(content.document.getElementById("testinput").value, text,
"<input> contains expected text");
});
}
function afterOpen() {
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
/* The test text decoded incorrectly as Windows-1251. This is the "right" wrong
text; anything else is unexpected. */
const wrongText="\u0453\u2020\u0453\u006A\u0453\u0052\u0403\u005B\u0453\u0068\u201A\u041D\u0403\u0041\u201A\u00B7\u201A\u0427\u201A\u0414\u201A\u041C\u2022\u00B6\u040B\u0459\u201A\u0419\u040A\u0415\u2014\u004C\u201A\u041C\u201D\u0424\u040C\u2020\u201A\u0440\u2022\u0074\u2014\u005E\u201A\u00B5\u201A\u042C\u201A\u00B7";
/* Test that the content on load is the expected wrong decoding */
testContent(wrongText).then(() => {
BrowserSetForcedCharacterSet("Shift_JIS");
});
}
function afterChangeCharset() {
/* The test text decoded correctly as Shift_JIS */
const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059";
/* test that the content is decoded correctly */
testContent(rightText).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}
function test() {
waitForExplicitFinish();
// Get the local directory. This needs to be a file: URI because chrome: URIs
// are always UTF-8 (bug 617339) and we are testing decoding from other
// charsets.
var jar = getJar(getRootDirectory(gTestPath));
var dir = jar ?
extractJarToTmp(jar) :
getChromeDir(getResolvedURI(gTestPath));
var rootDir = Services.io.newFileURI(dir).spec;
gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
}

View file

@ -0,0 +1,65 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
});
let browser = gBrowser.getBrowserForTab(tab);
function loadURL(url, flags, func) {
browser.addEventListener("load", function loadListener(e) {
if (browser.currentURI.spec != url)
return;
browser.removeEventListener(e.type, loadListener, true);
func();
}, true);
browser.loadURIWithFlags(url, flags, null, null, null);
}
// Load a normal http URL
function testURL(url, func) {
loadURL("http://example.com/", 0, function () {
let pagePrincipal = browser.contentPrincipal;
ok(pagePrincipal, "got principal for http:// page");
// Now load the URL normally
loadURL(url, 0, function () {
ok(browser.contentPrincipal.equals(pagePrincipal), url + " should inherit principal");
// Now load the URL and disallow inheriting the principal
let webNav = Components.interfaces.nsIWebNavigation;
loadURL(url, webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, function () {
let newPrincipal = browser.contentPrincipal;
ok(newPrincipal, "got inner principal");
ok(!newPrincipal.equals(pagePrincipal),
url + " should not inherit principal when loaded with DISALLOW_INHERIT_OWNER");
func();
});
});
});
}
let urls = [
"data:text/html,<body>hi",
// We used to test javascript: here as well, but now that we no longer run
// javascript: in a sandbox, we end up not running it at all in the
// DISALLOW_INHERIT_OWNER case, so never actually do a load for it at all.
];
function nextTest() {
let url = urls.shift();
if (url)
testURL(url, nextTest);
else
finish();
}
nextTest();
}

View file

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
var Cc = Components.classes;
var Ci = Components.interfaces;
const gPostData = "postdata=true";
function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
});
var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
dataStream.data = gPostData;
var postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
createInstance(Ci.nsIMIMEInputStream);
postStream.addHeader("Content-Type", "application/x-www-form-urlencoded");
postStream.addContentLength = true;
postStream.setData(dataStream);
tab.linkedBrowser.loadURIWithFlags("http://mochi.test:8888/browser/docshell/test/browser/print_postdata.sjs", 0, null, null, postStream);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
ContentTask.spawn(tab.linkedBrowser, gPostData, function(postData) {
var bodyText = content.document.body.textContent;
is(bodyText, postData, "post data was submitted correctly");
}).then(() => { finish(); });
});
}

View file

@ -0,0 +1,15 @@
add_task(function* test_multiple_pushState() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.org/browser/docshell/test/browser/file_multiple_pushState.html",
}, function* (browser) {
const kExpected = "http://example.org/bar/ABC/DEF?key=baz";
let contentLocation = yield ContentTask.spawn(browser, null, function* () {
return content.document.location.href;
});
is(contentLocation, kExpected);
is(browser.documentURI.spec, kExpected);
});
});

View file

@ -0,0 +1,176 @@
var contentWindow;
var originalLocation;
var currentTest = -1;
var stayingOnPage = true;
var TEST_PAGE = "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
var TARGETED_PAGE = "data:text/html," + encodeURIComponent("<body>Shouldn't be seeing this</body>");
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
var loadExpected = TEST_PAGE;
var testTab;
var testsLength;
var loadStarted = false;
var tabStateListener = {
onStateChange: function(webprogress, request, stateFlags, status) {
let startDocumentFlags = Ci.nsIWebProgressListener.STATE_START |
Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
if ((stateFlags & startDocumentFlags) == startDocumentFlags) {
loadStarted = true;
}
},
onStatusChange: () => {},
onLocationChange: () => {},
onSecurityChange: () => {},
onProgressChange: () => {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener])
};
function onTabLoaded(event) {
info("A document loaded in a tab!");
let loadedPage = event.target.location.href;
if (loadedPage == "about:blank" ||
event.originalTarget != testTab.linkedBrowser.contentDocument) {
return;
}
if (!loadExpected) {
ok(false, "Expected no page loads, but loaded " + loadedPage + " instead!");
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");
}
if (onAfterPageLoad) {
onAfterPageLoad();
}
}
function onAfterTargetedPageLoad() {
ok(!stayingOnPage, "We should only fire if we're expecting to let the onbeforeunload dialog proceed to the new location");
is(testTab.linkedBrowser.currentURI.spec, TARGETED_PAGE, "Should have loaded the expected new page");
runNextTest();
}
function onTabModalDialogLoaded(node) {
let content = testTab.linkedBrowser.contentWindow;
ok(!loadStarted, "No load should be started.");
info(content.location.href);
is(content, contentWindow, "Window should be the same still.");
is(content.location.href, originalLocation, "Page should not have changed.");
is(content.mySuperSpecialMark, 42, "Page should not have refreshed.");
ok(!content.dialogWasInvoked, "Dialog should only be invoked once per test.");
content.dialogWasInvoked = true;
// Now listen for the dialog going away again...
let observer = new MutationObserver(function(muts) {
if (!node.parentNode) {
info("Dialog is gone");
observer.disconnect();
observer = null;
// If we're staying on the page, run the next test from here
if (stayingOnPage) {
// Evil, but necessary: without this delay, we manage to still break our
// own onbeforeunload code, because we'll basically cause a new load to be
// started while processing the destruction of the dialog for the old one.
executeSoon(runNextTest);
}
// if we accepted a page load in the dialog, the next test will get started
// by the load handler for that page loading
}
});
observer.observe(node.parentNode, {childList: true});
// If we're going to let the page load, set us up to listen for that happening:
if (!stayingOnPage) {
loadExpected = TARGETED_PAGE;
onAfterPageLoad = onAfterTargetedPageLoad;
}
let button = stayingOnPage ? node.ui.button1 : node.ui.button0;
// ... and then actually make the dialog go away
info("Clicking button: " + button.label);
EventUtils.synthesizeMouseAtCenter(button, {});
}
// Listen for the dialog being created
Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
function runNextTest() {
currentTest++;
if (currentTest >= testsLength) {
if (!stayingOnPage) {
finish();
return;
}
// Run the same tests again, but this time let the navigation happen:
stayingOnPage = false;
// Remove onbeforeunload handler, or this load will trigger the dialog...
contentWindow.onbeforeunload = null;
currentTest = 0;
}
if (!stayingOnPage) {
// Right now we're on the data: page. Null contentWindow out to
// avoid CPOW errors when contentWindow is no longer the correct
// outer window proxy object.
contentWindow = null;
onAfterPageLoad = runCurrentTest;
loadExpected = TEST_PAGE;
testTab.linkedBrowser.loadURI(TEST_PAGE);
} else {
runCurrentTest();
}
}
function runCurrentTest() {
// Reset things so we're sure the previous tests failings don't influence this one:
contentWindow = testTab.linkedBrowser.contentWindow;
contentWindow.mySuperSpecialMark = 42;
contentWindow.dialogWasInvoked = false;
originalLocation = contentWindow.location.href;
// And run this test:
info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
loadStarted = false;
testTab.linkedBrowser.loadURI(TARGETED_PAGE);
}
var onAfterPageLoad = runNextTest;
function test() {
waitForExplicitFinish();
gBrowser.addProgressListener(tabStateListener);
testTab = gBrowser.selectedTab = gBrowser.addTab();
testTab.linkedBrowser.addEventListener("load", onTabLoaded, true);
testTab.linkedBrowser.loadURI(TEST_PAGE);
}
registerCleanupFunction(function() {
// Remove the handler, or closing this tab will prove tricky:
if (contentWindow) {
try {
contentWindow.onbeforeunload = null;
} catch (ex) {}
}
contentWindow = null;
testTab.linkedBrowser.removeEventListener("load", onTabLoaded, true);
Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
gBrowser.removeProgressListener(tabStateListener);
gBrowser.removeTab(testTab);
});

View file

@ -0,0 +1,51 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
const kSearchEngineID = "test_urifixup_search_engine";
const kSearchEngineURL = "http://localhost/?search={searchTerms}";
Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
kSearchEngineURL);
let oldDefaultEngine = Services.search.defaultEngine;
Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
let selectedName = Services.search.defaultEngine.name;
is(selectedName, kSearchEngineID, "Check fake search engine is selected");
registerCleanupFunction(function() {
if (oldDefaultEngine) {
Services.search.defaultEngine = oldDefaultEngine;
}
let engine = Services.search.getEngineByName(kSearchEngineID);
if (engine) {
Services.search.removeEngine(engine);
}
});
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
function observer(subject, topic, data) {
Services.obs.removeObserver(observer, "keyword-search");
is(topic, "keyword-search", "Got keyword-search notification");
let engine = Services.search.defaultEngine;
ok(engine, "Have default search engine.");
is(engine, subject, "Notification subject is engine.");
is("firefox health report", data, "Notification data is search term.");
executeSoon(function cleanup() {
gBrowser.removeTab(tab);
finish();
});
}
Services.obs.addObserver(observer, "keyword-search", false);
gURLBar.value = "firefox health report";
gURLBar.handleCommand();
}

View file

@ -0,0 +1,49 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(function*() {
const URI = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
yield BrowserTestUtils.withNewTab({ gBrowser, url: URI }, function* (browser) {
yield ContentTask.spawn(browser, null, test_body);
});
});
function* test_body() {
let docshell = docShell;
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_NONE,
"touchEventsOverride flag should be initially set to NONE");
docshell.touchEventsOverride = Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED;
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"touchEventsOverride flag should be changed to DISABLED");
let frameWin = content.document.querySelector("#test-iframe").contentWindow;
docshell = frameWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"touchEventsOverride flag should be passed on to frames.");
let newFrame = content.document.createElement("iframe");
content.document.body.appendChild(newFrame);
let newFrameWin = newFrame.contentWindow;
docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"Newly created frames should use the new touchEventsOverride flag");
newFrameWin.location.reload();
yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
"New touchEventsOverride flag should persist across reloads");
}

View file

@ -0,0 +1,32 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the docShell has the right profile timeline API
const URL = "data:text/html;charset=utf-8,Test page";
add_task(function* () {
yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
function* (browser) {
yield ContentTask.spawn(browser, null, function() {
ok("recordProfileTimelineMarkers" in docShell,
"The recordProfileTimelineMarkers attribute exists");
ok("popProfileTimelineMarkers" in docShell,
"The popProfileTimelineMarkers function exists");
ok(docShell.recordProfileTimelineMarkers === false,
"recordProfileTimelineMarkers is false by default");
ok(docShell.popProfileTimelineMarkers().length === 0,
"There are no markers by default");
docShell.recordProfileTimelineMarkers = true;
ok(docShell.recordProfileTimelineMarkers === true,
"recordProfileTimelineMarkers can be set to true");
docShell.recordProfileTimelineMarkers = false;
ok(docShell.recordProfileTimelineMarkers === false,
"recordProfileTimelineMarkers can be set to false");
});
});
});

View file

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var URL = '<!DOCTYPE html><style>' +
'body {margin:0; padding: 0;} ' +
'div {width:100px;height:100px;background:red;} ' +
'.resize-change-color {width:50px;height:50px;background:blue;} ' +
'.change-color {width:50px;height:50px;background:yellow;} ' +
'.add-class {}' +
'</style><div></div>';
URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
var test = makeTimelineTest("browser_timelineMarkers-frame-02.js", URL);

View file

@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var URL = "data:text/html;charset=utf-8,<p>Test page</p>";
var test = makeTimelineTest("browser_timelineMarkers-frame-03.js", URL);

View file

@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = "http://mochi.test:8888/browser/docshell/test/browser/timelineMarkers-04.html";
var test = makeTimelineTest("browser_timelineMarkers-frame-04.js", URL);

View file

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var URL = '<!DOCTYPE html><style>' +
'body {margin:0; padding: 0;} ' +
'div {width:100px;height:100px;background:red;} ' +
'.resize-change-color {width:50px;height:50px;background:blue;} ' +
'.change-color {width:50px;height:50px;background:yellow;} ' +
'.add-class {}' +
'</style><div></div>';
URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
var test = makeTimelineTest("browser_timelineMarkers-frame-05.js", URL);

View file

@ -0,0 +1,133 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the docShell profile timeline API returns the right markers when
// restyles, reflows and paints occur
function rectangleContains(rect, x, y, width, height) {
return rect.x <= x && rect.y <= y && rect.width >= width &&
rect.height >= height;
}
function sanitizeMarkers(list) {
// These markers are currently gathered from all docshells, which may
// interfere with this test.
return list.filter(e => e.name != "Worker" && e.name != "MinorGC");
}
var TESTS = [{
desc: "Changing the width of the test element",
searchFor: "Paint",
setup: function(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "resize-change-color");
},
check: function(markers) {
markers = sanitizeMarkers(markers);
ok(markers.length > 0, "markers were returned");
console.log(markers);
info(JSON.stringify(markers.filter(m => m.name == "Paint")));
ok(markers.some(m => m.name == "Reflow"), "markers includes Reflow");
ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
for (let marker of markers.filter(m => m.name == "Paint")) {
// This change should generate at least one rectangle.
ok(marker.rectangles.length >= 1, "marker has one rectangle");
// One of the rectangles should contain the div.
ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100)));
}
ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
}
}, {
desc: "Changing the test element's background color",
searchFor: "Paint",
setup: function(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "change-color");
},
check: function(markers) {
markers = sanitizeMarkers(markers);
ok(markers.length > 0, "markers were returned");
ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
for (let marker of markers.filter(m => m.name == "Paint")) {
// This change should generate at least one rectangle.
ok(marker.rectangles.length >= 1, "marker has one rectangle");
// One of the rectangles should contain the div.
ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50)));
}
ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
}
}, {
desc: "Changing the test element's classname",
searchFor: "Paint",
setup: function(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "change-color add-class");
},
check: function(markers) {
markers = sanitizeMarkers(markers);
ok(markers.length > 0, "markers were returned");
ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
ok(!markers.some(m => m.name == "Paint"), "markers doesn't include Paint");
ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
}
}, {
desc: "sync console.time/timeEnd",
searchFor: "ConsoleTime",
setup: function(docShell) {
content.console.time("FOOBAR");
content.console.timeEnd("FOOBAR");
let markers = docShell.popProfileTimelineMarkers();
is(markers.length, 1, "Got one marker");
is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker");
is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail");
content.console.time("FOO");
content.setTimeout(() => {
content.console.time("BAR");
content.setTimeout(() => {
content.console.timeEnd("FOO");
content.console.timeEnd("BAR");
}, 100);
}, 100);
},
check: function(markers) {
markers = sanitizeMarkers(markers);
is(markers.length, 2, "Got 2 markers");
is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker");
is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail");
is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker");
is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail");
}
}, {
desc: "Timestamps created by console.timeStamp()",
searchFor: "Timestamp",
setup: function(docshell) {
content.console.timeStamp("rock");
let markers = docShell.popProfileTimelineMarkers();
is(markers.length, 1, "Got one marker");
is(markers[0].name, "TimeStamp", "Got Timestamp marker");
is(markers[0].causeName, "rock", "Got Timestamp label value");
content.console.timeStamp("paper");
content.console.timeStamp("scissors");
content.console.timeStamp();
content.console.timeStamp(undefined);
},
check: function (markers) {
markers = sanitizeMarkers(markers);
is(markers.length, 4, "Got 4 markers");
is(markers[0].name, "TimeStamp", "Got Timestamp marker");
is(markers[0].causeName, "paper", "Got Timestamp label value");
is(markers[1].name, "TimeStamp", "Got Timestamp marker");
is(markers[1].causeName, "scissors", "Got Timestamp label value");
is(markers[2].name, "TimeStamp", "Got empty Timestamp marker when no argument given");
is(markers[2].causeName, void 0, "Got empty Timestamp label value");
is(markers[3].name, "TimeStamp", "Got empty Timestamp marker when argument is undefined");
is(markers[3].causeName, void 0, "Got empty Timestamp label value");
markers.forEach(m => is(m.end, m.start,
"All Timestamp markers should have identical start/end times"));
}
}];
timelineContentTest(TESTS);

View file

@ -0,0 +1,91 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the docShell profile timeline API returns the right
// markers for DOM events.
var TESTS = [{
desc: "Event dispatch with single handler",
searchFor: 'DOMEvent',
setup: function(docShell) {
content.document.body.addEventListener("dog",
function(e) { console.log("hi"); },
true);
content.document.body.dispatchEvent(new content.Event("dog"));
},
check: function(markers) {
markers = markers.filter(m => m.name == 'DOMEvent');
is(markers.length, 1, "Got 1 marker");
is(markers[0].type, "dog", "Got dog event name");
is(markers[0].eventPhase, 2, "Got phase 2");
}
}, {
desc: "Event dispatch with a second handler",
searchFor: function(markers) {
return markers.filter(m => m.name == 'DOMEvent').length >= 2;
},
setup: function(docShell) {
content.document.body.addEventListener("dog",
function(e) { console.log("hi"); },
false);
content.document.body.dispatchEvent(new content.Event("dog"));
},
check: function(markers) {
markers = markers.filter(m => m.name == 'DOMEvent');
is(markers.length, 2, "Got 2 markers");
}
}, {
desc: "Event targeted at child",
searchFor: function(markers) {
return markers.filter(m => m.name == 'DOMEvent').length >= 2;
},
setup: function(docShell) {
let child = content.document.body.firstElementChild;
child.addEventListener("dog", function(e) { });
child.dispatchEvent(new content.Event("dog"));
},
check: function(markers) {
markers = markers.filter(m => m.name == 'DOMEvent');
is(markers.length, 2, "Got 2 markers");
is(markers[0].eventPhase, 1, "Got phase 1 marker");
is(markers[1].eventPhase, 2, "Got phase 2 marker");
}
}, {
desc: "Event dispatch on a new document",
searchFor: function(markers) {
return markers.filter(m => m.name == 'DOMEvent').length >= 2;
},
setup: function(docShell) {
let doc = content.document.implementation.createHTMLDocument("doc");
let p = doc.createElement("p");
p.innerHTML = "inside";
doc.body.appendChild(p);
p.addEventListener("zebra", function(e) {console.log("hi");});
p.dispatchEvent(new content.Event("zebra"));
},
check: function(markers) {
markers = markers.filter(m => m.name == 'DOMEvent');
is(markers.length, 1, "Got 1 marker");
}
}, {
desc: "Event dispatch on window",
searchFor: function(markers) {
return markers.filter(m => m.name == 'DOMEvent').length >= 2;
},
setup: function(docShell) {
let doc = content.window.addEventListener("aardvark", function(e) {
console.log("I like ants!");
});
content.window.dispatchEvent(new content.Event("aardvark"));
},
check: function(markers) {
markers = markers.filter(m => m.name == 'DOMEvent');
is(markers.length, 1, "Got 1 marker");
}
}];
timelineContentTest(TESTS);

View file

@ -0,0 +1,88 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the docShell profile timeline API returns the right
// markers for XMLHttpRequest events.
var TESTS = [{
desc: "Event dispatch from XMLHttpRequest",
searchFor: function(markers) {
return markers.filter(m => m.name == "DOMEvent").length >= 5;
},
setup: function(docShell) {
content.dispatchEvent(new content.Event("dog"));
},
check: function(markers) {
let domMarkers = markers.filter(m => m.name == "DOMEvent");
// One subtlety here is that we have five events: the event we
// inject in "setup", plus the four state transition events. The
// first state transition is reported synchronously and so should
// show up as a nested marker.
is(domMarkers.length, 5, "Got 5 markers");
// We should see some Javascript markers, and they should have a
// cause.
let jsMarkers = markers.filter(m => m.name == "Javascript" && m.causeName);
ok(jsMarkers.length > 0, "Got some Javascript markers");
is(jsMarkers[0].stack.functionDisplayName, "do_xhr",
"Javascript marker has entry point name");
}
}];
if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
TESTS.push({
desc: "Async stack trace on Javascript marker",
searchFor: (markers) => {
return markers.some(m => (m.name == "Javascript" &&
m.causeName == "promise callback"));
},
setup: function(docShell) {
content.dispatchEvent(new content.Event("promisetest"));
},
check: function(markers) {
markers = markers.filter(m => (m.name == "Javascript" &&
m.causeName == "promise callback"));
ok(markers.length > 0, "Found a Javascript marker");
let frame = markers[0].stack;
ok(frame.asyncParent !== null, "Parent frame has async parent");
is(frame.asyncParent.asyncCause, "promise callback",
"Async parent has correct cause");
let asyncFrame = frame.asyncParent;
// Skip over self-hosted parts of our Promise implementation.
while (asyncFrame.source === 'self-hosted')
asyncFrame = asyncFrame.parent;
is(asyncFrame.functionDisplayName, "do_promise",
"Async parent has correct function name");
}
}, {
desc: "Async stack trace on Javascript marker with script",
searchFor: (markers) => {
return markers.some(m => (m.name == "Javascript" &&
m.causeName == "promise callback"));
},
setup: function(docShell) {
content.dispatchEvent(new content.Event("promisescript"));
},
check: function(markers) {
markers = markers.filter(m => (m.name == "Javascript" &&
m.causeName == "promise callback"));
ok(markers.length > 0, "Found a Javascript marker");
let frame = markers[0].stack;
ok(frame.asyncParent !== null, "Parent frame has async parent");
is(frame.asyncParent.asyncCause, "promise callback",
"Async parent has correct cause");
let asyncFrame = frame.asyncParent;
// Skip over self-hosted parts of our Promise implementation.
while (asyncFrame.source === 'self-hosted')
asyncFrame = asyncFrame.parent;
is(asyncFrame.functionDisplayName, "do_promise_script",
"Async parent has correct function name");
}
});
}
timelineContentTest(TESTS);

View file

@ -0,0 +1,117 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function forceSyncReflow(div) {
div.setAttribute('class', 'resize-change-color');
// Force a reflow.
return div.offsetWidth;
}
function testSendingEvent() {
content.document.body.dispatchEvent(new content.Event("dog"));
}
function testConsoleTime() {
content.console.time("cats");
}
function testConsoleTimeEnd() {
content.console.timeEnd("cats");
}
function makePromise() {
let resolver;
new Promise(function(resolve, reject) {
testConsoleTime();
resolver = resolve;
}).then(function(val) {
testConsoleTimeEnd();
});
return resolver;
}
function resolvePromise(resolver) {
resolver(23);
}
var TESTS = [{
desc: "Stack trace on sync reflow",
searchFor: "Reflow",
setup: function(docShell) {
let div = content.document.querySelector("div");
forceSyncReflow(div);
},
check: function(markers) {
markers = markers.filter(m => m.name == "Reflow");
ok(markers.length > 0, "Reflow marker includes stack");
ok(markers[0].stack.functionDisplayName == "forceSyncReflow");
}
}, {
desc: "Stack trace on DOM event",
searchFor: "DOMEvent",
setup: function(docShell) {
content.document.body.addEventListener("dog",
function(e) { console.log("hi"); },
true);
testSendingEvent();
},
check: function(markers) {
markers = markers.filter(m => m.name == "DOMEvent");
ok(markers.length > 0, "DOMEvent marker includes stack");
ok(markers[0].stack.functionDisplayName == "testSendingEvent",
"testSendingEvent is on the stack");
}
}, {
desc: "Stack trace on console event",
searchFor: "ConsoleTime",
setup: function(docShell) {
testConsoleTime();
testConsoleTimeEnd();
},
check: function(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(markers.length > 0, "ConsoleTime marker includes stack");
ok(markers[0].stack.functionDisplayName == "testConsoleTime",
"testConsoleTime is on the stack");
ok(markers[0].endStack.functionDisplayName == "testConsoleTimeEnd",
"testConsoleTimeEnd is on the stack");
}
}];
if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
TESTS.push({
desc: "Async stack trace on Promise",
searchFor: "ConsoleTime",
setup: function(docShell) {
let resolver = makePromise();
resolvePromise(resolver);
},
check: function(markers) {
markers = markers.filter(m => m.name == "ConsoleTime");
ok(markers.length > 0, "Promise marker includes stack");
ok(markers[0].stack.functionDisplayName == "testConsoleTime",
"testConsoleTime is on the stack");
let frame = markers[0].endStack;
ok(frame.functionDisplayName == "testConsoleTimeEnd",
"testConsoleTimeEnd is on the stack");
frame = frame.parent;
ok(frame.functionDisplayName == "makePromise/<",
"makePromise/< is on the stack");
let asyncFrame = frame.asyncParent;
ok(asyncFrame !== null, "Frame has async parent");
is(asyncFrame.asyncCause, "promise callback",
"Async parent has correct cause");
// Skip over self-hosted parts of our Promise implementation.
while (asyncFrame.source === 'self-hosted') {
asyncFrame = asyncFrame.parent;
}
is(asyncFrame.functionDisplayName, "makePromise",
"Async parent has correct function name");
}
});
}
timelineContentTest(TESTS);

View file

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
// Test that the docShell UA emulation works
function* contentTask() {
let docshell = docShell;
is(docshell.customUserAgent, "", "There should initially be no customUserAgent");
docshell.customUserAgent = "foo";
is(content.navigator.userAgent, "foo", "The user agent should be changed to foo");
let frameWin = content.document.querySelector("#test-iframe").contentWindow;
is(frameWin.navigator.userAgent, "foo", "The UA should be passed on to frames.");
let newFrame = content.document.createElement("iframe");
content.document.body.appendChild(newFrame);
let newFrameWin = newFrame.contentWindow;
is(newFrameWin.navigator.userAgent, "foo", "Newly created frames should use the new UA");
newFrameWin.location.reload();
yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
is(newFrameWin.navigator.userAgent, "foo", "New UA should persist across reloads");
}
add_task(function* () {
yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
function* (browser) {
yield ContentTask.spawn(browser, null, contentTask);
});
});

View file

@ -0,0 +1,24 @@
"use strict";
const REDIRECTURL = "http://www.example.com/browser/docshell/test/browser/redirect_to_example.sjs"
add_task(function* () {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
gURLBar.value = REDIRECTURL;
gURLBar.select();
let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
EventUtils.sendKey("return");
yield errorPageLoaded;
let [contentURL, originalURL] = yield ContentTask.spawn(tab.linkedBrowser, null, () => {
return [
content.document.documentURI,
content.document.mozDocumentURIIfNotForErrorPages.spec,
];
});
info("Page that loaded: " + contentURL);
ok(contentURL.startsWith("about:neterror?"), "Should be on an error page");
originalURL = new URL(originalURL);
is(originalURL.host, "example", "Should be an error for http://example, not http://www.example.com/");
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -0,0 +1,51 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const kSearchEngineID = "browser_urifixup_search_engine";
const kSearchEngineURL = "http://example.com/?search={searchTerms}";
add_task(function* setup() {
// Add a new fake search engine.
Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
kSearchEngineURL);
let oldDefaultEngine = Services.search.defaultEngine;
Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
// Remove the fake engine when done.
registerCleanupFunction(() => {
if (oldDefaultEngine) {
Services.search.defaultEngine = oldDefaultEngine;
}
let engine = Services.search.getEngineByName(kSearchEngineID);
if (engine) {
Services.search.removeEngine(engine);
}
});
});
add_task(function* test() {
for (let searchParams of ["foo bar", "brokenprotocol:somethingelse"]) {
// Add a new blank tab.
gBrowser.selectedTab = gBrowser.addTab("about:blank");
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
// Enter search terms and start a search.
gURLBar.value = searchParams;
gURLBar.focus();
EventUtils.synthesizeKey("VK_RETURN", {});
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
// Check that we arrived at the correct URL.
let escapedParams = encodeURIComponent(searchParams).replace("%20", "+");
let expectedURL = kSearchEngineURL.replace("{searchTerms}", escapedParams);
is(gBrowser.selectedBrowser.currentURI.spec, expectedURL,
"New tab should have loaded with expected url.");
// Cleanup.
gBrowser.removeCurrentTab();
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1046022 - test navigating inside onbeforeunload</title>
</head>
<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

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Test page for bug 1206879</title>
</head>
<body>
<iframe src="http://example.com/"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in parent or child</title>
</head>
<body>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in parent or child</title>
</head>
<body>
<h1>No encoding declaration in parent or child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-1-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,4 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>XML child with no encoding declaration</title></head>
<body><p>Euro sign if decoded as UTF-8: €</p></body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in HTML parent or XHTML child</title>
</head>
<body>
<h1>No encoding declaration in HTML parent or XHTML child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-10-child.xhtml"></iframe>
</body>
</html>

View file

@ -0,0 +1,4 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title></head>
<body><p>Euro sign if decoded as UTF-8: €</p></body>
</html>

View file

@ -0,0 +1 @@
Content-Type: application/xhtml+xml; charset=utf-8

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title>
</head>
<body>
<h1>No encoding declaration in HTML parent and HTTP declaration in XHTML child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-11-child.xhtml"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in parent or child</title>
</head>
<body>
<p>Euro sign if decoded as UTF-8: €</p>
<p>a with diaeresis if decoded as UTF-8: ä</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>No encoding declaration in parent or child</title>
</head>
<body>
<h1>No encoding declaration in parent or child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-2-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and child</title>
</head>
<body>
<p>Euro sign if decoded as UTF-8: €</p>
<p>a with diaeresis if decoded as UTF-8: ä</p>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1252">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and child</title>
</head>
<body>
<h1>meta declaration in parent and child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-3-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and BOM in child</title>
</head>
<body>
<p>Euro sign if decoded as UTF-8: €</p>
<p>a with diaeresis if decoded as UTF-8: ä</p>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1252">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and BOM in child</title>
</head>
<body>
<h1>meta declaration in parent and BOM in child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-4-child.html"></iframe>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1252">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and UTF-16 BOM in child</title>
</head>
<body>
<h1>meta declaration in parent and UTF-16 BOM in child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-5-child.html"></iframe>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1 @@
Content-Type: text/html; charset=utf-16be

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1252">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</title>
</head>
<body>
<h1>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-6-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
</head>
<body>
<p>Euro sign if decoded as UTF-8: €</p>
<p>a with diaeresis if decoded as UTF-8: ä</p>
</body>
</html>

View file

@ -0,0 +1 @@
Content-Type: text/html; charset=utf-8

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1252">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
</head>
<body>
<h1>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</h1>
<p>Euro sign if decoded as Windows-1252: €</p>
<p>a with diaeresis if decoded as Windows-1252: ä</p>
<iframe src="file_bug234628-7-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and no declaration in child</title>
</head>
<body>
<p>Capital dje if decoded as Windows-1251: €</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="windows-1251">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>meta declaration in parent and no declaration in child</title>
</head>
<body>
<h1>meta declaration in parent and no declaration in child</h1>
<p>Capital dje if decoded as Windows-1251: €</p>
<iframe src="file_bug234628-8-child.html"></iframe>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>UTF-16 with BOM in parent and no declaration in child</title>
</head>
<body>
<p>Euro sign if decoded as Windows-1251: €</p>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1,31 @@
<head>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="/>
<title>Page Title for Bug 420605</title>
</head>
<body>
<h1>Fragment links</h1>
<p>This page has a bunch of fragment links to sections below:</p>
<ul>
<li><a id="firefox-link" href="#firefox">Firefox</a></li>
<li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
<li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
</ul>
<p>And here are the sections:</p>
<h2 id="firefox">Firefox</h2>
<p>Firefox is a browser.</p>
<h2 id="thunderbird">Thunderbird</h2>
<p>Thunderbird is an email client</p>
<h2 id="seamonkey">Seamonkey</h2>
<p>Seamonkey is the all-in-one application.</p>
</body>
</html>

View file

@ -0,0 +1,98 @@
const { utils: Cu, interfaces: Ci } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function SHistoryListener() {
}
SHistoryListener.prototype = {
retval: true,
last: "initial",
OnHistoryNewEntry: function (aNewURI) {
this.last = "newentry";
},
OnHistoryGoBack: function (aBackURI) {
this.last = "goback";
return this.retval;
},
OnHistoryGoForward: function (aForwardURI) {
this.last = "goforward";
return this.retval;
},
OnHistoryGotoIndex: function (aIndex, aGotoURI) {
this.last = "gotoindex";
return this.retval;
},
OnHistoryPurge: function (aNumEntries) {
this.last = "purge";
return this.retval;
},
OnHistoryReload: function (aReloadURI, aReloadFlags) {
this.last = "reload";
return this.retval;
},
OnHistoryReplaceEntry: function (aIndex) {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference])
};
let testAPI = {
shistory: null,
listeners: [ new SHistoryListener(),
new SHistoryListener() ],
init() {
this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
for (let listener of this.listeners) {
this.shistory.addSHistoryListener(listener);
}
},
cleanup() {
for (let listener of this.listeners) {
this.shistory.removeSHistoryListener(listener);
}
this.shistory = null;
sendAsyncMessage("bug422543:cleanup:return", {});
},
getListenerStatus() {
sendAsyncMessage("bug422543:getListenerStatus:return",
this.listeners.map(l => l.last));
},
resetListeners() {
for (let listener of this.listeners) {
listener.last = "initial";
}
sendAsyncMessage("bug422543:resetListeners:return", {});
},
notifyReload() {
let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
let rval =
internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
sendAsyncMessage("bug422543:notifyReload:return", { rval });
},
setRetval({ num, val }) {
this.listeners[num].retval = val;
sendAsyncMessage("bug422543:setRetval:return", {});
},
};
addMessageListener("bug422543:cleanup", () => { testAPI.cleanup(); });
addMessageListener("bug422543:getListenerStatus", () => { testAPI.getListenerStatus(); });
addMessageListener("bug422543:notifyReload", () => { testAPI.notifyReload(); });
addMessageListener("bug422543:resetListeners", () => { testAPI.resetListeners(); });
addMessageListener("bug422543:setRetval", (msg) => { testAPI.setRetval(msg.data); });
testAPI.init();

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<!--
Test page for https://bugzilla.mozilla.org/show_bug.cgi?id=503832
-->
<head>
<title>Page Title for Bug 503832</title>
</head>
<body>
<h1>Fragment links</h1>
<p>This page has a bunch of fragment links to sections below:</p>
<ul>
<li><a id="firefox-link" href="#firefox">Firefox</a></li>
<li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
<li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
</ul>
<p>And here are the sections:</p>
<h2 id="firefox">Firefox</h2>
<p>Firefox is a browser.</p>
<h2 id="thunderbird">Thunderbird</h2>
<p>Thunderbird is an email client</p>
<h2 id="seamonkey">Seamonkey</h2>
<p>Seamonkey is the all-in-one application.</p>
</body>
</html>

View file

@ -0,0 +1,11 @@
<html>
<head>
<link rel='icon' href='favicon_bug655270.ico'>
</head>
<body>
Nothing to see here...
</body>
</html>

View file

@ -0,0 +1,23 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script>
function load() {
function next() {
if (count < 5)
iframe.src = 'data:text/html;charset=utf-8,iframe ' + (++count);
}
var count = 0;
var iframe = document.createElement('iframe');
iframe.onload = function () { setTimeout(next, 0) };
document.body.appendChild(iframe);
setTimeout(next, 0);
}
</script>
</head>
<body onload="load()">
Testcase
</body>
</html>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test multiple calls to history.pushState</title>
</head>
<body>
<h1>Ohai</h1>
</body>
<script type="text/javascript">
window.history.pushState({}, "", "/bar/ABC?key=baz");
window.history.pushState({}, "", "/bar/ABC/DEF?key=baz");
</script>
</html>

View file

@ -0,0 +1,113 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Functions that are automatically loaded as frame scripts for
// timeline tests.
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
var { Promise } = Cu.import('resource://gre/modules/Promise.jsm', {});
Cu.import("resource://gre/modules/Timer.jsm");
// Functions that look like mochitest functions but forward to the
// browser process.
this.ok = function(value, message) {
sendAsyncMessage("browser:test:ok", {
value: !!value,
message: message});
}
this.is = function(v1, v2, message) {
ok(v1 == v2, message);
}
this.info = function(message) {
sendAsyncMessage("browser:test:info", {message: message});
}
this.finish = function() {
sendAsyncMessage("browser:test:finish");
}
/* Start a task that runs some timeline tests in the ordinary way.
*
* @param array tests
* The tests to run. This is an array where each element
* is of the form { desc, searchFor, setup, check }.
*
* desc is the test description, a string.
* searchFor is a string or a function
* If a string, then when a marker with this name is
* found, marker-reading is stopped.
* If a function, then the accumulated marker array is
* passed to it, and marker reading stops when it returns
* true.
* setup is a function that takes the docshell as an argument.
* It should start the test.
* check is a function that takes an array of markers
* as an argument and checks the results of the test.
*/
this.timelineContentTest = function(tests) {
Task.spawn(function*() {
let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
info("Start recording");
docShell.recordProfileTimelineMarkers = true;
for (let {desc, searchFor, setup, check} of tests) {
info("Running test: " + desc);
info("Flushing the previous markers if any");
docShell.popProfileTimelineMarkers();
info("Running the test setup function");
let onMarkers = timelineWaitForMarkers(docShell, searchFor);
setup(docShell);
info("Waiting for new markers on the docShell");
let markers = yield onMarkers;
// Cycle collection markers are non-deterministic, and none of these tests
// expect them to show up.
markers = markers.filter(m => m.name.indexOf("nsCycleCollector") === -1);
info("Running the test check function");
check(markers);
}
info("Stop recording");
docShell.recordProfileTimelineMarkers = false;
finish();
});
}
function timelineWaitForMarkers(docshell, searchFor) {
if (typeof(searchFor) == "string") {
let searchForString = searchFor;
let f = function (markers) {
return markers.some(m => m.name == searchForString);
};
searchFor = f;
}
return new Promise(function(resolve, reject) {
let waitIterationCount = 0;
let maxWaitIterationCount = 10; // Wait for 2sec maximum
let markers = [];
setTimeout(function timeoutHandler() {
let newMarkers = docshell.popProfileTimelineMarkers();
markers = [...markers, ...newMarkers];
if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
resolve(markers);
} else {
setTimeout(timeoutHandler, 200);
waitIterationCount++;
}
}, 200);
});
}

View file

@ -0,0 +1,99 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Helper function for timeline tests. Returns an async task that is
* suitable for use as a particular timeline test.
* @param string frameScriptName
* Base name of the frame script file.
* @param string url
* URL to load.
*/
function makeTimelineTest(frameScriptName, url) {
info("in timelineTest");
return Task.async(function*() {
info("in in timelineTest");
waitForExplicitFinish();
yield timelineTestOpenUrl(url);
const here = "chrome://mochitests/content/browser/docshell/test/browser/";
let mm = gBrowser.selectedBrowser.messageManager;
mm.loadFrameScript(here + "frame-head.js", false);
mm.loadFrameScript(here + frameScriptName, false);
// Set up some listeners so that timeline tests running in the
// content process can forward their results to the main process.
mm.addMessageListener("browser:test:ok", function(message) {
ok(message.data.value, message.data.message);
});
mm.addMessageListener("browser:test:info", function(message) {
info(message.data.message);
});
mm.addMessageListener("browser:test:finish", function(ignore) {
gBrowser.removeCurrentTab();
finish();
});
});
}
/* Open a URL for a timeline test. */
function timelineTestOpenUrl(url) {
window.focus();
let tabSwitchPromise = new Promise((resolve, reject) => {
window.gBrowser.addEventListener("TabSwitchDone", function listener() {
window.gBrowser.removeEventListener("TabSwitchDone", listener);
resolve();
});
});
let loadPromise = new Promise(function(resolve, reject) {
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onload() {
linkedBrowser.removeEventListener("load", onload, true);
resolve(tab);
}, true);
});
return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
}
/**
* Helper function for charset tests. It loads |url| in a new tab,
* runs |check1| in a ContentTask when the page is ready, switches the
* charset to |charset|, and then runs |check2| in a ContentTask when
* the page has finished reloading.
*
* |charset| and |check2| can be omitted, in which case the test
* finishes when |check1| completes.
*/
function runCharsetTest(url, check1, charset, check2) {
waitForExplicitFinish();
BrowserTestUtils.openNewForegroundTab(gBrowser, url, true).then(afterOpen);
function afterOpen() {
if (charset) {
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
BrowserSetForcedCharacterSet(charset);
});
} else {
ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}
}
function afterChangeCharset() {
ContentTask.spawn(gBrowser.selectedBrowser, null, check2).then(() => {
gBrowser.removeCurrentTab();
finish();
});
}
}

View file

@ -0,0 +1,22 @@
const CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
function handleRequest(request, response) {
response.setHeader("Content-Type", "text/plain", false);
if (request.method == "GET") {
response.write(request.queryString);
} else {
var body = new BinaryInputStream(request.bodyInputStream);
var avail;
var bytes = [];
while ((avail = body.available()) > 0)
Array.prototype.push.apply(bytes, body.readByteArray(avail));
var data = String.fromCharCode.apply(null, bytes);
response.bodyOutputStream.write(data, data.length);
}
}

View file

@ -0,0 +1,4 @@
function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, 302, "Moved Permanently");
response.setHeader("Location", "http://example");
}

View file

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/REC-html401-19991224/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<title>Shift_JIS in body and text area</title>
</head>
<body>
<h1>Incorrect meta charset</h1>
<h2>This page is encoded in Shift_JIS, but has an incorrect meta charset
claiming that it is windows-1251</h2>
<p id="testpar">ユニコードは、すべての文字に固有の番号を付与します</p>
<form>
<p>
<textarea id="testtextarea" rows=6 cols=60>ユニコードは、すべての文字に固有の番号を付与します</textarea>
<input id="testinput" type="text" size=60 value="ユニコードは、すべての文字に固有の番号を付与します">
</p>
</form>
<h2>Expected text on load:</h2>
<p>&#x453;&#x2020;&#x453;&#x6A;&#x453;&#x52;&#x403;&#x5B;&#x453;&#x68;&#x201A;&#x41D;&#x403;&#x41;&#x201A;&#xB7;&#x201A;&#x427;&#x201A;&#x414;&#x201A;&#x41C;&#x2022;&#xB6;&#x40B;&#x459;&#x201A;&#x419;&#x40A;&#x415;&#x2014;&#x4C;&#x201A;&#x41C;&#x201D;&#x424;&#x40C;&#x2020;&#x201A;&#x440;&#x2022;&#x74;&#x2014;&#x5E;&#x201A;&#xB5;&#x201A;&#x42C;&#x201A;&#xB7;</p>
<h2>Expected text on resetting the encoding to Shift_JIS:</h2>
<p>&#x30E6;&#x30CB;&#x30B3;&#x30FC;&#x30C9;&#x306F;&#x3001;&#x3059;&#x3079;&#x3066;&#x306E;&#x6587;&#x5B57;&#x306B;&#x56FA;&#x6709;&#x306E;&#x756A;&#x53F7;&#x3092;&#x4ED8;&#x4E0E;&#x3057;&#x307E;&#x3059;</p>
</body>
</html>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"></meta>
<title>markers test</title>
</head>
<body>
<p>Test page</p>
<script>
function do_xhr() {
const theURL = "timelineMarkers-04.html";
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
dump("ReadyState = " + xhr.readyState + "\n");
};
xhr.open("get", theURL, true);
xhr.send();
}
window.addEventListener("dog", do_xhr, true);
function do_promise() {
new Promise(function(resolve, reject) {
console.time("Bob");
window.setTimeout(function() {
resolve(23);
}, 10);
}).then(function (val) {
console.timeEnd("Bob");
});
}
window.addEventListener("promisetest", do_promise, true);
var globalResolver;
function do_promise_script() {
new Promise(function(resolve, reject) {
console.time("Bob");
globalResolver = resolve;
window.setTimeout("globalResolver(23);", 10);
}).then(function (val) {
console.timeEnd("Bob");
});
}
window.addEventListener("promisescript", do_promise_script, true);
</script>
</body>
</html>