This commit is contained in:
Wes Kocher 2016-10-12 14:23:33 -07:00
Родитель e3f99a78e1 f1659f19b4
Коммит 3770ad1b24
124 изменённых файлов: 2265 добавлений и 403 удалений

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

@ -205,6 +205,8 @@
<true/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
<key>LSFileQuarantineEnabled</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>10.9.0</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>

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

@ -379,9 +379,6 @@ pref("browser.search.hiddenOneOffs", "");
pref("browser.search.reset.enabled", true);
pref("browser.usedOnWindows10", false);
pref("browser.usedOnWindows10.introURL", "https://www.mozilla.org/%LOCALE%/firefox/windows-10/welcome/?utm_source=firefox-browser&utm_medium=firefox-browser");
pref("browser.sessionhistory.max_entries", 50);
// Built-in default permissions.

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

@ -6453,7 +6453,7 @@
class="tab-throbber"
role="presentation"
layer="true" />
<xul:image xbl:inherits="src=image,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
<xul:image xbl:inherits="src=image,loadingprincipal=iconLoadingPrincipal,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
anonid="tab-icon-image"
class="tab-icon-image"
validate="never"

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

@ -64,31 +64,31 @@ const PAGECONTENT_TRANSLATED =
"</iframe>" +
"</div></body></html>";
function openSelectPopup(selectPopup, withMouse, selector = "select")
function openSelectPopup(selectPopup, withMouse, selector = "select", win = window)
{
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
if (withMouse) {
return Promise.all([popupShownPromise,
BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, gBrowser.selectedBrowser)]);
BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser)]);
}
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, code: "ArrowDown" });
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, code: "ArrowDown" }, win);
return popupShownPromise;
}
function hideSelectPopup(selectPopup, mode = "enter")
function hideSelectPopup(selectPopup, mode = "enter", win = window)
{
let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
if (mode == "escape") {
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" });
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" }, win);
}
else if (mode == "enter") {
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" });
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" }, win);
}
else if (mode == "click") {
EventUtils.synthesizeMouseAtCenter(selectPopup.lastChild, { });
EventUtils.synthesizeMouseAtCenter(selectPopup.lastChild, { }, win);
}
return popupHiddenPromise;
@ -402,13 +402,11 @@ add_task(function* test_event_order() {
});
});
// This test checks select elements with a large number of options to ensure that
// the popup appears within the browser area.
add_task(function* test_large_popup() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
function* performLargePopupTests(win)
{
let browser = win.gBrowser.selectedBrowser;
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
yield ContentTask.spawn(browser, null, function*() {
let doc = content.document;
let select = doc.getElementById("one");
for (var i = 0; i < 180; i++) {
@ -419,8 +417,8 @@ add_task(function* test_large_popup() {
select.focus();
});
let selectPopup = document.getElementById("ContentSelectDropdown").menupopup;
let browserRect = tab.linkedBrowser.getBoundingClientRect();
let selectPopup = win.document.getElementById("ContentSelectDropdown").menupopup;
let browserRect = browser.getBoundingClientRect();
let positions = [
"margin-top: 300px;",
@ -430,15 +428,15 @@ add_task(function* test_large_popup() {
let position;
while (true) {
yield openSelectPopup(selectPopup, false);
yield openSelectPopup(selectPopup, false, "select", win);
let rect = selectPopup.getBoundingClientRect();
ok(rect.top >= browserRect.top, "Popup top position in within browser area");
ok(rect.bottom <= browserRect.bottom, "Popup bottom position in within browser area");
// Don't check the scroll position for the last step as the popup will be cut off.
if (positions.length == 1) {
let cs = window.getComputedStyle(selectPopup);
if (positions.length > 0) {
let cs = win.getComputedStyle(selectPopup);
let bpBottom = parseFloat(cs.paddingBottom) + parseFloat(cs.borderBottomWidth);
is(selectPopup.childNodes[60].getBoundingClientRect().bottom,
@ -446,24 +444,49 @@ add_task(function* test_large_popup() {
"Popup scroll at correct position " + bpBottom);
}
yield hideSelectPopup(selectPopup);
yield hideSelectPopup(selectPopup, "enter", win);
position = positions.shift();
if (!position) {
break;
}
let contentPainted = BrowserTestUtils.contentPainted(tab.linkedBrowser);
yield ContentTask.spawn(tab.linkedBrowser, position, function*(position) {
let contentPainted = BrowserTestUtils.contentPainted(browser);
yield ContentTask.spawn(browser, position, function*(position) {
let select = content.document.getElementById("one");
select.setAttribute("style", position);
});
yield contentPainted;
}
}
// This test checks select elements with a large number of options to ensure that
// the popup appears within the browser area.
add_task(function* test_large_popup() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
yield* performLargePopupTests(window);
yield BrowserTestUtils.removeTab(tab);
});
// This test checks the same as the previous test but in a new smaller window.
add_task(function* test_large_popup_in_small_window() {
let newwin = yield BrowserTestUtils.openNewBrowserWindow({ width: 400, height: 400 });
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
let browserLoadedPromise = BrowserTestUtils.browserLoaded(newwin.gBrowser.selectedBrowser);
yield BrowserTestUtils.loadURI(newwin.gBrowser.selectedBrowser, pageUrl);
yield browserLoadedPromise;
newwin.gBrowser.selectedBrowser.focus();
yield* performLargePopupTests(newwin);
yield BrowserTestUtils.closeWindow(newwin);
});
// This test checks that a mousemove event is fired correctly at the menu and
// not at the browser, ensuring that any mouse capture has been cleared.
add_task(function* test_mousemove_correcttarget() {

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

@ -4,7 +4,7 @@
pref("startup.homepage_override_url", "");
pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/");
pref("startup.homepage_welcome_url.additional", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/learnmore/");
pref("startup.homepage_welcome_url.additional", "");
// Interval: Time between checks for a new version (in seconds)
pref("app.update.interval", 43200); // 12 hours
// The time interval between the downloading of mar file chunks in the

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

@ -22,7 +22,7 @@ function getIconFile() {
NetUtil.asyncFetch({
uri: "http://www.example.com/browser/browser/components/contextualidentity/test/browser/favicon-normal32.png",
loadUsingSystemPrincipal: true,
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON
}, function(inputStream, status) {
let size = inputStream.available();
gFaviconData = NetUtil.readInputStreamToString(inputStream, size);

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

@ -157,11 +157,6 @@ FirefoxProfileMigrator.prototype._getResourcesInternal = function(sourceProfileD
// session with the "what's new" page:
Services.prefs.setCharPref("browser.startup.homepage_override.mstone", mstone);
Services.prefs.setCharPref("browser.startup.homepage_override.buildID", buildID);
// Also set the Windows 10 pref to avoid the win10 intro page to show up
// on startup.
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
Services.prefs.setBoolPref("browser.usedOnWindows10", true);
}
// It's too early in startup for the pref service to have a profile directory,
// so we have to manually tell it where to save the prefs file.
let newPrefsFile = currentProfileDir.clone();

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

@ -525,22 +525,6 @@ nsBrowserContentHandler.prototype = {
if (overridePage == "about:blank")
overridePage = "";
// Temporary override page for users who are running Firefox on Windows 10 for their first time.
let platformVersion = Services.sysinfo.getProperty("version");
if (AppConstants.platform == "win" &&
Services.vc.compare(platformVersion, "10") == 0 &&
!Services.prefs.getBoolPref("browser.usedOnWindows10")) {
Services.prefs.setBoolPref("browser.usedOnWindows10", true);
let firstUseOnWindows10URL = Services.urlFormatter.formatURLPref("browser.usedOnWindows10.introURL");
if (firstUseOnWindows10URL && firstUseOnWindows10URL.length) {
additionalPage = firstUseOnWindows10URL;
if (override == OVERRIDE_NEW_PROFILE) {
additionalPage += "&utm_content=firstrun";
}
}
}
if (!additionalPage) {
additionalPage = LaterRun.getURL() || "";
}

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

@ -3,6 +3,12 @@ skip-if = buildapp == "mulet"
tags = usercontextid firstpartyisolation originattributes
support-files =
dummy.html
file_favicon.html
file_favicon.png
file_favicon.png^headers^
file_favicon_cache.html
file_favicon_cache.png
file_favicon_thirdParty.html
file_firstPartyBasic.html
file_sharedworker.html
file_sharedworker.js
@ -24,6 +30,8 @@ support-files =
worker_blobify.js
worker_deblobify.js
[browser_favicon_firstParty.js]
[browser_favicon_userContextId.js]
[browser_firstPartyIsolation.js]
[browser_localStorageIsolation.js]
[browser_blobURLIsolation.js]

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

@ -0,0 +1,334 @@
/**
* Bug 1277803 - A test case for testing favicon loading across different first party domains.
*/
const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/PlacesUtils.jsm");
const FIRST_PARTY_ONE = "example.com";
const FIRST_PARTY_TWO = "example.org";
const THIRD_PARTY = "mochi.test:8888";
const TEST_SITE_ONE = "http://" + FIRST_PARTY_ONE;
const TEST_SITE_TWO = "http://" + FIRST_PARTY_TWO;
const THIRD_PARTY_SITE = "http://" + THIRD_PARTY;
const TEST_DIRECTORY = "/browser/browser/components/originattributes/test/browser/";
const TEST_PAGE = TEST_DIRECTORY + "file_favicon.html";
const TEST_THIRD_PARTY_PAGE = TEST_DIRECTORY + "file_favicon_thirdParty.html";
const TEST_CACHE_PAGE = TEST_DIRECTORY + "file_favicon_cache.html";
const FAVICON_URI = TEST_DIRECTORY + "file_favicon.png";
const TEST_FAVICON_CACHE_URI = TEST_DIRECTORY + "file_favicon_cache.png";
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
function clearAllImageCaches() {
let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
.getService(SpecialPowers.Ci.imgITools);
let imageCache = tools.getImgCacheForDocument(window.document);
imageCache.clearCache(true); // true=chrome
imageCache.clearCache(false); // false=content
}
function clearAllPlacesFavicons() {
let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
.getService(Ci.nsIFaviconService);
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
if (aTopic === "places-favicons-expired") {
resolve();
Services.obs.removeObserver(observer, "places-favicons-expired", false);
}
}
};
Services.obs.addObserver(observer, "places-favicons-expired", false);
faviconService.expireAllFavicons();
});
}
function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
let faviconReqXUL = false;
let faviconReqPlaces = false;
let expectedPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(aPageURI, { firstPartyDomain: aFirstPartyDomain });
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
// Make sure that the topic is 'http-on-modify-request'.
if (aTopic === "http-on-modify-request") {
// We check the firstPartyDomain for the originAttributes of the loading
// channel. All requests for the favicon should contain the correct
// firstPartyDomain. There are two requests for a favicon loading, one
// from the Places library and one from the XUL image. The difference
// of them is the loading principal. The Places will use the content
// principal and the XUL image will use the system principal.
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
let loadingPrincipal = reqLoadInfo.loadingPrincipal;
let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
// Make sure this is a favicon request.
if (!httpChannel.URI.spec.endsWith(FAVICON_URI)) {
return;
}
// Check the first party domain.
is(reqLoadInfo.originAttributes.firstPartyDomain, aFirstPartyDomain,
"The loadInfo has correct first party domain");
if (loadingPrincipal.equals(systemPrincipal)) {
faviconReqXUL = true;
ok(triggeringPrincipal.equals(expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
faviconReqPlaces = true;
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
is(faviconCookie, aExpectedCookie, "The cookie of the favicon loading is correct.");
} else {
ok(false, "Received unexpected topic: ", aTopic);
}
if (faviconReqXUL && faviconReqPlaces) {
Services.obs.removeObserver(observer, "http-on-modify-request", false);
resolve();
}
}
};
Services.obs.addObserver(observer, "http-on-modify-request", false);
});
}
function waitOnFaviconResponse(aFaviconURL) {
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
if (aTopic === "http-on-examine-response" ||
aTopic === "http-on-examine-cached-response") {
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let loadInfo = httpChannel.loadInfo;
if (httpChannel.URI.spec !== aFaviconURL) {
return;
}
let result = {
topic: aTopic,
firstPartyDomain: loadInfo.originAttributes.firstPartyDomain
};
resolve(result);
Services.obs.removeObserver(observer, "http-on-examine-response", false);
Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
}
}
};
Services.obs.addObserver(observer, "http-on-examine-response", false);
Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
});
}
function waitOnFaviconLoaded(aFaviconURL) {
return new Promise(resolve => {
let observer = {
onPageChanged(uri, attr, value, id) {
if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
value === aFaviconURL) {
resolve();
PlacesUtils.history.removeObserver(observer, false);
}
},
};
PlacesUtils.history.addObserver(observer, false);
});
}
function* openTab(aURL) {
let tab = gBrowser.addTab(aURL);
// Select tab and make sure its browser is focused.
gBrowser.selectedTab = tab;
tab.ownerGlobal.focus();
let browser = gBrowser.getBrowserForTab(tab);
yield BrowserTestUtils.browserLoaded(browser);
return {tab, browser};
}
function* assignCookiesUnderFirstParty(aURL, aFirstParty, aCookieValue) {
// Open a tab under the given aFirstParty, and this tab will have an
// iframe which loads the aURL.
let tabInfo = yield openTabInFirstParty(aURL, aFirstParty);
// Add cookies into the iframe.
yield ContentTask.spawn(tabInfo.browser, aCookieValue, function* (value) {
content.document.cookie = value;
});
yield BrowserTestUtils.removeTab(tabInfo.tab);
}
function* generateCookies(aThirdParty) {
// we generate two different cookies for two first party domains.
let cookies = [];
cookies.push(Math.random().toString());
cookies.push(Math.random().toString());
let firstSiteURL;
let secondSiteURL;
if (aThirdParty) {
// Add cookies into the third party site with different first party domain.
firstSiteURL = THIRD_PARTY_SITE;
secondSiteURL = THIRD_PARTY_SITE;
} else {
// Add cookies into sites.
firstSiteURL = TEST_SITE_ONE;
secondSiteURL = TEST_SITE_TWO;
}
yield assignCookiesUnderFirstParty(firstSiteURL, TEST_SITE_ONE, cookies[0]);
yield assignCookiesUnderFirstParty(secondSiteURL, TEST_SITE_TWO, cookies[1]);
return cookies;
}
function* doTest(aTestPage, aExpectedCookies, aFaviconURL) {
let firstPageURI = makeURI(TEST_SITE_ONE + aTestPage);
let secondPageURI = makeURI(TEST_SITE_TWO + aTestPage);
// Start to observer the event of that favicon has been fully loaded.
let promiseFaviconLoaded = waitOnFaviconLoaded(aFaviconURL);
// Open the tab for the first site.
let tabInfo = yield openTab(TEST_SITE_ONE + aTestPage);
// Waiting until favicon requests are all made.
yield observeFavicon(FIRST_PARTY_ONE, aExpectedCookies[0], firstPageURI);
// Waiting until favicon loaded.
yield promiseFaviconLoaded;
// Close the tab.
yield BrowserTestUtils.removeTab(tabInfo.tab);
// Open the tab for the second site.
tabInfo = yield openTab(TEST_SITE_TWO + aTestPage);
// Waiting until favicon requests are all made.
yield observeFavicon(FIRST_PARTY_TWO, aExpectedCookies[1], secondPageURI);
yield BrowserTestUtils.removeTab(tabInfo.tab);
}
add_task(function* setup() {
// Make sure first party isolation is enabled.
yield SpecialPowers.pushPrefEnv({"set": [
["privacy.firstparty.isolate", true]
]});
});
// A clean up function to prevent affecting other tests.
registerCleanupFunction(() => {
// Clear all cookies.
let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
cookieMgr.removeAll();
// Clear all image caches and network caches.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
});
add_task(function* test_favicon_firstParty() {
for (let testThirdParty of [false, true]) {
// Clear all image caches and network caches before running the test.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Clear Places favicon caches.
yield clearAllPlacesFavicons();
let cookies = yield generateCookies(testThirdParty);
if (testThirdParty) {
yield doTest(TEST_THIRD_PARTY_PAGE, cookies, THIRD_PARTY_SITE + FAVICON_URI);
} else {
yield doTest(TEST_PAGE, cookies, TEST_SITE_ONE + FAVICON_URI);
}
}
});
add_task(function* test_favicon_cache_firstParty() {
// Clear all image caches and network caches before running the test.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Open the tab for the first site.
let tabInfoA = yield openTab(TEST_SITE_ONE + TEST_CACHE_PAGE);
// Start to observer the event of that favicon has been fully loaded and cached.
let promiseForFaviconLoaded = waitOnFaviconLoaded(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
// Wait for the favicon response of the first tab.
let response = yield waitOnFaviconResponse(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
// Make sure the favicon is loaded through the network and its first party domain is correct.
is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network.");
is(response.firstPartyDomain, FIRST_PARTY_ONE, "We should only observe the network response for the first first party.");
// Waiting until the favicon has been loaded and cached.
yield promiseForFaviconLoaded;
// Open the tab again for checking the image cache is working correctly.
let tabInfoB = yield openTab(TEST_SITE_ONE + TEST_CACHE_PAGE);
// Start to observe the favicon response, the second tab actually will not
// make any network request since the favicon will be loaded by the cache for
// both Places and XUL image. So here, we are going to observe the favicon
// response for the third tab which opens with the second first party.
let promiseForFaviconResponse = waitOnFaviconResponse(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
// Open the tab for the second site.
let tabInfoC = yield openTab(TEST_SITE_TWO + TEST_CACHE_PAGE);
// Wait for the favicon response. In this case, we suppose to catch the
// response for the third tab but not the second tab since it will not
// go through the network.
response = yield promiseForFaviconResponse;
// Check that the favicon response has came from the network and it has the
// correct first party domain.
is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network again.");
is(response.firstPartyDomain, FIRST_PARTY_TWO, "We should only observe the network response for the second first party.");
yield BrowserTestUtils.removeTab(tabInfoA.tab);
yield BrowserTestUtils.removeTab(tabInfoB.tab);
yield BrowserTestUtils.removeTab(tabInfoC.tab);
});

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

@ -0,0 +1,250 @@
/**
* Bug 1277803 - A test caes for testing favicon loading across different userContextId.
*/
const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
const TEST_SITE = "http://mochi.test:8888";
const TEST_PAGE = TEST_SITE + "/browser/browser/components/originattributes/" +
"test/browser/file_favicon.html";
const FAVICON_URI = TEST_SITE + "/browser/browser/components/originattributes/" +
"test/browser/file_favicon.png";
const TEST_THIRD_PARTY_PAGE = "http://example.com/browser/browser/components/" +
"originattributes/test/browser/file_favicon_thirdParty.html";
const USER_CONTEXT_ID_PERSONAL = 1;
const USER_CONTEXT_ID_WORK = 2;
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
function clearAllImageCaches() {
var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
.getService(SpecialPowers.Ci.imgITools);
var imageCache = tools.getImgCacheForDocument(window.document);
imageCache.clearCache(true); // true=chrome
imageCache.clearCache(false); // false=content
}
function clearAllPlacesFavicons() {
let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
.getService(Ci.nsIFaviconService);
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
if (aTopic === "places-favicons-expired") {
resolve();
Services.obs.removeObserver(observer, "places-favicons-expired", false);
}
}
};
Services.obs.addObserver(observer, "places-favicons-expired", false);
faviconService.expireAllFavicons();
});
}
function FaviconObserver(aUserContextId, aExpectedCookie, aPageURI) {
this.reset(aUserContextId, aExpectedCookie, aPageURI);
}
FaviconObserver.prototype = {
observe(aSubject, aTopic, aData) {
// Make sure that the topic is 'http-on-modify-request'.
if (aTopic === "http-on-modify-request") {
// We check the userContextId for the originAttributes of the loading
// channel. All requests for the favicon should contain the correct
// userContextId. There are two requests for a favicon loading, one
// from the Places library and one from the XUL image. The difference
// of them is the loading principal. The Places will use the content
// principal and the XUL image will use the system principal.
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
let loadingPrincipal;
let triggeringPrincipal;
// Make sure this is a favicon request.
if (httpChannel.URI.spec !== FAVICON_URI) {
return;
}
if (reqLoadInfo) {
loadingPrincipal = reqLoadInfo.loadingPrincipal;
triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
}
// Check the userContextId.
is(reqLoadInfo.originAttributes.userContextId, this._curUserContextId,
"The loadInfo has correct userContextId");
if (loadingPrincipal.equals(systemPrincipal)) {
this._faviconReqXUL = true;
ok(triggeringPrincipal.equals(this._expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
this._faviconReqPlaces = true;
ok(loadingPrincipal.equals(this._expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
is(faviconCookie, this._expectedCookie, "The cookie of the favicon loading is correct.");
} else {
ok(false, "Received unexpected topic: ", aTopic);
}
if (this._faviconReqXUL && this._faviconReqPlaces) {
this._faviconLoaded.resolve();
}
},
reset(aUserContextId, aExpectedCookie, aPageURI) {
this._curUserContextId = aUserContextId;
this._expectedCookie = aExpectedCookie;
this._expectedPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(aPageURI, { userContextId: aUserContextId });
this._faviconReqXUL = false;
this._faviconReqPlaces = false;
this._faviconLoaded = new Promise.defer();
},
get promise() {
return this._faviconLoaded.promise;
}
};
function waitOnFaviconLoaded(aFaviconURL) {
return new Promise(resolve => {
let observer = {
onPageChanged(uri, attr, value, id) {
if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
value === aFaviconURL) {
resolve();
PlacesUtils.history.removeObserver(observer, false);
}
},
};
PlacesUtils.history.addObserver(observer, false);
});
}
function* generateCookies() {
// we generate two different cookies for two userContextIds.
let cookies = [];
cookies.push(Math.random().toString());
cookies.push(Math.random().toString());
// Then, we add cookies into the site for 'personal' and 'work'.
let tabInfoA = yield openTabInUserContext(TEST_SITE, USER_CONTEXT_ID_PERSONAL);
let tabInfoB = yield openTabInUserContext(TEST_SITE, USER_CONTEXT_ID_WORK);
yield ContentTask.spawn(tabInfoA.browser, cookies[0], function* (value) {
content.document.cookie = value;
});
yield ContentTask.spawn(tabInfoB.browser, cookies[1], function* (value) {
content.document.cookie = value;
});
yield BrowserTestUtils.removeTab(tabInfoA.tab);
yield BrowserTestUtils.removeTab(tabInfoB.tab);
return cookies;
}
function* doTest(aTestPage) {
let cookies = yield generateCookies();
let pageURI = makeURI(aTestPage);
// Create the observer object for observing request channels of the personal
// container.
let observer = new FaviconObserver(USER_CONTEXT_ID_PERSONAL, cookies[0], pageURI);
Services.obs.addObserver(observer, "http-on-modify-request", false);
// Open the tab with the personal container.
let tabInfo = yield openTabInUserContext(aTestPage, USER_CONTEXT_ID_PERSONAL);
// Waiting for favicon requests are all made.
yield observer.promise;
// Waiting for favicon loaded.
yield waitOnFaviconLoaded(FAVICON_URI);
// Close the tab.
yield BrowserTestUtils.removeTab(tabInfo.tab);
// Reset the observer for observing requests for the work container.
observer.reset(USER_CONTEXT_ID_WORK, cookies[1], pageURI);
tabInfo = yield openTabInUserContext(aTestPage, USER_CONTEXT_ID_WORK);
// Waiting for favicon requests are all made.
yield observer.promise;
Services.obs.removeObserver(observer, "http-on-modify-request", false);
yield BrowserTestUtils.removeTab(tabInfo.tab);
}
add_task(function* setup() {
// Make sure userContext is enabled.
yield SpecialPowers.pushPrefEnv({"set": [
["privacy.userContext.enabled", true]
]});
});
// A clean up function to prevent affecting other tests.
registerCleanupFunction(() => {
// Clear all cookies.
let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
cookieMgr.removeAll();
// Clear all image caches and network caches.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Clear Places favicon caches.
clearAllPlacesFavicons();
});
add_task(function* test_favicon_userContextId() {
// Clear all image caches before running the test.
clearAllImageCaches();
// Clear all network caches.
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Clear Places favicon caches.
yield clearAllPlacesFavicons();
yield doTest(TEST_PAGE);
});
add_task(function* test_thirdPartyFavicon_userContextId() {
// Clear all image caches before running the test.
clearAllImageCaches();
// Clear all network caches.
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Clear Places favicon caches.
yield clearAllPlacesFavicons();
yield doTest(TEST_THIRD_PARTY_PAGE);
});

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<title>Favicon Test for originAttributes</title>
<link rel="icon" type="image/png" href="file_favicon.png" />
</head>
<body>
Favicon!!
</body>
</html>

Двоичные данные
browser/components/originattributes/test/browser/file_favicon.png Normal file

Двоичный файл не отображается.

После

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

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

@ -0,0 +1 @@
Cache-Control: no-cache

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<title>Favicon Test for originAttributes</title>
<link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/file_favicon_cache.png" />
</head>
<body>
Third Party Favicon!!
</body>
</html>

Двоичный файл не отображается.

После

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

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<title>Favicon Test for originAttributes</title>
<link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/file_favicon.png" />
</head>
<body>
Third Party Favicon!!
</body>
</html>

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

@ -230,9 +230,9 @@
<label id="fxaDisplayName" hidden="true"/>
<label id="fxaEmailAddress1"/>
<hbox class="fxaAccountBoxButtons">
<button id="fxaUnlinkButton" label="&disconnect.label;" accesskey="&disconnect.label.accesskey;"/>
<button id="fxaUnlinkButton" label="&disconnect.label;" accesskey="&disconnect.accesskey;"/>
<html:a id="verifiedManage" target="_blank"
accesskey="&verifiedManage.label.accesskey;"
accesskey="&verifiedManage.accesskey;"
onkeypress="gSyncPane.openManageFirefoxAccount(event);"><!--
-->&verifiedManage.label;</html:a>
</hbox>
@ -254,8 +254,8 @@
</description>
</hbox>
<hbox class="fxaAccountBoxButtons">
<button id="verifyFxaAccount" accesskey="&verify.label.accesskey;">&verify.label;</button>
<button id="unverifiedUnlinkFxaAccount" accesskey="&forget.label.accesskey;">&forget.label;</button>
<button id="verifyFxaAccount" accesskey="&verify.accesskey;">&verify.label;</button>
<button id="unverifiedUnlinkFxaAccount" accesskey="&forget.accesskey;">&forget.label;</button>
</hbox>
</vbox>
</hbox>
@ -275,8 +275,8 @@
</description>
</hbox>
<hbox class="fxaAccountBoxButtons">
<button id="rejectReSignIn" accessky="&signIn.label.accesskey;">&signIn.label;</button>
<button id="rejectUnlinkFxaAccount" accesskey="&rejectUnlinkFxaAccount.forget.label.accesskey;">&forget.label;</button>
<button id="rejectReSignIn" accessky="&signIn.accesskey;">&signIn.label;</button>
<button id="rejectUnlinkFxaAccount" accesskey="&forget.accesskey;">&forget.label;</button>
</hbox>
</vbox>
</hbox>
@ -326,14 +326,14 @@
<hbox>
<button id="fxaChangeDeviceName"
label="&changeSyncDeviceName.label;"
accesskey="&changeSyncDeviceName.label.accesskey;"/>
accesskey="&changeSyncDeviceName.accesskey;"/>
<button id="fxaCancelChangeDeviceName"
label="&cancelChangeSyncDeviceName.label;"
accesskey="&cancelChangeSyncDeviceName.label.accesskey;"
accesskey="&cancelChangeSyncDeviceName.accesskey;"
hidden="true"/>
<button id="fxaSaveChangeDeviceName"
label="&saveChangeSyncDeviceName.label;"
accesskey="&saveChangeSyncDeviceName.label.accesskey;"
accesskey="&saveChangeSyncDeviceName.accesskey;"
hidden="true"/>
</hbox>
</hbox>

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

@ -15,6 +15,9 @@ support-files =
popup.html
title.sjs
empty_file.html
file_favicon.html
file_favicon.png
file_favicon.png^headers^
[browser_privatebrowsing_DownloadLastDirWithCPS.js]
[browser_privatebrowsing_about.js]
@ -29,6 +32,7 @@ tags = trackingprotection
[browser_privatebrowsing_downloadLastDir.js]
[browser_privatebrowsing_downloadLastDir_c.js]
[browser_privatebrowsing_downloadLastDir_toggle.js]
[browser_privatebrowsing_favicon.js]
[browser_privatebrowsing_geoprompt.js]
[browser_privatebrowsing_lastpbcontextexited.js]
[browser_privatebrowsing_localStorage.js]

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

@ -0,0 +1,290 @@
/* 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/. */
// This test make sure that the favicon of the private browsing is isolated.
const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
const TEST_SITE = "http://mochi.test:8888";
const TEST_DIRECTORY = "/browser/browser/components/privatebrowsing/test/browser/";
const TEST_PAGE = TEST_SITE + TEST_DIRECTORY + "file_favicon.html";
const FAVICON_URI = TEST_SITE + TEST_DIRECTORY + "file_favicon.png";
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
function clearAllImageCaches() {
let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
.getService(SpecialPowers.Ci.imgITools);
let imageCache = tools.getImgCacheForDocument(window.document);
imageCache.clearCache(true); // true=chrome
imageCache.clearCache(false); // false=content
}
function clearAllPlacesFavicons() {
let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
.getService(Ci.nsIFaviconService);
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
if (aTopic === "places-favicons-expired") {
resolve();
Services.obs.removeObserver(observer, "places-favicons-expired", false);
}
}
};
Services.obs.addObserver(observer, "places-favicons-expired", false);
faviconService.expireAllFavicons();
});
}
function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
let faviconReqXUL = false;
let faviconReqPlaces = false;
let attr = {};
if (aIsPrivate) {
attr.privateBrowsingId = 1;
}
let expectedPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(aPageURI, attr);
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
// Make sure that the topic is 'http-on-modify-request'.
if (aTopic === "http-on-modify-request") {
// We check the privateBrowsingId for the originAttributes of the loading
// channel. All requests for the favicon should contain the correct
// privateBrowsingId. There are two requests for a favicon loading, one
// from the Places library and one from the XUL image. The difference
// of them is the loading principal. The Places will use the content
// principal and the XUL image will use the system principal.
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
let loadingPrincipal = reqLoadInfo.loadingPrincipal;
let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
// Make sure this is a favicon request.
if (httpChannel.URI.spec !== FAVICON_URI) {
return;
}
// Check the privateBrowsingId.
if (aIsPrivate) {
is(reqLoadInfo.originAttributes.privateBrowsingId, 1, "The loadInfo has correct privateBrowsingId");
} else {
is(reqLoadInfo.originAttributes.privateBrowsingId, 0, "The loadInfo has correct privateBrowsingId");
}
if (loadingPrincipal.equals(systemPrincipal)) {
faviconReqXUL = true;
ok(triggeringPrincipal.equals(expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
faviconReqPlaces = true;
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
is(faviconCookie, aExpectedCookie, "The cookie of the favicon loading is correct.");
} else {
ok(false, "Received unexpected topic: ", aTopic);
}
if (faviconReqXUL && faviconReqPlaces) {
resolve();
Services.obs.removeObserver(observer, "http-on-modify-request", false);
}
}
};
Services.obs.addObserver(observer, "http-on-modify-request", false);
});
}
function waitOnFaviconResponse(aFaviconURL) {
return new Promise(resolve => {
let observer = {
observe(aSubject, aTopic, aData) {
if (aTopic === "http-on-examine-response" ||
aTopic === "http-on-examine-cached-response") {
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let loadInfo = httpChannel.loadInfo;
if (httpChannel.URI.spec !== aFaviconURL) {
return;
}
let result = {
topic: aTopic,
privateBrowsingId: loadInfo.originAttributes.privateBrowsingId
};
resolve(result);
Services.obs.removeObserver(observer, "http-on-examine-response", false);
Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
}
}
};
Services.obs.addObserver(observer, "http-on-examine-response", false);
Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
});
}
function waitOnFaviconLoaded(aFaviconURL) {
return new Promise(resolve => {
let observer = {
onPageChanged(uri, attr, value, id) {
if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
value === aFaviconURL) {
resolve();
PlacesUtils.history.removeObserver(observer, false);
}
},
};
PlacesUtils.history.addObserver(observer, false);
});
}
function* assignCookies(aBrowser, aURL, aCookieValue){
let tabInfo = yield openTab(aBrowser, aURL);
yield ContentTask.spawn(tabInfo.browser, aCookieValue, function* (value) {
content.document.cookie = value;
});
yield BrowserTestUtils.removeTab(tabInfo.tab);
}
function* openTab(aBrowser, aURL) {
let tab = aBrowser.addTab(aURL);
// Select tab and make sure its browser is focused.
aBrowser.selectedTab = tab;
tab.ownerGlobal.focus();
let browser = aBrowser.getBrowserForTab(tab);
yield BrowserTestUtils.browserLoaded(browser);
return {tab, browser};
}
// A clean up function to prevent affecting other tests.
registerCleanupFunction(() => {
// Clear all cookies.
let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
cookieMgr.removeAll();
// Clear all image caches and network caches.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
});
add_task(function* test_favicon_privateBrowsing() {
// Clear all image caches before running the test.
clearAllImageCaches();
// Clear all favicons in Places.
yield clearAllPlacesFavicons();
// Create a private browsing window.
let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
let pageURI = makeURI(TEST_PAGE);
// Generate two random cookies for non-private window and private window
// respectively.
let cookies = [];
cookies.push(Math.random().toString());
cookies.push(Math.random().toString());
// Open a tab in private window and add a cookie into it.
yield assignCookies(privateWindow.gBrowser, TEST_SITE, cookies[0]);
// Open a tab in non-private window and add a cookie into it.
yield assignCookies(gBrowser, TEST_SITE, cookies[1]);
// Add the observer earlier in case we don't capture events in time.
let promiseObserveFavicon = observeFavicon(true, cookies[0], pageURI);
// Open a tab for the private window.
let tabInfo = yield openTab(privateWindow.gBrowser, TEST_PAGE);
// Waiting until favicon requests are all made.
yield promiseObserveFavicon;
// Close the tab.
yield BrowserTestUtils.removeTab(tabInfo.tab);
// Add the observer earlier in case we don't capture events in time.
promiseObserveFavicon = observeFavicon(false, cookies[1], pageURI);
// Open a tab for the non-private window.
tabInfo = yield openTab(gBrowser, TEST_PAGE);
// Waiting until favicon requests are all made.
yield promiseObserveFavicon;
// Close the tab.
yield BrowserTestUtils.removeTab(tabInfo.tab);
yield BrowserTestUtils.closeWindow(privateWindow);
});
add_task(function* test_favicon_cache_privateBrowsing() {
// Clear all image cahces and network cache before running the test.
clearAllImageCaches();
let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
networkCache.clear();
// Clear all favicons in Places.
yield clearAllPlacesFavicons();
// Create a private browsing window.
let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
// Add an observer for making sure the favicon has been loaded and cached.
let promiseFaviconLoaded = waitOnFaviconLoaded(FAVICON_URI);
// Open a tab for the non-private window.
let tabInfoNonPrivate = yield openTab(gBrowser, TEST_PAGE);
let response = yield waitOnFaviconResponse(FAVICON_URI);
yield promiseFaviconLoaded;
// Check that the favicon response has come from the network and it has the
// correct privateBrowsingId.
is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network.");
is(response.privateBrowsingId, 0, "We should observe the network response for the non-private tab.");
// Open a tab for the private window.
let tabInfoPrivate = yield openTab(privateWindow.gBrowser, TEST_PAGE);
// Wait for the favicon response of the private tab.
response = yield waitOnFaviconResponse(FAVICON_URI);
// Make sure the favicon is loaded through the network and its privateBrowsingId is correct.
is(response.topic, "http-on-examine-response", "The favicon image should be loaded through the network again.");
is(response.privateBrowsingId, 1, "We should observe the network response for the private tab.");
yield BrowserTestUtils.removeTab(tabInfoPrivate.tab);
yield BrowserTestUtils.removeTab(tabInfoNonPrivate.tab);
yield BrowserTestUtils.closeWindow(privateWindow);
});

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<title>Favicon Test for originAttributes</title>
<link rel="icon" type="image/png" href="file_favicon.png" />
</head>
<body>
Favicon!!
</body>
</html>

Двоичные данные
browser/components/privatebrowsing/test/browser/file_favicon.png Normal file

Двоичный файл не отображается.

После

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

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

@ -0,0 +1 @@
Cache-Control: no-cache

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

@ -40,11 +40,11 @@
<!ENTITY syncDeviceName.label "Device Name:">
<!ENTITY fxaSyncDeviceName.label "Device Name">
<!ENTITY changeSyncDeviceName.label "Change Device Name…">
<!ENTITY changeSyncDeviceName.label.accesskey "h">
<!ENTITY changeSyncDeviceName.accesskey "h">
<!ENTITY cancelChangeSyncDeviceName.label "Cancel">
<!ENTITY cancelChangeSyncDeviceName.label.accesskey "n">
<!ENTITY cancelChangeSyncDeviceName.accesskey "n">
<!ENTITY saveChangeSyncDeviceName.label "Save">
<!ENTITY saveChangeSyncDeviceName.label.accesskey "v">
<!ENTITY saveChangeSyncDeviceName.accesskey "v">
<!ENTITY unlinkDevice.label "Unlink This Device">
<!-- Footer stuff -->
@ -73,17 +73,16 @@ both, to better adapt this sentence to their language.
<!ENTITY notSignedIn.label "You are not signed in.">
<!ENTITY signIn.label "Sign in">
<!ENTITY signIn.label.accesskey "g">
<!ENTITY signIn.accesskey "g">
<!ENTITY profilePicture.tooltip "Change profile picture">
<!ENTITY verifiedManage.label "Manage Account">
<!ENTITY verifiedManage.label.accesskey "o">
<!ENTITY verifiedManage.accesskey "o">
<!ENTITY disconnect.label "Disconnect…">
<!ENTITY disconnect.label.accesskey "D">
<!ENTITY disconnect.accesskey "D">
<!ENTITY verify.label "Verify Email">
<!ENTITY verify.label.accesskey "V">
<!ENTITY verify.accesskey "V">
<!ENTITY forget.label "Forget this Email">
<!ENTITY forget.label.accesskey "F">
<!ENTITY rejectUnlinkFxaAccount.forget.label.accesskey "e">
<!ENTITY forget.accesskey "F">
<!ENTITY welcome.description "Access your tabs, bookmarks, passwords and more wherever you use &brandShortName;.">
<!ENTITY welcome.signIn.label "Sign In">

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

@ -108,7 +108,7 @@ function loadRecordingFromFile(file) {
// If the recording has no label, set it to be the
// filename without its extension.
if (!recordingData.label) {
recordingData.label = file.leafName.replace(/\..+$/, "");
recordingData.label = file.leafName.replace(/\.[^.]+$/, "");
}
resolve(recordingData);

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

@ -1078,8 +1078,7 @@ EventSource::DispatchAllMessageEvents()
// create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action
RefPtr<MessageEvent> event =
NS_NewDOMMessageEvent(this, nullptr, nullptr);
RefPtr<MessageEvent> event = new MessageEvent(this, nullptr, nullptr);
event->InitMessageEvent(nullptr, message->mEventName, false, false, jsData,
mOrigin, message->mLastEventID, nullptr, nullptr);

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

@ -2005,7 +2005,7 @@ WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
// create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action
RefPtr<MessageEvent> event = NS_NewDOMMessageEvent(this, nullptr, nullptr);
RefPtr<MessageEvent> event = new MessageEvent(this, nullptr, nullptr);
event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false, false,
jsData, mImpl->mUTF16Origin, EmptyString(), nullptr,

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

@ -131,6 +131,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_IMAGE );
CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_IMAGE_FAVICON );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
default:

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

@ -8418,6 +8418,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
return nsIContentPolicy::TYPE_IMAGE;
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:

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

@ -402,7 +402,7 @@ nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
jsData.setString(jsString);
}
RefPtr<MessageEvent> event = NS_NewDOMMessageEvent(this, nullptr, nullptr);
RefPtr<MessageEvent> event = new MessageEvent(this, nullptr, nullptr);
event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false, false,
jsData, mOrigin, EmptyString(), nullptr, nullptr);

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

@ -11413,9 +11413,18 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
return;
}
// Per spec only HTML, <svg>, and <math> should be allowed, but
// we also need to allow XUL elements right now.
Element* elem = aRequest->GetElement();
if (!elem->IsHTMLElement() && !elem->IsXULElement() &&
!elem->IsSVGElement(nsGkAtoms::svg) &&
!elem->IsMathMLElement(nsGkAtoms::math)) {
DispatchFullscreenError("FullscreenDeniedNotHTMLSVGOrMathML");
return;
}
// We don't need to check element ready before this point, because
// if we called ApplyFullscreen, it would check that for us.
Element* elem = aRequest->GetElement();
if (!FullscreenElementReadyCheck(elem, aRequest->mIsCallerChrome)) {
return;
}

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

@ -557,6 +557,7 @@ GK_ATOM(listing, "listing")
GK_ATOM(listitem, "listitem")
GK_ATOM(listrows, "listrows")
GK_ATOM(load, "load")
GK_ATOM(loadingprincipal, "loadingprincipal")
GK_ATOM(localedir, "localedir")
GK_ATOM(localName, "local-name")
GK_ATOM(longdesc, "longdesc")

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

@ -321,6 +321,14 @@ interface nsIContentPolicyBase : nsISupports
*/
const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40;
/**
* Indicates an internal constant for favicon.
*
* This will be mapped to TYPE_IMAGE before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_IMAGE_FAVICON = 41;
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, the static_assert in dom/cache/DBSchema.cpp,

3
dom/cache/DBSchema.cpp поставляемый
Просмотреть файл

@ -292,7 +292,8 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40,
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON == 41,
"nsContentPolicyType values are as expected");
namespace {

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

@ -995,7 +995,8 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
}
if (aEventType.LowerCaseEqualsLiteral("messageevent")) {
LOG_EVENT_CREATION(MESSAGEEVENT);
return NS_NewDOMMessageEvent(aOwner, aPresContext, nullptr);
RefPtr<Event> event = new MessageEvent(aOwner, aPresContext, nullptr);
return event.forget();
}
if (aEventType.LowerCaseEqualsLiteral("notifypaintevent")) {
LOG_EVENT_CREATION(NOTIFYPAINTEVENT);

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

@ -205,15 +205,3 @@ MessageEvent::SetSource(mozilla::dom::MessagePort* aPort)
} // namespace dom
} // namespace mozilla
using namespace mozilla;
using namespace mozilla::dom;
already_AddRefed<MessageEvent>
NS_NewDOMMessageEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetEvent* aEvent)
{
RefPtr<MessageEvent> it = new MessageEvent(aOwner, aPresContext, aEvent);
return it.forget();
}

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

@ -97,9 +97,4 @@ private:
} // namespace dom
} // namespace mozilla
already_AddRefed<mozilla::dom::MessageEvent>
NS_NewDOMMessageEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
mozilla::WidgetEvent* aEvent);
#endif // mozilla_dom_MessageEvent_h_

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

@ -181,6 +181,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
break;
case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
context = RequestContext::Image;
break;
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:

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

@ -45,7 +45,7 @@ namespace dom {
* frame | TYPE_INTERNAL_FRAME
* hyperlink |
* iframe | TYPE_INTERNAL_IFRAME
* image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD
* image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD, TYPE_INTERNAL_IMAGE_FAVICON
* imageset | TYPE_IMAGESET
* import | Not supported by Gecko
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER

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

@ -211,7 +211,9 @@ const Decimal HTMLInputElement::kStepScaleFactorDate = Decimal(86400000);
const Decimal HTMLInputElement::kStepScaleFactorNumberRange = Decimal(1);
const Decimal HTMLInputElement::kStepScaleFactorTime = Decimal(1000);
const Decimal HTMLInputElement::kStepScaleFactorMonth = Decimal(1);
const Decimal HTMLInputElement::kStepScaleFactorWeek = Decimal(7 * 86400000);
const Decimal HTMLInputElement::kDefaultStepBase = Decimal(0);
const Decimal HTMLInputElement::kDefaultStepBaseWeek = Decimal(-259200000);
const Decimal HTMLInputElement::kDefaultStep = Decimal(1);
const Decimal HTMLInputElement::kDefaultStepTime = Decimal(60);
const Decimal HTMLInputElement::kStepAny = Decimal(0);
@ -2381,6 +2383,7 @@ HTMLInputElement::GetStepBase() const
mType == NS_FORM_INPUT_DATE ||
mType == NS_FORM_INPUT_TIME ||
mType == NS_FORM_INPUT_MONTH ||
mType == NS_FORM_INPUT_WEEK ||
mType == NS_FORM_INPUT_RANGE,
"Check that kDefaultStepBase is correct for this new type");
@ -2401,6 +2404,10 @@ HTMLInputElement::GetStepBase() const
return stepBase;
}
if (mType == NS_FORM_INPUT_WEEK) {
return kDefaultStepBaseWeek;
}
return kDefaultStepBase;
}
@ -7353,7 +7360,8 @@ HTMLInputElement::GetStep() const
}
// For input type=date, we round the step value to have a rounded day.
if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_MONTH) {
if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_MONTH ||
mType == NS_FORM_INPUT_WEEK) {
step = std::max(step.round(), Decimal(1));
}
@ -8489,6 +8497,8 @@ HTMLInputElement::GetStepScaleFactor() const
return kStepScaleFactorTime;
case NS_FORM_INPUT_MONTH:
return kStepScaleFactorMonth;
case NS_FORM_INPUT_WEEK:
return kStepScaleFactorWeek;
default:
MOZ_ASSERT(false, "Unrecognized input type");
return Decimal::nan();
@ -8503,6 +8513,7 @@ HTMLInputElement::GetDefaultStep() const
switch (mType) {
case NS_FORM_INPUT_DATE:
case NS_FORM_INPUT_MONTH:
case NS_FORM_INPUT_WEEK:
case NS_FORM_INPUT_NUMBER:
case NS_FORM_INPUT_RANGE:
return kDefaultStep;

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

@ -1053,11 +1053,7 @@ protected:
/**
* Returns if the step attribute apply for the current type.
*/
bool DoesStepApply() const
{
// TODO: this is temporary until bug 888316 is fixed.
return DoesMinMaxApply() && mType != NS_FORM_INPUT_WEEK;
}
bool DoesStepApply() const { return DoesMinMaxApply(); }
/**
* Returns if stepDown and stepUp methods apply for the current type.
@ -1507,9 +1503,13 @@ protected:
static const Decimal kStepScaleFactorNumberRange;
static const Decimal kStepScaleFactorTime;
static const Decimal kStepScaleFactorMonth;
static const Decimal kStepScaleFactorWeek;
// Default step base value when a type do not have specific one.
static const Decimal kDefaultStepBase;
// Default step base value when type=week does not not have a specific one,
// which is 259200000, the start of week 1970-W01.
static const Decimal kDefaultStepBaseWeek;
// Default step used when there is no specified step.
static const Decimal kDefaultStep;

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

@ -254,10 +254,62 @@ function error3(event) {
}
function begin() {
addFullscreenChangeContinuation("enter", enter1);
fullScreenElement().requestFullscreen();
testNamespaces(() => {
addFullscreenChangeContinuation("enter", enter1);
fullScreenElement().requestFullscreen();
});
}
function testNamespaces(followupTestFn) {
let tests = [
{allowed: false, name: "element", ns: "http://www.w3.org/XML/1998/namespace"},
{allowed: false, name: "element", ns: "http://www.w3.org/1999/xlink"},
{allowed: false, name: "element", ns: "http://www.w3.org/2000/svg"},
{allowed: false, name: "element", ns: "http://www.w3.org/1998/Math/MathML"},
{allowed: false, name: "mathml", ns: "unknown"},
{allowed: false, name: "svg", ns: "unknown"},
{allowed: true, name: "element", ns: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"},
{allowed: true, name: "element", ns: "http://www.w3.org/1999/xhtml"},
{allowed: true, name: "svg", ns: "http://www.w3.org/1999/xhtml"},
{allowed: true, name: "math", ns: "http://www.w3.org/1999/xhtml"},
{allowed: true, name: "svg", ns: "http://www.w3.org/2000/svg"},
{allowed: true, name: "math", ns: "http://www.w3.org/1998/Math/MathML"},
{allowed: true, name: "element"},
];
function runNextNamespaceTest() {
let test = tests.shift();
if (!test) {
followupTestFn();
return;
}
let elem = test.ns ? document.createElementNS(test.ns, test.name) :
document.createElement(test.name);
document.body.appendChild(elem);
if (test.allowed) {
addFullscreenChangeContinuation("enter", () => {
ok(document.fullscreen, "Document should be in fullscreen");
is(document.fullscreenElement, elem,
`Element named '${test.name}' in this namespace should be allowed: ${test.ns}`);
addFullscreenChangeContinuation("exit", runNextNamespaceTest);
document.body.removeChild(elem);
});
} else {
addFullscreenErrorContinuation(() => {
ok(!document.fullscreenElement,
`Element named '${test.name}' in this namespace should not be allowed: ${test.ns}`);
document.body.removeChild(elem);
runNextNamespaceTest();
});
}
elem.requestFullscreen();
}
runNextNamespaceTest();
}
</script>
</pre>
<div id="full-screen-element"></div>

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

@ -17,8 +17,8 @@
href="https://bugzilla.mozilla.org/show_bug.cgi?id=73503">
Mozilla Bug 735031</a>
<svg width="100" height="100" viewbox="0 0 100 100">
<rect id="svg-elem" x="10" y="10" width="50" height="50"
<svg id="svg-elem" width="100" height="100" viewbox="0 0 100 100">
<rect x="10" y="10" width="50" height="50"
fill="black" stroke="blue" stroke-width="2"/>
</svg>

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

@ -30,8 +30,7 @@ var data = [
{ type: 'datetime', apply: true, todo: true },
{ type: 'date', apply: true },
{ type: 'month', apply: true },
// TODO: temporary set to false until bug 888316 is fixed.
{ type: 'week', apply: false },
{ type: 'week', apply: true },
{ type: 'time', apply: true },
{ type: 'datetime-local', apply: true, todo: true },
{ type: 'number', apply: true },
@ -840,7 +839,115 @@ for (var test of data) {
break;
case 'week':
// TODO: this is temporary until bug 888316 is fixed.
// When step is invalid, every week is valid
input.step = 0;
input.value = '2016-W30';
checkValidity(input, true, apply);
input.step = 'foo';
input.value = '1970-W01';
checkValidity(input, true, apply);
input.step = '-1';
input.value = '1970-W01';
checkValidity(input, true, apply);
input.removeAttribute('step');
input.value = '1500-W01';
checkValidity(input, true, apply);
input.step = 'any';
input.value = '1966-W52';
checkValidity(input, true, apply);
input.step = 'ANY';
input.value = '2013-W10';
checkValidity(input, true, apply);
// When min is set to a valid week, there is a step base.
input.min = '2000-W01';
input.step = '2';
input.value = '2000-W03';
checkValidity(input, true, apply);
input.value = '2000-W02';
checkValidity(input, false, apply, { low: "2000-W01", high: "2000-W03" });
input.min = '2012-W52';
input.value = '2013-W01';
checkValidity(input, false, apply, { low: "2012-W52", high: "2013-W02" });
input.min = '2010-W01';
input.step = '1.1';
input.value = '2010-W02';
checkValidity(input, true, apply);
input.min = '2010-W05';
input.step = '1.9';
input.value = '2010-W06';
checkValidity(input, false, apply, { low: "2010-W05", high: "2010-W07" });
// Without any step attribute the week is valid
input.removeAttribute('step');
checkValidity(input, true, apply);
input.min = '1950-W01';
input.step = '53';
input.value = '1951-W01';
checkValidity(input, false, apply, { low: "1950-W01", high: "1951-W02" });
input.min = '1951-W01';
input.step = '52';
input.value = '1952-W01';
checkValidity(input, true, apply);
input.step = '0.9';
input.value = '1951-W02';
checkValidity(input, true, apply);
input.step = '1.5';
input.value = '1951-W04';
checkValidity(input, false, apply, { low: "1951-W03", high: "1951-W05" });
input.value = '1951-W20';
checkValidity(input, false, apply, { low: "1951-W19", high: "1951-W21" });
input.step = '300';
input.min= '1968-W01';
input.value = '1968-W05';
checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" });
input.value = '1971-W01';
checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" });
input.value = '1975-W01';
checkValidity(input, false, apply, { low: "1973-W40", high: "1979-W27" });
input.value = '1985-W14';
checkValidity(input, true, apply);
input.step = '2.1';
input.min = '1991-W01';
input.value = '1991-W01';
checkValidity(input, true, apply);
input.value = '1991-W02';
checkValidity(input, false, apply, { low: "1991-W01", high: "1991-W03" });
input.value = '1991-W03';
checkValidity(input, true, apply);
input.step = '2.1';
input.min = '1969-W52';
input.value = '1969-W52';
checkValidity(input, true, apply);
input.value = '1970-W01';
checkValidity(input, false, apply, { low: "1969-W52", high: "1970-W02" });
input.value = '1970-W02';
checkValidity(input, true, apply);
break;
default:
ok(false, "Implement the tests for <input type='" + test.type + " >");

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

@ -51,13 +51,13 @@ function checkAvailability()
["date", true],
["time", true],
["month", true],
["week", true],
["color", false],
];
var todoList =
[
["datetime", true],
["week", true],
["datetime-local", true],
];
@ -445,6 +445,70 @@ function checkStepDown()
[ '2016-01', 'AnY', null, null, 1, null, true ],
[ '2016-01', 'aNy', null, null, 1, null, true ],
]},
{ type: 'week', data: [
// Regular case.
[ '2016-W40', null, null, null, null, '2016-W39', false ],
// Argument testing.
[ '2016-W40', null, null, null, 1, '2016-W39', false ],
[ '2016-W40', null, null, null, 5, '2016-W35', false ],
[ '2016-W40', null, null, null, -1, '2016-W41', false ],
[ '2016-W40', null, null, null, 0, '2016-W40', false ],
// Week/Year wrapping.
[ '2016-W01', null, null, null, 1, '2015-W53', false ],
[ '1969-W02', null, null, null, 4, '1968-W50', false ],
[ '1969-W01', null, null, null, -52, '1970-W01', false ],
// Float values are rounded to integer (1.1 -> 1).
[ '2016-W40', null, null, null, 1.1, '2016-W39', false ],
[ '2016-W01', null, null, null, 1.9, '2015-W53', false ],
// With step values.
[ '2016-W03', '0.5', null, null, null, '2016-W02', false ],
[ '2016-W03', '2', null, null, null, '2016-W01', false ],
[ '2016-W03', '0.25', null, null, 4, '2015-W52', false ],
[ '2016-W52', '1.1', '2016-W01', null, 1, '2016-W51', false ],
[ '2016-W52', '1.1', '2016-W01', null, 2, '2016-W50', false ],
[ '2016-W52', '1.1', '2016-W01', null, 10, '2016-W42', false ],
[ '2016-W52', '1.1', '2016-W01', null, 52, '2016-W01', false ],
[ '1968-W52', '1.1', '1968-W01', null, 8, '1968-W44', false ],
// step = 0 isn't allowed (-> step = 1).
[ '2016-W02', '0', null, null, null, '2016-W01', false ],
// step < 0 isn't allowed (-> step = 1).
[ '2016-W02', '-1', null, null, null, '2016-W01', false ],
// step = NaN isn't allowed (-> step = 1).
[ '2016-W02', 'foo', null, null, null, '2016-W01', false ],
// Min values testing.
[ '2016-W03', '1', 'foo', null, 2, '2016-W01', false ],
[ '2016-W02', '1', '2016-01', null, null, '2016-W01', false ],
[ '2016-W01', '1', '2016-W01', null, null, '2016-W01', false ],
[ '2016-W01', '1', '2016-W01', null, 1, '2016-W01', false ],
[ '2016-W05', '3', '2016-W01', null, null, '2016-W04', false ],
[ '1969-W01', '5', '1969-W01', '1969-W02', null, '1969-W01', false ],
// Max values testing.
[ '2016-W02', '1', null, 'foo', null, '2016-W01', false ],
[ '2016-W02', null, null, '2016-W05', null, '2016-W01', false ],
[ '2016-W03', null, null, '2016-W03', null, '2016-W02', false ],
[ '2016-W07', null, null, '2016-W04', 4, '2016-W03', false ],
[ '2016-W07', '2', null, '2016-W04', 3, '2016-W01', false ],
// Step mismatch.
[ '2016-W04', '2', '2016-W01', null, null, '2016-W03', false ],
[ '2016-W06', '2', '2016-W01', null, 2, '2016-W03', false ],
[ '2016-W05', '2', '2016-W04', '2016-W08', null, '2016-W04', false ],
[ '1970-W04', '2', null, null, null, '1970-W02', false ],
[ '1970-W09', '3', null, null, null, '1970-W06', false ],
// Clamping.
[ '2016-W05', null, null, '2016-W01', null, '2016-W01', false ],
[ '1970-W05', '2', '1970-W02', '1970-W05', null, '1970-W04', false ],
[ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W01', false ],
[ '1970-W07', '5', '1969-W52', '1970-W10', 2, '1969-W52', false ],
[ '1970-W08', '3', '1970-W01', '1970-W07', 15, '1970-W01', false ],
[ '1970-W10', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ],
// value = "" (NaN).
[ '', null, null, null, null, '1970-W01', false ],
// With step = 'any'.
[ '2016-W01', 'any', null, null, 1, null, true ],
[ '2016-W01', 'ANY', null, null, 1, null, true ],
[ '2016-W01', 'AnY', null, null, 1, null, true ],
[ '2016-W01', 'aNy', null, null, 1, null, true ],
]},
];
for (var test of testData) {
@ -829,6 +893,71 @@ function checkStepUp()
[ '2016-01', 'AnY', null, null, 1, null, true ],
[ '2016-01', 'aNy', null, null, 1, null, true ],
]},
{ type: 'week', data: [
// Regular case.
[ '2016-W40', null, null, null, null, '2016-W41', false ],
// Argument testing.
[ '2016-W40', null, null, null, 1, '2016-W41', false ],
[ '2016-W40', null, null, null, 20, '2017-W08', false ],
[ '2016-W40', null, null, null, -1, '2016-W39', false ],
[ '2016-W40', null, null, null, 0, '2016-W40', false ],
// Week/Year wrapping.
[ '2015-W53', null, null, null, 1, '2016-W01', false ],
[ '1968-W52', null, null, null, 4, '1969-W04', false ],
[ '1970-W01', null, null, null, -52, '1969-W01', false ],
// Float values are rounded to integer (1.1 -> 1).
[ '2016-W01', null, null, null, 1.1, '2016-W02', false ],
[ '2016-W01', null, null, null, 1.9, '2016-W02', false ],
// With step values.
[ '2016-W01', '0.5', null, null, null, '2016-W02', false ],
[ '2016-W01', '2', null, null, null, '2016-W03', false ],
[ '2016-W01', '0.25', null, null, 4, '2016-W05', false ],
[ '2016-W01', '1.1', '2016-01', null, 1, '2016-W02', false ],
[ '2016-W01', '1.1', '2016-01', null, 2, '2016-W03', false ],
[ '2016-W01', '1.1', '2016-01', null, 10, '2016-W11', false ],
[ '2016-W01', '1.1', '2016-01', null, 20, '2016-W21', false ],
// step = 0 isn't allowed (-> step = 1).
[ '2016-W01', '0', null, null, null, '2016-W02', false ],
// step < 0 isn't allowed (-> step = 1).
[ '2016-W01', '-1', null, null, null, '2016-W02', false ],
// step = NaN isn't allowed (-> step = 1).
[ '2016-W01', 'foo', null, null, null, '2016-W02', false ],
// Min values testing.
[ '2016-W01', '1', 'foo', null, null, '2016-W02', false ],
[ '2016-W01', null, '2015-W53', null, null, '2016-W02', false ],
[ '2016-W01', null, '2016-W02', null, null, '2016-W02', false ],
[ '2016-W01', null, '2016-W01', null, null, '2016-W02', false ],
[ '2016-W01', null, '2016-W04', null, 4, '2016-W05', false ],
[ '2016-W01', '2', '2016-W04', null, 3, '2016-W06', false ],
// Max values testing.
[ '2016-W01', '1', null, 'foo', 2, '2016-W03', false ],
[ '2016-W01', '1', null, '2016-W02', 1, '2016-W02', false ],
[ '2016-W02', null, null, '2016-W01', null, '2016-W02', false ],
[ '2016-W02', null, null, '2016-W02', null, '2016-W02', false ],
[ '1969-W02', '5', '1969-W01', '1969-W02', null, '1969-W02', false ],
// Step mismatch.
[ '2016-W02', '2', '2016-W01', null, null, '2016-W03', false ],
[ '2016-W02', '2', '2016-W01', null, 2, '2016-W05', false ],
[ '2016-W05', '2', '2016-W01', '2016-W06', null, '2016-W05', false ],
[ '1970-W02', '2', null, null, null, '1970-W04', false ],
[ '1970-W05', '3', null, null, null, '1970-W08', false ],
[ '1970-W03', '3', null, null, null, '1970-W06', false ],
[ '1970-W03', '3', '1970-W02', null, null, '1970-W05', false ],
// Clamping.
[ '2016-W01', null, '2016-W52', null, null, '2016-W52', false ],
[ '1970-W02', '2', '1970-W01', '1970-W04', null, '1970-W03', false ],
[ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W07', false ],
[ '1969-W50', '5', '1969-W52', '1970-W06', 3, '1970-W05', false ],
[ '1970-W01', '3', '1970-W02', '1971-W07', 15, '1970-W44', false ],
[ '1970-W01', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ],
// value = "" (NaN).
[ '', null, null, null, null, '1970-W02', false ],
// With step = 'any'.
[ '2016-W01', 'any', null, null, 1, null, true ],
[ '2016-W01', 'ANY', null, null, 1, null, true ],
[ '2016-W01', 'AnY', null, null, 1, null, true ],
[ '2016-W01', 'aNy', null, null, 1, null, true ],
]},
];
for (var test of testData) {

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

@ -71,6 +71,7 @@ FullscreenDeniedFocusedPlugin=Request for fullscreen was denied because a window
FullscreenDeniedHidden=Request for fullscreen was denied because the document is no longer visible.
FullscreenDeniedContainerNotAllowed=Request for fullscreen was denied because at least one of the documents containing elements is not an iframe or does not have an “allowfullscreen” attribute.
FullscreenDeniedNotInputDriven=Request for fullscreen was denied because Element.requestFullscreen() was not called from inside a short running user-generated event handler.
FullscreenDeniedNotHTMLSVGOrMathML=Request for fullscreen was denied because requesting element is not <svg>, <math>, or an HTML element.
FullscreenDeniedNotInDocument=Request for fullscreen was denied because requesting element is no longer in its document.
FullscreenDeniedMovedDocument=Request for fullscreen was denied because requesting element has moved document.
FullscreenDeniedLostWindow=Request for fullscreen was denied because we no longer have a window.

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

@ -575,8 +575,7 @@ PresentationConnection::DispatchMessageEvent(JS::Handle<JS::Value> aData)
return rv;
}
RefPtr<MessageEvent> messageEvent =
NS_NewDOMMessageEvent(this, nullptr, nullptr);
RefPtr<MessageEvent> messageEvent = new MessageEvent(this, nullptr, nullptr);
messageEvent->InitMessageEvent(nullptr,
NS_LITERAL_STRING("message"),

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

@ -51,6 +51,7 @@ static bool IsImageLoadInEditorAppType(nsILoadInfo* aLoadInfo)
nsContentPolicyType type = aLoadInfo->InternalContentPolicyType();
if (type != nsIContentPolicy::TYPE_INTERNAL_IMAGE &&
type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD &&
type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON &&
type != nsIContentPolicy::TYPE_IMAGESET) {
return false;
}

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

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

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

@ -0,0 +1,7 @@
[DEFAULT]
support-files =
favicon_bug1277803.ico
bug1277803.html
[test_bug1277803.xul]
skip-if = os == 'android'

Двоичные данные
dom/security/test/general/favicon_bug1277803.ico Normal file

Двоичный файл не отображается.

После

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

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

@ -0,0 +1,99 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Bug 1277803 test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="600"
height="600"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<script type="application/javascript"><![CDATA[
SimpleTest.requestCompleteLog();
let Ci = Components.interfaces;
let Cc = Components.classes;
let Cu = Components.utils;
let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
const BASE_URI = "http://mochi.test:8888/chrome/dom/security/test/general/";
const FAVICON_URI = BASE_URI + "favicon_bug1277803.ico";
const LOADING_URI = BASE_URI + "bug1277803.html";
let testWindow; //will be used to trigger favicon load
let securityManager = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
let expectedPrincipal = securityManager.createCodebasePrincipal(makeURI(LOADING_URI), {});
let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance();
// We expect 2 favicon loads, one from PlacesUIUtils.loadFavicon and one
// from XUL:image loads.
let requestXUL = false;
let requestPlaces = false;
function runTest() {
// Register our observer to intercept favicon requests.
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let observer = {
observe: function(aSubject, aTopic, aData)
{
// Make sure this is a favicon request.
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
if (FAVICON_URI != httpChannel.URI.spec) {
return;
}
// Ensure the topic is the one we set an observer for.
is(aTopic, "http-on-modify-request", "Expected observer topic");
// Check for the correct loadingPrincipal, triggeringPrincipal.
let triggeringPrincipal = httpChannel.loadInfo.triggeringPrincipal;
let loadingPrincipal = httpChannel.loadInfo.loadingPrincipal;
if (loadingPrincipal.equals(systemPrincipal)) {
// This is the favicon loading from XUL, which will have the system
// principal as its loading principal and have a content principal
// as its triggering principal.
ok(triggeringPrincipal.equals(expectedPrincipal),
"Correct triggeringPrincipal for favicon from XUL.");
requestXUL = true;
} else if (loadingPrincipal.equals(expectedPrincipal)) {
// This is the favicon loading from Places, which will have a
// content principal as its loading principal and triggering
// principal.
ok(triggeringPrincipal.equals(expectedPrincipal),
"Correct triggeringPrincipal for favicon from Places.");
requestPlaces = true;
} else {
ok(false, "An unexpected favicon request.")
}
// Cleanup after ourselves...
if (requestXUL && requestPlaces) {
os.removeObserver(this, "http-on-modify-request");
SimpleTest.finish();
}
}
}
os.addObserver(observer, "http-on-modify-request", false);
// Now that the observer is set up, trigger a favicon load with navigation
testWindow = window.open(LOADING_URI);
}
SimpleTest.waitForExplicitFinish();
SimpleTest.registerCleanupFunction(function() {
if (testWindow) {
testWindow.close();
}
});
]]></script>
<browser type="content-primary" flex="1" id="content" src="about:blank"/>
</window>

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

@ -22,6 +22,7 @@ MOCHITEST_MANIFESTS += [
MOCHITEST_CHROME_MANIFESTS += [
'csp/chrome.ini',
'general/chrome.ini',
]
BROWSER_CHROME_MANIFESTS += [

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

@ -18,8 +18,8 @@
Mozilla Bug 633602</a>
<p id="display"></p>
<svg width="100" height="100" viewbox="0 0 100 100">
<rect id="svg-elem" x="10" y="10" width="50" height="50"
<svg id="svg-elem" width="100" height="100" viewbox="0 0 100 100">
<rect x="10" y="10" width="50" height="50"
fill="black" stroke="blue" stroke-width="2"/>
</svg>

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

@ -70,7 +70,7 @@ AssembleClientData(const nsAString& aOrigin, const nsAString& aTyp,
}
if (NS_WARN_IF(!aClientData.Assign(NS_ConvertUTF16toUTF8(json)))) {
return NS_ERROR_FAILURE;
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
@ -246,7 +246,12 @@ U2FRegisterTask::Run()
}
MOZ_ASSERT(buffer);
regData.Assign(buffer, bufferlen);
if (NS_WARN_IF(!regData.Assign(buffer, bufferlen))) {
free(buffer);
ReturnError(ErrorCode::OTHER_ERROR);
return NS_ERROR_OUT_OF_MEMORY;
}
free(buffer);
registerSuccess = true;
break;
@ -424,7 +429,12 @@ U2FSignTask::Run()
}
MOZ_ASSERT(buffer);
signatureData.Assign(buffer, bufferlen);
if (NS_WARN_IF(!signatureData.Assign(buffer, bufferlen))) {
free(buffer);
ReturnError(ErrorCode::OTHER_ERROR);
return NS_ERROR_OUT_OF_MEMORY;
}
free(buffer);
signSuccess = true;
}

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

@ -18,7 +18,7 @@
var worker = new Worker("url_worker.js");
worker.onmessage = function(event) {
is(event.target, worker);
is(event.target, worker, "Correct worker");
if (event.data.type == 'finish') {
runTest();
@ -37,7 +37,7 @@
};
worker.onerror = function(event) {
is(event.target, worker);
is(event.target, worker, "Correct worker");
ok(false, "Worker had an error: " + event.message);
SimpleTest.finish();
};

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

@ -2668,7 +2668,6 @@ WorkerPrivateParent<Derived>::Thaw(nsPIDOMWindowInner* aWindow)
// Execute queued runnables before waking up the worker, otherwise the worker
// could post new messages before we run those that have been queued.
if (!IsParentWindowPaused() && !mQueuedRunnables.IsEmpty()) {
AssertIsOnMainThread();
MOZ_ASSERT(IsDedicatedWorker());
nsTArray<nsCOMPtr<nsIRunnable>> runnables;
@ -2720,7 +2719,6 @@ WorkerPrivateParent<Derived>::ParentWindowResumed()
// Execute queued runnables before waking up, otherwise the worker could post
// new messages before we run those that have been queued.
if (!IsFrozen() && !mQueuedRunnables.IsEmpty()) {
AssertIsOnMainThread();
MOZ_ASSERT(IsDedicatedWorker());
nsTArray<nsCOMPtr<nsIRunnable>> runnables;

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

@ -419,7 +419,7 @@ public:
void
QueueRunnable(nsIRunnable* aRunnable)
{
AssertIsOnMainThread();
AssertIsOnParentThread();
mQueuedRunnables.AppendElement(aRunnable);
}

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

@ -21,14 +21,15 @@
#include "mozilla/dom/VideoDecoderManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h"
#include "nsDebugImpl.h"
#include "mozilla/layers/LayerTreeOwnerTracker.h"
#include "ProcessUtils.h"
#include "nsDebugImpl.h"
#include "nsExceptionHandler.h"
#include "nsThreadManager.h"
#include "prenv.h"
#include "ProcessUtils.h"
#include "VRManager.h"
#include "VRManagerParent.h"
#include "VsyncBridgeParent.h"
#include "nsExceptionHandler.h"
#if defined(XP_WIN)
# include "DeviceManagerD3D9.h"
# include "mozilla/gfx/DeviceManagerDx.h"
@ -66,6 +67,13 @@ GPUParent::Init(base::ProcessId aParentPid,
MessageLoop* aIOLoop,
IPC::Channel* aChannel)
{
// Initialize the thread manager before starting IPC. Otherwise, messages
// may be posted to the main thread and we won't be able to process them.
if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
return false;
}
// Now it's safe to start IPC.
if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
return false;
}
@ -161,7 +169,7 @@ GPUParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
bool
GPUParent::RecvInitVsyncBridge(Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint)
{
VsyncBridgeParent::Start(Move(aVsyncEndpoint));
mVsyncBridge = VsyncBridgeParent::Start(Move(aVsyncEndpoint));
return true;
}
@ -317,6 +325,7 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
if (mVsyncBridge) {
mVsyncBridge->Shutdown();
mVsyncBridge = nullptr;
}
CompositorThreadHolder::Shutdown();
#if defined(XP_WIN)
@ -330,7 +339,6 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
#ifdef MOZ_CRASHREPORTER
CrashReporterClient::DestroySingleton();
#endif
NS_ShutdownXPCOM(nullptr);
XRE_ShutdownChildProcess();
}

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GPUProcessImpl.h"
#include "mozilla/ipc/IOThreadChild.h"
#include "nsXPCOM.h"
namespace mozilla {
namespace gfx {
@ -31,6 +32,7 @@ GPUProcessImpl::Init()
void
GPUProcessImpl::CleanUp()
{
NS_ShutdownXPCOM(nullptr);
}
} // namespace gfx

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

@ -55,10 +55,16 @@ VsyncBridgeParent::Shutdown()
{
MessageLoop* ccloop = CompositorThreadHolder::Loop();
if (MessageLoop::current() != ccloop) {
ccloop->PostTask(NewRunnableMethod(this, &VsyncBridgeParent::Shutdown));
ccloop->PostTask(NewRunnableMethod(this, &VsyncBridgeParent::ShutdownImpl));
return;
}
ShutdownImpl();
}
void
VsyncBridgeParent::ShutdownImpl()
{
if (mOpen) {
Close();
mOpen = false;

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

@ -30,6 +30,7 @@ private:
~VsyncBridgeParent();
void Open(Endpoint<PVsyncBridgeParent>&& aEndpoint);
void ShutdownImpl();
private:
bool mOpen;

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

@ -71,6 +71,7 @@ IPDL_SOURCES = [
LOCAL_INCLUDES += [
'/dom/ipc',
'/toolkit/crashreporter',
'/xpcom/threads',
]
include('/ipc/chromium/chromium-config.mozbuild')

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

@ -24,6 +24,7 @@
#include "mozilla/layers/PersistentBufferProvider.h"
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
#include "nsAString.h"
#include "nsDisplayList.h"
#include "nsIWidgetListener.h"
#include "nsTArray.h" // for AutoTArray
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
@ -275,13 +276,11 @@ ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags)
{
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization);
PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal",
js::ProfileEntry::Category::GRAPHICS);
if (!mForwarder || !mForwarder->IPCOpen()) {
return false;
}
#ifdef MOZ_LAYERS_HAVE_LOG
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
Log();
@ -356,6 +355,12 @@ ClientLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
if (!mForwarder->IPCOpen()) {
mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
mInTransaction = false;
return;
}
if (mWidget) {
mWidget->PrepareWindowEffects();
}
@ -381,9 +386,11 @@ ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
mInTransaction = false;
if (!mRoot) {
if (!mRoot || !mForwarder->IPCOpen()) {
mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
return false;
}
if (!EndTransactionInternal(nullptr, nullptr, aFlags)) {
// Return without calling ForwardTransaction. This leaves the
// ShadowLayerForwarder transaction open; the following

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

@ -743,14 +743,28 @@ NewImageChannel(nsIChannel** aResult,
nullptr, // loadGroup
callbacks,
aLoadFlags);
if (NS_FAILED(rv)) {
return rv;
}
if (aPolicyType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
// If this is a favicon loading, we will use the originAttributes from the
// loadingPrincipal as the channel's originAttributes. This allows the favicon
// loading from XUL will use the correct originAttributes.
NeckoOriginAttributes neckoAttrs;
neckoAttrs.InheritFromDocToNecko(BasePrincipal::Cast(aLoadingPrincipal)->OriginAttributesRef());
nsCOMPtr<nsILoadInfo> loadInfo = (*aResult)->GetLoadInfo();
rv = loadInfo->SetOriginAttributes(neckoAttrs);
}
} else {
// either we are loading something inside a document, in which case
// we should always have a requestingNode, or we are loading something
// outside a document, in which case the loadingPrincipal and
// triggeringPrincipal should always be the systemPrincipal.
// However, there are two exceptions: one is Notifications and the
// other one is Favicons which create a channel in the parent prcoess
// in which case we can't get a requestingNode.
// However, there are exceptions: one is Notifications which create a
// channel in the parent prcoess in which case we can't get a requestingNode.
rv = NS_NewChannel(aResult,
aURI,
nsContentUtils::GetSystemPrincipal(),

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

@ -250,9 +250,13 @@ UnixExceptionHandler(int signum, siginfo_t* info, void* context)
if (sPrevSEGVHandler.sa_flags & SA_SIGINFO)
sPrevSEGVHandler.sa_sigaction(signum, info, context);
else if (sPrevSEGVHandler.sa_handler == SIG_DFL || sPrevSEGVHandler.sa_handler == SIG_IGN)
raise(signum);
sigaction(SIGSEGV, &sPrevSEGVHandler, nullptr);
else
sPrevSEGVHandler.sa_handler(signum);
// If we reach here, we're returning to let the default signal handler deal
// with the exception. This is technically undefined behavior, but
// everything seems to do it, and it removes us from the crash stack.
}
bool
@ -266,7 +270,7 @@ MemoryProtectionExceptionHandler::install()
// Install our new exception handler and save the previous one.
struct sigaction faultHandler = {};
faultHandler.sa_flags = SA_SIGINFO;
faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER;
faultHandler.sa_sigaction = UnixExceptionHandler;
sigemptyset(&faultHandler.sa_mask);
sExceptionHandlerInstalled = !sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler);

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

@ -18,8 +18,20 @@ assertEq(f(0), 0);
setCachingEnabled(true);
// In order to allow following tests work on both big-endian and little-
// endian architectures we need to define least significant byte (lsb) and
// least significant word (lsw).
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
var lsb=0;
var lsw=0
if (f(0x12345678) == 0x12) {
lsb=3;
lsw=1;
}
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7f),0x7f);
assertEq(f(0xff),-1);
@ -27,7 +39,7 @@ assertEq(f(0x100),0);
{
var buf = new ArrayBuffer(BUF_MIN);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + '/* not a clone */ function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + '/* not a clone */ function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
var f = asmLink(code, this, null, buf);
assertEq(f(0),0);
assertEq(f(0x7f),0x7f);
@ -40,21 +52,21 @@ assertEq(f(0x100),0);
setCachingEnabled(false);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7f),0x7f);
assertEq(f(0xff),0xff);
assertEq(f(0x100),0);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i16[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i16[' + lsw + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7fff),0x7fff);
assertEq(f(0xffff),-1);
assertEq(f(0x10000),0);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u16[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u16[' + lsw + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7fff),0x7fff);
@ -75,14 +87,14 @@ assertEq(f(0x7fffffff),0x7fffffff);
assertEq(f(0xffffffff),-1);
assertEq(f(0x100000000),0);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7f),0x7f);
assertEq(f(0xff),-1);
assertEq(f(0x100),0);
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[0]|0}; return f');
var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f');
var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
assertEq(f(0),0);
assertEq(f(0x7f),0x7f);

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

@ -1,3 +1,10 @@
// getJitCompilerOptions will always return array with zeros when JIT is
// disabled. Therefore we quit now.
if (inJit() == 'Baseline is disabled.') {
print("JIT is disabled.");
quit();
}
var wait = 100;
var method_A = function() {

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

@ -14,6 +14,5 @@ var test = (function () {
try {
evalWithCache(test, {});
} catch (x) {
assertEq(x.message.includes("AsmJS"), true);
assertEq(x.message.includes("XDR"), true);
assertEq(x.message.includes("Asm.js is not supported by XDR"), true);
}

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

@ -55,7 +55,13 @@ class BufferPointer
return (T*)p;
}
T& operator*() const { return *get(); }
void set(const T& value) {
*get() = value;
}
// Note: we return a copy instead of a reference, to avoid potential memory
// safety hazards when the underlying buffer gets resized.
const T operator*() const { return *get(); }
T* operator->() const { return get(); }
};
@ -111,7 +117,7 @@ struct BaselineStackBuilder
js_free(buffer_);
}
bool init() {
MOZ_MUST_USE bool init() {
MOZ_ASSERT(!buffer_);
MOZ_ASSERT(bufferUsed_ == 0);
buffer_ = reinterpret_cast<uint8_t*>(js_calloc(bufferTotal_));
@ -136,7 +142,7 @@ struct BaselineStackBuilder
return true;
}
bool enlarge() {
MOZ_MUST_USE bool enlarge() {
MOZ_ASSERT(buffer_ != nullptr);
if (bufferTotal_ & mozilla::tl::MulOverflowMask<2>::value)
return false;
@ -176,7 +182,7 @@ struct BaselineStackBuilder
return framePushed_;
}
bool subtract(size_t size, const char* info = nullptr) {
MOZ_MUST_USE bool subtract(size_t size, const char* info = nullptr) {
// enlarge the buffer if need be.
while (size > bufferAvail_) {
if (!enlarge())
@ -197,7 +203,10 @@ struct BaselineStackBuilder
}
template <typename T>
bool write(const T& t) {
MOZ_MUST_USE bool write(const T& t) {
MOZ_ASSERT(!(uintptr_t(&t) >= uintptr_t(header_->copyStackBottom) &&
uintptr_t(&t) < uintptr_t(header_->copyStackTop)),
"Should not reference memory that can be freed");
if (!subtract(sizeof(T)))
return false;
memcpy(header_->copyStackBottom, &t, sizeof(T));
@ -205,7 +214,7 @@ struct BaselineStackBuilder
}
template <typename T>
bool writePtr(T* t, const char* info) {
MOZ_MUST_USE bool writePtr(T* t, const char* info) {
if (!write<T*>(t))
return false;
if (info)
@ -215,7 +224,7 @@ struct BaselineStackBuilder
return true;
}
bool writeWord(size_t w, const char* info) {
MOZ_MUST_USE bool writeWord(size_t w, const char* info) {
if (!write<size_t>(w))
return false;
if (info) {
@ -232,7 +241,7 @@ struct BaselineStackBuilder
return true;
}
bool writeValue(const Value& val, const char* info) {
MOZ_MUST_USE bool writeValue(const Value& val, const char* info) {
if (!write<Value>(val))
return false;
if (info) {
@ -244,7 +253,7 @@ struct BaselineStackBuilder
return true;
}
bool maybeWritePadding(size_t alignment, size_t after, const char* info) {
MOZ_MUST_USE bool maybeWritePadding(size_t alignment, size_t after, const char* info) {
MOZ_ASSERT(framePushed_ % sizeof(Value) == 0);
MOZ_ASSERT(after % sizeof(Value) == 0);
size_t offset = ComputeByteAlignment(after, alignment);
@ -430,7 +439,7 @@ class SnapshotIteratorForBailout : public SnapshotIterator
// Take previously computed result out of the activation, or compute the
// results of all recover instructions contained in the snapshot.
bool init(JSContext* cx) {
MOZ_MUST_USE bool init(JSContext* cx) {
// Under a bailout, there is no need to invalidate the frame after
// evaluating the recover instruction, as the invalidation is only
@ -758,7 +767,7 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
JitSpew(JitSpew_BaselineBailouts, " thisv=%016llx", *((uint64_t*) &thisv));
size_t thisvOffset = builder.framePushed() + JitFrameLayout::offsetOfThis();
*builder.valuePointerAtStackOffset(thisvOffset) = thisv;
builder.valuePointerAtStackOffset(thisvOffset).set(thisv);
MOZ_ASSERT(iter.numAllocations() >= CountArgSlots(script, fun));
JitSpew(JitSpew_BaselineBailouts, " frame slots %u, nargs %u, nfixed %u",
@ -781,7 +790,7 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
(int) i, *((uint64_t*) &arg));
if (callerPC) {
size_t argOffset = builder.framePushed() + JitFrameLayout::offsetOfActualArg(i);
*builder.valuePointerAtStackOffset(argOffset) = arg;
builder.valuePointerAtStackOffset(argOffset).set(arg);
} else {
startFrameFormals[i].set(arg);
}
@ -1061,12 +1070,18 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
// Push undefs onto the stack in anticipation of the popping of the
// callee, thisv, and actual arguments passed from the caller's frame.
if (isCall) {
builder.writeValue(UndefinedValue(), "CallOp FillerCallee");
builder.writeValue(UndefinedValue(), "CallOp FillerThis");
for (uint32_t i = 0; i < numCallArgs; i++)
builder.writeValue(UndefinedValue(), "CallOp FillerArg");
if (pushedNewTarget)
builder.writeValue(UndefinedValue(), "CallOp FillerNewTarget");
if (!builder.writeValue(UndefinedValue(), "CallOp FillerCallee"))
return false;
if (!builder.writeValue(UndefinedValue(), "CallOp FillerThis"))
return false;
for (uint32_t i = 0; i < numCallArgs; i++) {
if (!builder.writeValue(UndefinedValue(), "CallOp FillerArg"))
return false;
}
if (pushedNewTarget) {
if (!builder.writeValue(UndefinedValue(), "CallOp FillerNewTarget"))
return false;
}
frameSize += (numCallArgs + 2 + pushedNewTarget) * sizeof(Value);
blFrame->setFrameSize(frameSize);
@ -1276,7 +1291,8 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
size_t calleeSlot = valueSlot - actualArgc - 1 - pushedNewTarget;
for (size_t i = valueSlot; i > calleeSlot; i--) {
if (!builder.writeValue(*blFrame->valueSlot(i), "ArgVal"))
Value v = *blFrame->valueSlot(i);
if (!builder.writeValue(v, "ArgVal"))
return false;
}
@ -1372,7 +1388,9 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
if (pushedNewTarget) {
size_t newTargetOffset = (builder.framePushed() - endOfBaselineStubArgs) +
(actualArgc + 1) * sizeof(Value);
builder.writeValue(*builder.valuePointerAtStackOffset(newTargetOffset), "CopiedNewTarget");
Value newTargetValue = *builder.valuePointerAtStackOffset(newTargetOffset);
if (!builder.writeValue(newTargetValue, "CopiedNewTarget"))
return false;
}
// Push undefined for missing arguments.

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

@ -162,7 +162,6 @@ MSG_DEF(JSMSG_USER_DEFINED_ERROR, 0, JSEXN_ERR, "JS_ReportError was called"
// Internal errors
MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size overflow")
MSG_DEF(JSMSG_BAD_BUILD_ID, 0, JSEXN_INTERNALERR, "bad build ID for XDR script")
MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small")
MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE, 0, JSEXN_INTERNALERR, "build ID is not available")

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

@ -68,7 +68,8 @@ BEGIN_TEST(testSharedImmutableStringsCache)
for (auto i : mozilla::MakeRange(NUM_THREADS)) {
auto cacheAndIndex = js_new<CacheAndIndex>(&cache, i);
CHECK(cacheAndIndex);
threads.infallibleEmplaceBack(getString, cacheAndIndex);
threads.infallibleEmplaceBack();
CHECK(threads.back().init(getString, cacheAndIndex));
}
for (auto& thread : threads)

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

@ -77,7 +77,8 @@ BEGIN_TEST(testExclusiveData)
for (auto i : mozilla::MakeRange(NumThreads)) {
auto counterAndBit = js_new<CounterAndBit>(i, counter);
CHECK(counterAndBit);
CHECK(threads.emplaceBack(setBitAndCheck, counterAndBit));
CHECK(threads.emplaceBack());
CHECK(threads.back().init(setBitAndCheck, counterAndBit));
}
for (auto& thread : threads)

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

@ -18,7 +18,8 @@
BEGIN_TEST(testThreadingThreadJoin)
{
bool flag = false;
js::Thread thread([](bool* flagp){*flagp = true;}, &flag);
js::Thread thread;
CHECK(thread.init([](bool* flagp){*flagp = true;}, &flag));
CHECK(thread.joinable());
thread.join();
CHECK(flag);
@ -32,7 +33,8 @@ BEGIN_TEST(testThreadingThreadDetach)
// We are going to detach this thread. Unlike join, we can't have it pointing at the stack
// because it might do the write after we have returned and pushed a new frame.
bool* flag = js_new<bool>(false);
js::Thread thread([](bool* flag){*flag = true; js_delete(flag);}, mozilla::Move(flag));
js::Thread thread;
CHECK(thread.init([](bool* flag){*flag = true; js_delete(flag);}, mozilla::Move(flag)));
CHECK(thread.joinable());
thread.detach();
CHECK(!thread.joinable());
@ -43,7 +45,8 @@ END_TEST(testThreadingThreadDetach)
BEGIN_TEST(testThreadingThreadSetName)
{
js::Thread thread([](){js::ThisThread::SetName("JSAPI Test Thread");});
js::Thread thread;
CHECK(thread.init([](){js::ThisThread::SetName("JSAPI Test Thread");}));
thread.detach();
return true;
}
@ -53,7 +56,8 @@ BEGIN_TEST(testThreadingThreadId)
{
CHECK(js::Thread::Id() == js::Thread::Id());
js::Thread::Id fromOther;
js::Thread thread([](js::Thread::Id* idp){*idp = js::ThisThread::GetId();}, &fromOther);
js::Thread thread;
CHECK(thread.init([](js::Thread::Id* idp){*idp = js::ThisThread::GetId();}, &fromOther));
js::Thread::Id fromMain = thread.get_id();
thread.join();
CHECK(fromOther == fromMain);
@ -67,7 +71,8 @@ BEGIN_TEST(testThreadingThreadVectorMoveConstruct)
mozilla::Atomic<int> count(0);
mozilla::Vector<js::Thread, 0, js::SystemAllocPolicy> v;
for (auto i : mozilla::MakeRange(N)) {
CHECK(v.emplaceBack([](mozilla::Atomic<int>* countp){(*countp)++;}, &count));
CHECK(v.emplaceBack());
CHECK(v.back().init([](mozilla::Atomic<int>* countp){(*countp)++;}, &count));
CHECK(v.length() == i + 1);
}
for (auto& th : v)
@ -88,7 +93,8 @@ BEGIN_TEST(testThreadingThreadArgCopy)
{
for (size_t i = 0; i < 10000; ++i) {
bool b = true;
js::Thread thread([](bool bb){MOZ_RELEASE_ASSERT(bb);}, b);
js::Thread thread;
CHECK(thread.init([](bool bb){MOZ_RELEASE_ASSERT(bb);}, b));
b = false;
thread.join();
}

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

@ -26,13 +26,17 @@ FreezeThaw(JSContext* cx, JS::HandleScript script)
// freeze
uint32_t nbytes;
void* memory = JS_EncodeScript(cx, script, &nbytes);
if (!memory)
void* memory = nullptr;
TranscodeResult rs = JS_EncodeScript(cx, script, &nbytes, &memory);
if (rs != TranscodeResult_Ok)
return nullptr;
// thaw
JSScript* script2 = JS_DecodeScript(cx, memory, nbytes);
JS::RootedScript script2(cx);
rs = JS_DecodeScript(cx, memory, nbytes, &script2);
js_free(memory);
if (rs != TranscodeResult_Ok)
return nullptr;
return script2;
}

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

@ -6592,44 +6592,50 @@ JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
}
#endif /* JS_DEBUG */
JS_PUBLIC_API(void*)
JS_EncodeScript(JSContext* cx, HandleScript scriptArg, uint32_t* lengthp)
JS_PUBLIC_API(TranscodeResult)
JS_EncodeScript(JSContext* cx, HandleScript scriptArg,
uint32_t* lengthp, void** buffer)
{
XDREncoder encoder(cx);
RootedScript script(cx, scriptArg);
if (!encoder.codeScript(&script))
return nullptr;
return encoder.forgetData(lengthp);
*buffer = nullptr;
if (encoder.codeScript(&script))
*buffer = encoder.forgetData(lengthp);
MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
return encoder.resultCode();
}
JS_PUBLIC_API(void*)
JS_EncodeInterpretedFunction(JSContext* cx, HandleObject funobjArg, uint32_t* lengthp)
JS_PUBLIC_API(TranscodeResult)
JS_EncodeInterpretedFunction(JSContext* cx, HandleObject funobjArg,
uint32_t* lengthp, void** buffer)
{
XDREncoder encoder(cx);
RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
if (!encoder.codeFunction(&funobj))
return nullptr;
return encoder.forgetData(lengthp);
*buffer = nullptr;
if (encoder.codeFunction(&funobj))
*buffer = encoder.forgetData(lengthp);
MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
return encoder.resultCode();
}
JS_PUBLIC_API(JSScript*)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length)
JS_PUBLIC_API(TranscodeResult)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleScript scriptp)
{
XDRDecoder decoder(cx, data, length);
RootedScript script(cx);
if (!decoder.codeScript(&script))
return nullptr;
return script;
decoder.codeScript(scriptp);
MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
return decoder.resultCode();
}
JS_PUBLIC_API(JSObject*)
JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length)
JS_PUBLIC_API(TranscodeResult)
JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleFunction funp)
{
XDRDecoder decoder(cx, data, length);
RootedFunction funobj(cx);
if (!decoder.codeFunction(&funobj))
return nullptr;
return funobj;
decoder.codeFunction(funp);
MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok));
return decoder.resultCode();
}
JS_PUBLIC_API(void)

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

@ -5836,17 +5836,38 @@ class MOZ_RAII AutoHideScriptedCaller
* Encode/Decode interpreted scripts and functions to/from memory.
*/
extern JS_PUBLIC_API(void*)
JS_EncodeScript(JSContext* cx, JS::HandleScript script, uint32_t* lengthp);
enum TranscodeResult
{
// Successful encoding / decoding.
TranscodeResult_Ok = 0,
extern JS_PUBLIC_API(void*)
JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj, uint32_t* lengthp);
// A warning message, is set to the message out-param.
TranscodeResult_Failure = 0x100,
TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
TranscodeResult_Failure_UnknownClassKind = TranscodeResult_Failure | 0x4,
extern JS_PUBLIC_API(JSScript*)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length);
// A error, the JSContext has a pending exception.
TranscodeResult_Throw = 0x200
};
extern JS_PUBLIC_API(TranscodeResult)
JS_EncodeScript(JSContext* cx, JS::HandleScript script,
uint32_t* lengthp, void** buffer);
extern JS_PUBLIC_API(TranscodeResult)
JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj,
uint32_t* lengthp, void** buffer);
extern JS_PUBLIC_API(TranscodeResult)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleScript scriptp);
extern JS_PUBLIC_API(TranscodeResult)
JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleFunction funp);
extern JS_PUBLIC_API(JSObject*)
JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length);
namespace js {

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

@ -358,10 +358,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
if (!comp->creationOptions().cloneSingletons() ||
!comp->behaviors().getSingletonsAsTemplates())
{
JS_ReportErrorASCII(cx,
"Can't serialize a run-once non-function script "
"when we're not doing singleton cloning");
return false;
return xdr->fail(TranscodeResult_Failure_RunOnceNotSupported);
}
}
}
@ -795,8 +792,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
funEnclosingScope = function->nonLazyScript()->enclosingScope();
} else {
MOZ_ASSERT(function->isAsmJSNative());
JS_ReportErrorASCII(cx, "AsmJS modules are not yet supported in XDR serialization.");
return false;
return xdr->fail(TranscodeResult_Failure_AsmJSNotSupported);
}
funEnclosingScopeIndex = FindScopeIndex(script, *funEnclosingScope);
@ -831,7 +827,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
default: {
MOZ_ASSERT(false, "Unknown class kind.");
return false;
return xdr->fail(TranscodeResult_Failure_UnknownClassKind);
}
}
}

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

@ -1148,9 +1148,8 @@ CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
if (!JS::ToUint32(cx, args[2], &size))
return false;
sizeGiven = true;
if (offset > size) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
"2");
if (size == 0) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
}
@ -1168,7 +1167,7 @@ CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
JS_ReportErrorASCII(cx, "Unable to stat file");
return false;
}
if (st.st_size < off_t(offset)) {
if (off_t(offset) >= st.st_size) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_ARG_INDEX_OUT_OF_RANGE, "2");
return false;
@ -1511,6 +1510,42 @@ CacheEntry_setBytecode(JSContext* cx, HandleObject cache, uint8_t* buffer, uint3
return true;
}
static bool
ConvertTranscodeResultToJSException(JSContext* cx, TranscodeResult rv)
{
switch (rv) {
case TranscodeResult_Ok:
return true;
default:
MOZ_FALLTHROUGH;
case TranscodeResult_Failure:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "generic warning");
return false;
case TranscodeResult_Failure_BadBuildId:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "the build-id does not match");
return false;
case TranscodeResult_Failure_RunOnceNotSupported:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "run-once script are not supported by XDR");
return false;
case TranscodeResult_Failure_AsmJSNotSupported:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "Asm.js is not supported by XDR");
return false;
case TranscodeResult_Failure_UnknownClassKind:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "Unknown class kind, go fix it.");
return false;
case TranscodeResult_Throw:
MOZ_ASSERT(cx->isExceptionPending());
return false;
}
}
static bool
Evaluate(JSContext* cx, unsigned argc, Value* vp)
{
@ -1656,7 +1691,9 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
}
if (loadBytecode) {
script = JS_DecodeScript(cx, loadBuffer, loadLength);
TranscodeResult rv = JS_DecodeScript(cx, loadBuffer, loadLength, &script);
if (!ConvertTranscodeResultToJSException(cx, rv))
return false;
} else {
mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
(void) JS::Compile(cx, options, chars.start().get(), chars.length(), &script);
@ -1705,8 +1742,9 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
}
if (saveBytecode) {
saveBuffer = reinterpret_cast<uint8_t*>(JS_EncodeScript(cx, script, &saveLength));
if (!saveBuffer)
TranscodeResult rv = JS_EncodeScript(cx, script, &saveLength,
reinterpret_cast<void**>(&saveBuffer.rwget()));
if (!ConvertTranscodeResultToJSException(cx, rv))
return false;
}
}
@ -3533,7 +3571,10 @@ ScheduleWatchdog(JSContext* cx, double t)
LockGuard<Mutex> guard(sc->watchdogLock);
if (!sc->watchdogThread) {
MOZ_ASSERT(!sc->watchdogTimeout);
sc->watchdogThread.emplace(WatchdogMain, cx);
sc->watchdogThread.emplace();
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!sc->watchdogThread->init(WatchdogMain, cx))
oomUnsafe.crash("watchdogThread.init");
} else if (!sc->watchdogTimeout || timeout < sc->watchdogTimeout.value()) {
sc->watchdogWakeup.notify_one();
}

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

@ -99,20 +99,12 @@ public:
, options_(mozilla::Forward<O>(options))
{ }
// Start a thread of execution at functor |f| with parameters |args|. Note
// that the arguments must be either POD or rvalue references (mozilla::Move).
// Attempting to pass a reference will result in the value being copied, which
// may not be the intended behavior. See the comment below on
// ThreadTrampoline::args for an explanation.
template <typename F, typename... Args>
explicit Thread(F&& f, Args&&... args) {
MOZ_RELEASE_ASSERT(init(mozilla::Forward<F>(f),
mozilla::Forward<Args>(args)...));
}
// Start a thread of execution at functor |f| with parameters |args|. This
// method will return false if thread creation fails. This Thread must not
// already have been created.
// already have been created. Note that the arguments must be either POD or
// rvalue references (mozilla::Move). Attempting to pass a reference will
// result in the value being copied, which may not be the intended behavior.
// See the comment below on ThreadTrampoline::args for an explanation.
template <typename F, typename... Args>
MOZ_MUST_USE bool init(F&& f, Args&&... args) {
MOZ_RELEASE_ASSERT(!joinable());

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

@ -58,6 +58,16 @@ XDRBuffer::grow(size_t n)
return true;
}
template<XDRMode mode>
void
XDRState<mode>::postProcessContextErrors(JSContext* cx)
{
if (cx->isExceptionPending()) {
MOZ_ASSERT(resultCode_ == TranscodeResult_Ok);
resultCode_ = TranscodeResult_Throw;
}
}
template<XDRMode mode>
bool
XDRState<mode>::codeChars(const Latin1Char* chars, size_t nchars)
@ -110,10 +120,8 @@ VersionCheck(XDRState<mode>* xdr)
if (!xdr->codeUint32(&buildIdLength))
return false;
if (mode == XDR_DECODE && buildIdLength != buildId.length()) {
JS_ReportErrorNumberASCII(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
return false;
}
if (mode == XDR_DECODE && buildIdLength != buildId.length())
return xdr->fail(TranscodeResult_Failure_BadBuildId);
if (mode == XDR_ENCODE) {
if (!xdr->codeBytes(buildId.begin(), buildIdLength))
@ -131,11 +139,9 @@ VersionCheck(XDRState<mode>* xdr)
if (!xdr->codeBytes(decodedBuildId.begin(), buildIdLength))
return false;
if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength)) {
// We do not provide binary compatibility with older scripts.
JS_ReportErrorNumberASCII(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
return false;
}
// We do not provide binary compatibility with older scripts.
if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
return xdr->fail(TranscodeResult_Failure_BadBuildId);
}
return true;
@ -143,18 +149,26 @@ VersionCheck(XDRState<mode>* xdr)
template<XDRMode mode>
bool
XDRState<mode>::codeFunction(MutableHandleFunction objp)
XDRState<mode>::codeFunction(MutableHandleFunction funp)
{
if (mode == XDR_DECODE)
objp.set(nullptr);
funp.set(nullptr);
else
MOZ_ASSERT(objp->nonLazyScript()->enclosingScope()->is<GlobalScope>());
MOZ_ASSERT(funp->nonLazyScript()->enclosingScope()->is<GlobalScope>());
if (!VersionCheck(this))
if (!VersionCheck(this)) {
postProcessContextErrors(cx());
return false;
}
RootedScope scope(cx(), &cx()->global()->emptyGlobalScope());
return XDRInterpretedFunction(this, scope, nullptr, objp);
if (!XDRInterpretedFunction(this, scope, nullptr, funp)) {
postProcessContextErrors(cx());
funp.set(nullptr);
return false;
}
return true;
}
template<XDRMode mode>
@ -166,10 +180,18 @@ XDRState<mode>::codeScript(MutableHandleScript scriptp)
else
MOZ_ASSERT(!scriptp->enclosingScope());
if (!VersionCheck(this))
if (!VersionCheck(this)) {
postProcessContextErrors(cx());
return false;
}
return XDRScript(this, nullptr, nullptr, nullptr, scriptp);
if (!XDRScript(this, nullptr, nullptr, nullptr, scriptp)) {
postProcessContextErrors(cx());
scriptp.set(nullptr);
return false;
}
return true;
}
template<XDRMode mode>

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

@ -79,16 +79,28 @@ template <XDRMode mode>
class XDRState {
public:
XDRBuffer buf;
TranscodeResult resultCode_;
protected:
explicit XDRState(JSContext* cx)
: buf(cx) { }
: buf(cx), resultCode_(TranscodeResult_Ok) { }
public:
JSContext* cx() const {
return buf.cx();
}
// Record logical failures of XDR.
void postProcessContextErrors(JSContext* cx);
TranscodeResult resultCode() const {
return resultCode_;
}
bool fail(TranscodeResult code) {
MOZ_ASSERT(resultCode_ == TranscodeResult_Ok);
resultCode_ = code;
return false;
}
bool codeUint8(uint8_t* n) {
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(sizeof *n);

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

@ -728,16 +728,26 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
// The script wasn't in the cache , so compile it now.
LOG(("Slow loading %s\n", nativePath.get()));
// Note - if mReuseLoaderGlobal is true, then we can't do lazy source,
// because we compile things as functions (rather than script), and lazy
// source isn't supported in that configuration. That's ok though,
// because we only do mReuseLoaderGlobal on b2g, where we invoke
// setDiscardSource(true) on the entire global.
// Use lazy source if both of these conditions hold:
//
// (1) mReuseLoaderGlobal is false. If mReuseLoaderGlobal is true, we
// can't do lazy source because we compile things as functions
// (rather than script), and lazy source isn't supported in that
// configuration. That's ok though, because we only do
// mReuseLoaderGlobal on b2g, where we invoke setDiscardSource(true)
// on the entire global.
//
// (2) We're using the startup cache. Non-lazy source + startup cache
// regresses installer size (due to source code stored in XDR
// encoded modules in omni.ja). Also, XDR decoding is relatively
// fast. Content processes don't use the startup cache, so we want
// them to use non-lazy source code to enable lazy parsing.
// See bug 1303754.
CompileOptions options(cx);
options.setNoScriptRval(mReuseLoaderGlobal ? false : true)
.setVersion(JSVERSION_LATEST)
.setFileAndLine(nativePath.get(), 1)
.setSourceIsLazy(!mReuseLoaderGlobal);
.setSourceIsLazy(!mReuseLoaderGlobal && !!cache);
if (realFile) {
#ifdef HAVE_PR_MEMMAP

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

@ -29,31 +29,24 @@ ReadCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
if (NS_FAILED(rv))
return rv; // don't warn since NOT_AVAILABLE is an ok error
scriptp.set(JS_DecodeScript(cx, buf.get(), len));
if (!scriptp)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
TranscodeResult code = JS_DecodeScript(cx, buf.get(), len, scriptp);
if (code == TranscodeResult_Ok)
return NS_OK;
if ((code & TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult
ReadCachedFunction(StartupCache* cache, nsACString& uri, JSContext* cx,
nsIPrincipal* systemPrincipal, JSFunction** functionp)
{
return NS_ERROR_FAILURE;
/* This doesn't actually work ...
nsAutoArrayPtr<char> buf;
uint32_t len;
nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
getter_Transfers(buf), &len);
if (NS_FAILED(rv))
return rv; // don't warn since NOT_AVAILABLE is an ok error
JSObject* obj = JS_DecodeInterpretedFunction(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nullptr);
if (!obj)
return NS_ERROR_OUT_OF_MEMORY;
JSFunction* function = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
*functionp = function;
return NS_OK;*/
// This doesn't actually work ...
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
@ -63,14 +56,17 @@ WriteCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
MOZ_ASSERT(JS_GetScriptPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
uint32_t size;
void* data = JS_EncodeScript(cx, script, &size);
if (!data) {
// JS_EncodeScript may have set a pending exception.
void* data = nullptr;
TranscodeResult code = JS_EncodeScript(cx, script, &size, &data);
if (code != TranscodeResult_Ok) {
if ((code & TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_FAILURE;
return NS_ERROR_OUT_OF_MEMORY;
}
MOZ_ASSERT(size);
MOZ_ASSERT(size && data);
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
js_free(data);
return rv;
@ -80,19 +76,6 @@ nsresult
WriteCachedFunction(StartupCache* cache, nsACString& uri, JSContext* cx,
nsIPrincipal* systemPrincipal, JSFunction* function)
{
return NS_ERROR_FAILURE;
/* This doesn't actually work ...
uint32_t size;
void* data =
JS_EncodeInterpretedFunction(cx, JS_GetFunctionObject(function), &size);
if (!data) {
// JS_EncodeInterpretedFunction may have set a pending exception.
JS_ClearPendingException(cx);
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(size);
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
js_free(data);
return rv;*/
// This doesn't actually work ...
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -1091,17 +1091,24 @@ WriteScriptOrFunction(nsIObjectOutputStream* stream, JSContext* cx,
uint32_t size;
void* data;
void* data = nullptr;
TranscodeResult code;
{
if (functionObj)
data = JS_EncodeInterpretedFunction(cx, functionObj, &size);
code = JS_EncodeInterpretedFunction(cx, functionObj, &size, &data);
else
data = JS_EncodeScript(cx, script, &size);
code = JS_EncodeScript(cx, script, &size, &data);
}
if (!data)
if (code != TranscodeResult_Ok) {
if ((code & TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
MOZ_ASSERT(size);
}
MOZ_ASSERT(size && data);
rv = stream->Write32(size);
if (NS_SUCCEEDED(rv))
rv = stream->WriteBytes(static_cast<char*>(data), size);
@ -1139,18 +1146,25 @@ ReadScriptOrFunction(nsIObjectInputStream* stream, JSContext* cx,
return rv;
{
TranscodeResult code;
if (scriptp) {
JSScript* script = JS_DecodeScript(cx, data, size);
if (!script)
rv = NS_ERROR_OUT_OF_MEMORY;
else
*scriptp = script;
Rooted<JSScript*> script(cx);
code = JS_DecodeScript(cx, data, size, &script);
if (code == TranscodeResult_Ok)
*scriptp = script.get();
} else {
JSObject* funobj = JS_DecodeInterpretedFunction(cx, data, size);
if (!funobj)
rv = NS_ERROR_OUT_OF_MEMORY;
else
*functionObjp = funobj;
Rooted<JSFunction*> funobj(cx);
code = JS_DecodeInterpretedFunction(cx, data, size, &funobj);
if (code == TranscodeResult_Ok)
*functionObjp = JS_GetFunctionObject(funobj.get());
}
if (code != TranscodeResult_Ok) {
if ((code & TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
}

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

@ -61,8 +61,10 @@
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/PendingAnimationTracker.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/gfx/gfxVars.h"
#include "ActiveLayerTracker.h"
#include "nsContentUtils.h"
#include "nsPrintfCString.h"
@ -1811,9 +1813,14 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
ContainerLayerParameters containerParameters
(presShell->GetResolution(), presShell->GetResolution());
RefPtr<ContainerLayer> root = layerBuilder->
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
containerParameters, nullptr);
RefPtr<ContainerLayer> root;
{
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
root = layerBuilder->
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
containerParameters, nullptr);
}
nsIDocument* document = presShell->GetDocument();
@ -7105,3 +7112,106 @@ nsDisplayFilter::PrintEffects(nsACString& aTo)
aTo += ")";
}
#endif
namespace mozilla {
uint32_t PaintTelemetry::sPaintLevel = 0;
uint32_t PaintTelemetry::sMetricLevel = 0;
EnumeratedArray<PaintTelemetry::Metric,
PaintTelemetry::Metric::COUNT,
double> PaintTelemetry::sMetrics;
PaintTelemetry::AutoRecordPaint::AutoRecordPaint()
{
// Don't record nested paints.
if (sPaintLevel++ > 0) {
return;
}
// Reset metrics for a new paint.
for (auto& metric : sMetrics) {
metric = 0.0;
}
mStart = TimeStamp::Now();
}
PaintTelemetry::AutoRecordPaint::~AutoRecordPaint()
{
MOZ_ASSERT(sPaintLevel != 0);
if (--sPaintLevel > 0) {
return;
}
// If we're in multi-process mode, don't include paint times for the parent
// process.
if (gfxVars::BrowserTabsRemoteAutostart() && XRE_IsParentProcess()) {
return;
}
double totalMs = (TimeStamp::Now() - mStart).ToMilliseconds();
// Record the total time.
Telemetry::Accumulate(Telemetry::CONTENT_PAINT_TIME, static_cast<uint32_t>(totalMs));
// If the total time was >= 16ms, then it's likely we missed a frame due to
// painting. In this case we'll gather some detailed metrics below.
if (totalMs <= 16.0) {
return;
}
auto record = [=](const char* aKey, double aDurationMs) -> void {
MOZ_ASSERT(aDurationMs <= totalMs);
uint32_t amount = static_cast<int32_t>((aDurationMs / totalMs) * 100.0);
nsDependentCString key(aKey);
Telemetry::Accumulate(Telemetry::CONTENT_LARGE_PAINT_PHASE_WEIGHT, key, amount);
};
double dlMs = sMetrics[Metric::DisplayList];
double flbMs = sMetrics[Metric::Layerization];
double rMs = sMetrics[Metric::Rasterization];
// Record all permutations since aggregation makes it difficult to
// correlate. For example we can't derive "flb+r" from "dl" because we
// don't know the total time associated with a bucket entry. So we just
// play it safe and include everything. We can however derive "other" time
// from the final permutation.
record("dl", dlMs);
record("flb", flbMs);
record("r", rMs);
record("dl,flb", dlMs + flbMs);
record("dl,r", dlMs + rMs);
record("flb,r", flbMs + rMs);
record("dl,flb,r", dlMs + flbMs + rMs);
}
PaintTelemetry::AutoRecord::AutoRecord(Metric aMetric)
: mMetric(aMetric)
{
// Don't double-record anything nested.
if (sMetricLevel++ > 0) {
return;
}
// Don't record inside nested paints, or outside of paints.
if (sPaintLevel != 1) {
return;
}
mStart = TimeStamp::Now();
}
PaintTelemetry::AutoRecord::~AutoRecord()
{
MOZ_ASSERT(sMetricLevel != 0);
sMetricLevel--;
if (mStart.IsNull()) {
return;
}
sMetrics[mMetric] += (TimeStamp::Now() - mStart).ToMilliseconds();
}
} // namespace mozilla

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

@ -28,8 +28,10 @@
#include "DisplayListClipState.h"
#include "LayerState.h"
#include "FrameMetrics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/gfx/UserData.h"
#include <stdint.h>
@ -4471,4 +4473,43 @@ public:
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
namespace mozilla {
class PaintTelemetry
{
public:
enum class Metric {
DisplayList,
Layerization,
Rasterization,
COUNT,
};
class AutoRecord
{
public:
explicit AutoRecord(Metric aMetric);
~AutoRecord();
private:
Metric mMetric;
mozilla::TimeStamp mStart;
};
class AutoRecordPaint
{
public:
AutoRecordPaint();
~AutoRecordPaint();
private:
mozilla::TimeStamp mStart;
};
private:
static uint32_t sPaintLevel;
static uint32_t sMetricLevel;
static mozilla::EnumeratedArray<Metric, Metric::COUNT, double> sMetrics;
};
} // namespace mozilla
#endif /*NSDISPLAYLIST_H_*/

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

@ -3522,6 +3522,8 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList",
js::ProfileEntry::Category::GRAPHICS);
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::DisplayList);
aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
}
@ -3634,8 +3636,8 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
}
TimeStamp paintStart = TimeStamp::Now();
RefPtr<LayerManager> layerManager =
list.PaintRoot(&builder, aRenderingContext, flags);
RefPtr<LayerManager> layerManager
= list.PaintRoot(&builder, aRenderingContext, flags);
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME,
paintStart);

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

@ -987,7 +987,7 @@ nsPresContext::DetachShell()
mRestyleManager->Disconnect();
mRestyleManager = nullptr;
}
if (mRefreshDriver && mRefreshDriver->PresContext() == this) {
if (mRefreshDriver && mRefreshDriver->GetPresContext() == this) {
mRefreshDriver->Disconnect();
// Can't null out the refresh driver here.
}

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

@ -134,7 +134,8 @@ class nsRootPresContext;
// An interface for presentation contexts. Presentation contexts are
// objects that provide an outer context for a presentation shell.
class nsPresContext : public nsIObserver {
class nsPresContext : public nsIObserver,
public mozilla::SupportsWeakPtr<nsPresContext> {
public:
typedef mozilla::FramePropertyTable FramePropertyTable;
typedef mozilla::LangGroupFontPrefs LangGroupFontPrefs;
@ -145,6 +146,7 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
NS_DECL_CYCLE_COLLECTION_CLASS(nsPresContext)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsPresContext)
enum nsPresContextType {
eContext_Galley, // unpaginated screen presentation

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

@ -1295,7 +1295,7 @@ PresShell::Destroy()
mHiddenInvalidationObserverRefreshDriver->RemovePresShellToInvalidateIfHidden(this);
}
if (rd->PresContext() == GetPresContext()) {
if (rd->GetPresContext() == GetPresContext()) {
rd->RevokeViewManagerFlush();
}
@ -8997,7 +8997,7 @@ PresShell::Freeze()
nsPresContext* presContext = GetPresContext();
if (presContext &&
presContext->RefreshDriver()->PresContext() == presContext) {
presContext->RefreshDriver()->GetPresContext() == presContext) {
presContext->RefreshDriver()->Freeze();
}
@ -9055,7 +9055,7 @@ PresShell::Thaw()
{
nsPresContext* presContext = GetPresContext();
if (presContext &&
presContext->RefreshDriver()->PresContext() == presContext) {
presContext->RefreshDriver()->GetPresContext() == presContext) {
presContext->RefreshDriver()->Thaw();
}
@ -10911,7 +10911,7 @@ PresShell::SetIsActive(bool aIsActive)
nsPresContext* presContext = GetPresContext();
if (presContext &&
presContext->RefreshDriver()->PresContext() == presContext) {
presContext->RefreshDriver()->GetPresContext() == presContext) {
presContext->RefreshDriver()->SetThrottled(!mIsActive);
}
@ -11142,7 +11142,7 @@ nsIPresShell::FontSizeInflationEnabled()
void
PresShell::PausePainting()
{
if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
if (GetPresContext()->RefreshDriver()->GetPresContext() != GetPresContext())
return;
mPaintingIsFrozen = true;
@ -11152,7 +11152,7 @@ PresShell::PausePainting()
void
PresShell::ResumePainting()
{
if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
if (GetPresContext()->RefreshDriver()->GetPresContext() != GetPresContext())
return;
mPaintingIsFrozen = false;

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

@ -68,6 +68,7 @@
#include "mozilla/TimelineConsumers.h"
#include "nsAnimationManager.h"
#include "nsIDOMEvent.h"
#include "nsDisplayList.h"
using namespace mozilla;
using namespace mozilla::widget;
@ -172,7 +173,8 @@ public:
NS_ASSERTION(mRootRefreshDrivers.Contains(aDriver), "RemoveRefreshDriver for a refresh driver that's not in the root refresh list!");
mRootRefreshDrivers.RemoveElement(aDriver);
} else {
nsPresContext* rootContext = aDriver->PresContext()->GetRootPresContext();
nsPresContext* pc = aDriver->GetPresContext();
nsPresContext* rootContext = pc ? pc->GetRootPresContext() : nullptr;
// During PresContext shutdown, we can't accurately detect
// if a root refresh driver exists or not. Therefore, we have to
// search and find out which list this driver exists in.
@ -226,7 +228,8 @@ protected:
bool IsRootRefreshDriver(nsRefreshDriver* aDriver)
{
nsPresContext* rootContext = aDriver->PresContext()->GetRootPresContext();
nsPresContext* pc = aDriver->GetPresContext();
nsPresContext* rootContext = pc ? pc->GetRootPresContext() : nullptr;
if (!rootContext) {
return false;
}
@ -1908,7 +1911,10 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mViewManagerFlushIsPending = false;
RefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager();
vm->ProcessPendingUpdates();
{
PaintTelemetry::AutoRecordPaint record;
vm->ProcessPendingUpdates();
}
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
@ -2096,7 +2102,8 @@ nsRefreshDriver::IsWaitingForPaint(mozilla::TimeStamp aTime)
// Try find the 'root' refresh driver for the current window and check
// if that is waiting for a paint.
nsPresContext *rootContext = PresContext()->GetRootPresContext();
nsPresContext* pc = GetPresContext();
nsPresContext* rootContext = pc ? pc->GetRootPresContext() : nullptr;
if (rootContext) {
nsRefreshDriver *rootRefresh = rootContext->RefreshDriver();
if (rootRefresh && rootRefresh != this) {

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

@ -14,7 +14,7 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/Vector.h"
#include "mozilla/WeakPtr.h"
#include "mozFlushType.h"
#include "nsTObserverArray.h"
#include "nsTArray.h"
@ -273,7 +273,7 @@ public:
/**
* Return the prescontext we were initialized with
*/
nsPresContext* PresContext() const { return mPresContext; }
nsPresContext* GetPresContext() const { return mPresContext; }
/**
* PBackgroundChild actor is created asynchronously in content process.
@ -381,8 +381,8 @@ private:
ProfilerBacktrace* mReflowCause;
ProfilerBacktrace* mStyleCause;
nsPresContext *mPresContext; // weak; pres context passed in constructor
// and unset in Disconnect
// nsPresContext passed in constructor and unset in Disconnect.
mozilla::WeakPtr<nsPresContext> mPresContext;
RefPtr<nsRefreshDriver> mRootRefresh;

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

@ -426,10 +426,13 @@ public:
SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) override
{
NS_ASSERTION(aListID == kPrincipalList, "unexpected frame list");
MOZ_ASSERT(aListID == kPrincipalList || aListID == kBackdropList,
"unexpected frame list");
nsBlockFrame::SetInitialChildList(aListID, aChildList);
// re-resolve our subtree to set any mathml-expected data
nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
if (aListID == kPrincipalList) {
// re-resolve our subtree to set any mathml-expected data
nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
}
}
virtual void

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

@ -1154,5 +1154,10 @@ function SendUpdateCanvasForEvent(event, contentRootElement)
#if REFTEST_B2G
OnInitialLoad();
#else
addEventListener("load", OnInitialLoad, true);
if (content.document.readyState == "complete") {
// load event has already fired for content, get started
OnInitialLoad();
} else {
addEventListener("load", OnInitialLoad, true);
}
#endif

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

@ -107,7 +107,6 @@ user_pref("browser.tabs.remote.autostart.2", false);
user_pref("startup.homepage_welcome_url", "");
user_pref("startup.homepage_welcome_url.additional", "");
user_pref("startup.homepage_override_url", "");
user_pref("browser.usedOnWindows10.introURL", "");
user_pref("media.gmp-manager.url.override", "http://localhost/dummy-gmp-manager.xml");
user_pref("media.gmp-manager.updateEnabled", false);

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

@ -48,6 +48,7 @@
#include "nsIContent.h"
#include "nsContentUtils.h"
#include "nsSerializationHelper.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/EventDispatcher.h"
@ -226,6 +227,29 @@ nsImageBoxFrame::UpdateImage()
if (mUseSrcAttr) {
nsIDocument* doc = mContent->GetComposedDoc();
if (doc) {
// Use the serialized loadingPrincipal from the image element. Fall back
// to mContent's principal (SystemPrincipal) if not available.
nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
nsCOMPtr<nsIPrincipal> loadingPrincipal = mContent->NodePrincipal();
nsAutoString imageLoadingPrincipal;
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
imageLoadingPrincipal);
if (!imageLoadingPrincipal.IsEmpty()) {
nsCOMPtr<nsISupports> serializedPrincipal;
NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal),
getter_AddRefs(serializedPrincipal));
loadingPrincipal = do_QueryInterface(serializedPrincipal);
if (loadingPrincipal) {
// Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
// indicating it's a favicon loading.
contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
} else {
// Fallback if the deserialization is failed.
loadingPrincipal = mContent->NodePrincipal();
}
}
nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
nsCOMPtr<nsIURI> uri;
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
@ -233,10 +257,11 @@ nsImageBoxFrame::UpdateImage()
doc,
baseURI);
if (uri) {
nsresult rv = nsContentUtils::LoadImage(uri, mContent, doc, mContent->NodePrincipal(),
nsresult rv = nsContentUtils::LoadImage(uri, mContent, doc, loadingPrincipal,
doc->GetDocumentURI(), doc->GetReferrerPolicy(),
mListener, mLoadFlags,
EmptyString(), getter_AddRefs(mImageRequest));
EmptyString(), getter_AddRefs(mImageRequest),
contentPolicyType);
if (NS_SUCCEEDED(rv) && mImageRequest) {
nsLayoutUtils::RegisterImageRequestIfAnimated(presContext,

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

@ -408,8 +408,13 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
// On mac, open menulist on either up/down arrow or space (w/o Cmd pressed)
if (!IsOpen() && ((keyEvent->mCharCode == ' ' && !keyEvent->IsMeta()) ||
(keyCode == NS_VK_UP || keyCode == NS_VK_DOWN))) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
OpenMenu(false);
// When pressing space, don't open the menu if performing an incremental search.
if (keyEvent->mCharCode != ' ' ||
!nsMenuPopupFrame::IsWithinIncrementalTime(keyEvent->mTime)) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
OpenMenu(false);
}
}
#else
// On other platforms, toggle menulist on unmodified F4 or Alt arrow

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

@ -61,6 +61,8 @@ using mozilla::dom::PopupBoxObject;
int8_t nsMenuPopupFrame::sDefaultLevelIsTop = -1;
DOMTimeStamp nsMenuPopupFrame::sLastKeyTime = 0;
// XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose:
// nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml
// need to find a good place to put them together.
@ -534,6 +536,11 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
if (mIsOpenChanged) {
mIsOpenChanged = false;
// Make sure the current selection in a menulist is visible.
if (IsMenuList() && mCurrentMenu) {
EnsureMenuItemIsVisible(mCurrentMenu);
}
#ifndef MOZ_WIDGET_GTK
// If the animate attribute is set to open, check for a transition and wait
// for it to finish before firing the popupshown event.
@ -2002,7 +2009,6 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction
bool isMenu = parentContent &&
!parentContent->NodeInfo()->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL);
static DOMTimeStamp lastKeyTime = 0;
DOMTimeStamp keyTime;
aKeyEvent->AsEvent()->GetTimeStamp(&keyTime);
@ -2027,12 +2033,11 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction
if (isMenu) {
// Menu supports only first-letter navigation
mIncrementalString = uniChar;
} else if (sTimeoutOfIncrementalSearch &&
keyTime - lastKeyTime > sTimeoutOfIncrementalSearch) {
} else if (IsWithinIncrementalTime(keyTime)) {
mIncrementalString.Append(uniChar);
} else {
// Interval too long, treat as new typing
mIncrementalString = uniChar;
} else {
mIncrementalString.Append(uniChar);
}
}
@ -2047,7 +2052,7 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction
stringLength = 1;
}
lastKeyTime = keyTime;
sLastKeyTime = keyTime;
// NOTE: If you crashed here due to a bogus |immediateParent| it is
// possible that the menu whose shortcut is being looked up has

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

@ -332,6 +332,9 @@ public:
nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction);
void ClearIncrementalString() { mIncrementalString.Truncate(); }
static bool IsWithinIncrementalTime(DOMTimeStamp time) {
return !sTimeoutOfIncrementalSearch || time - sLastKeyTime <= sTimeoutOfIncrementalSearch;
}
virtual nsIAtom* GetType() const override { return nsGkAtoms::menuPopupFrame; }
@ -616,6 +619,8 @@ protected:
static int8_t sDefaultLevelIsTop;
static DOMTimeStamp sLastKeyTime;
// If 0, never timed out. Otherwise, the value is in milliseconds.
static uint32_t sTimeoutOfIncrementalSearch;
}; // class nsMenuPopupFrame

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